DOMElement - Problem

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • DOMElement - Problem

    Ich habe folgendes Problem mit DOM-Objekten in PHP. Ich gebe ein DOM-Objekt über den return-Wert einer Funktion zurück und wenn ich danach darauf zugreife hat sich das DOMElement verändert. Folgenden Code einfach mal laufen lassen und die Aussage beobachten:

    PHP-Code:
    $domTree getHierarchy('produktrelease');
    $domTree->save('test.xml');


    function 
    getHierarchy($table) {
            global 
    $db;
            
            
    $domTree = new DOMDocument('1.0''iso-8859-1');
            
                
                
    $me $domTree->createElement($table);
                
    $parent _getHierarchy($domTree,$me);
                
    var_dump($parent);
                
                echo 
    'zurueck '.$parent->nodeName.'<br>';
                if (
    is_object($parent)) {
                    
    $parent->appendChild($me);
                    
    $domTree->appendChild($parent);
                }
                else {
                    
    $domTree->appendChild($me);
                }

            
            return 
    $domTree;
        }

    function 
    _getHierarchy($domTree$parent) {
            global 
    $db;

                
    $me getParent($parent->nodeName);
                if (
    $me) {
                    
    $meNode $domTree->createElement($me);
                    
    $parent _getHierarchy($domTree,$meNode);
                    if (
    $parent) {
                        
    var_dump($meNode);
                        echo 
    'returning '.$meNode->nodeName'<br>';
                        
    $parent->appendChild($meNode);
                        echo 
    'returning2 '.$meNode->nodeName'<br>';
                        
                        return 
    $meNode;        
                    }
                    else {
                        return 
    $meNode;
                    }
                }
                else {
                    return 
    null;    
                }
        
        }


        
        function 
    getParent($name) {
            if (
    $name == 'produktversion') return  'produktrelease';
            if (
    $name == 'produktreleaselizenz') return  'produktrelease';
            if (
    $name == 'produktrelease') return  'produkt';
            if (
    $name == 'produkt') return  'geschaeftsfeld';
            return 
    null;        
        } 
    Ausgegeben wird:
    object(DOMElement)#3 (0) {
    }
    returning produkt<br>returning2 produkt<br>NULL
    zurueck <br>
    Sorry, das der Code so lang ist, aber ich bekomme das Problem auch in keinem kleineren Beispiel reproduziert. Wenn man es im Debugger laufen lässt wird das Problem sehr deutlich. In der Funktion _getHierarchy() wird ein neues DOMElement erzeugt und man kann auf nodeNam zugreifen. Aber wenn das Objekt an die Hauptfunktion getHierarchy returned wird steht in nodeName der Name des Nodes nicht mehr drin...
    Ich brüte schon seit Stunden über dem Problem, sehe den Fehler aber nicht.

    Wäre über jede Hilfe dankbar!

    Herzliche Grüße,
    Daniel
    Zuletzt geändert von Daniel83; 15.06.2006, 18:25.

  • #2
    php4?

    schreib mal statt
    PHP-Code:
    function _getHierarchy($domTree$parent) { 
    PHP-Code:
    function &_getHierarchy($domTree$parent) { 

    Ein netter Guide zum übersichtlichen Schreiben von PHP/MySQL-Code!

    bei Klammersetzung bevorzuge ich jedoch die JavaCoding-Standards
    Wie man Fragen richtig stellt

    Kommentar


    • #3
      Ne php5.

      Daniel

      Zuletzt geändert von Daniel83; 14.06.2006, 15:30.

      Kommentar


      • #4
        ich kriege bei dem TestSkript nur folgende Ausgabe
        Code:
        NULL
        zurueck <br>
        sry, aber ohne vernünftiges Testskript kann und will ich dir nicht helfen. Setz einen vernünftigen Testcase auf, dann lass ich es durch meinen Debugger laufen

        Ein netter Guide zum übersichtlichen Schreiben von PHP/MySQL-Code!

        bei Klammersetzung bevorzuge ich jedoch die JavaCoding-Standards
        Wie man Fragen richtig stellt

        Kommentar


        • #5
          erste zeile im skript war falsch... ist jetzt korrigiert.

          Nochmal kurz zum eigentlichen Verständniss des Skript: getHierarchy ist die eigentliche Hauptfunktion, die von aussen aufgerufen wird und _getHierarchy ist die Rekursion. Die Funktion erstellt anhand der Funktion getParent einen DOM-Baum aller Vorfahren des der Funktion übergebenen Elements.

          Daniel
          Zuletzt geändert von Daniel83; 14.06.2006, 18:46.

          Kommentar


          • #6
            ich glaube dein Problem ist folgendes: Du versuchst in der Rekursion das aktuelle Node durch parent zu ersetzen und das aktuelle Node dann als Child an parent anzuhängen, nicht?
            Das scheint aber vom DomDocument aus nicht zu funktionieren ... wieso gehst du nicht zuerst nach ganz oben in den Baum rein, und erstellst den Baum dann von oben? Bei deiner Lösung (sofern ich sie richtig verstanden habe) baust du den Baum von unten auf und probierst dann durch Verschiebung der Knoten die Parents zwischen root und Blatt zu packen

            Falls das nicht der Fall sein sollte, Beschreibe mal bitte genau, was die Funktion machen soll und wie die XML-Datei hinterher aussehen sollte

            Ein netter Guide zum übersichtlichen Schreiben von PHP/MySQL-Code!

            bei Klammersetzung bevorzuge ich jedoch die JavaCoding-Standards
            Wie man Fragen richtig stellt

            Kommentar


            • #7
              Ne, die Hierarchie wird schon so aufgebaut wie du gesagt hast. Von der Wurzel aus werden die Kinder angehängt, auch wenn die Rekursion von den Kindern aus startet...

              Aber es geht auch nicht um das komplette Verständniss des Algorithmus. Wenn man es durch den Debugger laufen lässt, dann sind eigentlich nur wenige Schritte genauer zu brachten. Und wird in der Funktion _getHierarchy in Zeile 11 ja $meNode->nodeName ausgegeben... und der Nodename wird auch wirklich ausgegeben. Zwei Zeilen später wird genau dieser Knoten über return zurückgegeben und man kommt zurück in die Funktion getHierarchie in Zeile 8. Der Knoten aus $meNode steht jetzt in $parent. Wenn ich zwei Zeilen tiefer jetzt aber $parent->nodeName abfrage, hat der Knoten auf einmal keinen Namen mehr, ob wohl es sich um das selbe Objekt wie vorher handelt. Wie konnte sich das Objekt verändern?

              Daniel
              P.S.: Hier nochmal der Code mit Markierungen an die wichtigen Stellen:
              PHP-Code:
              $domTree getHierarchy('produktrelease');
              $domTree->save('test.xml');


              function 
              getHierarchy($table) {
                      global 
              $db;
                      
                      
              $domTree = new DOMDocument('1.0''iso-8859-1');
                      
                          
                          
              $me $domTree->createElement($table);
                          
              $parent _getHierarchy($domTree,$me);
                          
              var_dump($parent);
                          
              //Hier ist der Name des Knotens verschwunden, obwohl es sich um das selbe Objekt handel
                          
              (2)-->echo 'zurueck '.$parent->nodeName.'<br>';
                          if (
              is_object($parent)) {
                              
              $parent->appendChild($me);
                              
              $domTree->appendChild($parent);
                          }
                          else {
                              
              $domTree->appendChild($me);
                          }

                      
                      return 
              $domTree;
                  }

              function 
              _getHierarchy($domTree$parent) {
                      global 
              $db;

                          
              $me getParent($parent->nodeName);
                          if (
              $me) {
                              
              $meNode $domTree->createElement($me);
                              
              $parent _getHierarchy($domTree,$meNode);
                              if (
              $parent) {
                                  
              var_dump($meNode);
                                  echo 
              'returning '.$meNode->nodeName'<br>';
                                  
              $parent->appendChild($meNode);
              // Hier wird der Name des Knotens noch korrekt ausgegeben                    
              (1)--->echo 'returning2 '.$meNode->nodeName'<br>';
                                  
                                  return 
              $meNode;        
                              }
                              else {
                                  return 
              $meNode;
                              }
                          }
                          else {
                              return 
              null;    
                          }
                  
                  }


                  
                  function 
              getParent($name) {
                      if (
              $name == 'produktversion') return  'produktrelease';
                      if (
              $name == 'produktreleaselizenz') return  'produktrelease';
                      if (
              $name == 'produktrelease') return  'produkt';
                      if (
              $name == 'produkt') return  'geschaeftsfeld';
                      return 
              null;        
                  } 
              Zuletzt geändert von Daniel83; 15.06.2006, 18:26.

              Kommentar


              • #8
                PHP-Code:
                <?php

                function _getHierarchy($domTree$parent) {
                    [...]
                    if (
                $parent) {
                        
                $parent->appendChild($meNode);
                    
                        return 
                $meNode// $meNode???
                    
                }
                    else {
                        return 
                $meNode;
                    }
                    [...]
                }
                ich würds mal mit
                PHP-Code:
                return $parent
                probieren

                Ein netter Guide zum übersichtlichen Schreiben von PHP/MySQL-Code!

                bei Klammersetzung bevorzuge ich jedoch die JavaCoding-Standards
                Wie man Fragen richtig stellt

                Kommentar


                • #9
                  nein, $meNode ist schon korrekt...
                  Aber darum geht es ja auch nicht, welcher Wert hätte zurückgegeben werden müssen um den Baum korrekt aufzubauen. Es geht einzig und alleine darum, dass innerhalb der _getHierarchy-Funktion das DOMElement in $meNode noch seinen korrekten Name $meNode->nodeName hat und nachdem das Objekt zurückgegeben wurde in der Hauptfunktion über $parent->nodeName der Name auf einmal nicht mehr ansprechbar ist. Einfach mal im Debugger Position (1) als Haltepunkt setzen und dann schrittweise gucken, was an Position (2) passiert...

                  Ich hoffe es war jetzt verständlich.

                  Daniel
                  Zuletzt geändert von Daniel83; 15.06.2006, 18:24.

                  Kommentar


                  • #10
                    Original geschrieben von Daniel83
                    Ich hoffe es war jetzt verständlich.
                    nein, ist es nicht. Wenn ich das Skript wie beschrieben ändere kriege ich einen Baum, bei deinem Skript kriege ich mit error_reporting(E_ALL) nur zwei Warnings um die Ohren gehauen.
                    Des weiteren hast du immer noch nicht verraten wie die fertige Ausgabe eigentlich aussehen soll ...
                    mit der Änderung gibt es
                    Code:
                    <?xml version="1.0" encoding="iso-8859-1"?>
                    <geschaeftsfeld><produkt/><produktrelease/></geschaeftsfeld>
                    zurück, ohne gibt es nix vernünftiges...

                    Das Problem ist kein Problem mit OOP oder der Übergabe, sondern ein Problem deiner Logik

                    Ein netter Guide zum übersichtlichen Schreiben von PHP/MySQL-Code!

                    bei Klammersetzung bevorzuge ich jedoch die JavaCoding-Standards
                    Wie man Fragen richtig stellt

                    Kommentar


                    • #11
                      Das Problem ist kein Problem mit OOP oder der Übergabe, sondern ein Problem deiner Logik [/B]
                      Anscheinend ja nicht... OK, nochmal langsam: Es geht nicht darum, was am Ende herauskommt. Was der Algorithmus macht ist absolut uninteressant! Es geht nur darum, was beim durchlaufen des Debuggers an den besagten Stellen passiert! Und zwar das ein Objekt von der Funktion _getHierarchie zurückgegeben wird (1) und in der aufrufenden Funktion das Objekt sich verändert hat (2).

                      Wer es durch den Debugger laufen lässt und sich die besagten Stellen genau anschaut, wie ich es oben mehrfach erklärt habe, wird sehen, was das Problem ist.

                      Daniel

                      Kommentar


                      • #12
                        Original geschrieben von Daniel83
                        Anscheinend ja nicht... OK, nochmal langsam: Es geht nicht darum, was am Ende herauskommt. Was der Algorithmus macht ist absolut uninteressant! Es geht nur darum, was beim durchlaufen des Debuggers an den besagten Stellen passiert! Und zwar das ein Objekt von der Funktion _getHierarchie zurückgegeben wird (1) und in der aufrufenden Funktion das Objekt sich verändert hat (2).

                        Wer es durch den Debugger laufen lässt und sich die besagten Stellen genau anschaut, wie ich es oben mehrfach erklärt habe, wird sehen, was das Problem ist.

                        Daniel
                        somit wären wir wieder bei dem Problem deiner Logik...
                        PHP-Code:
                        echo 'returning '.$meNode->nodeName'<br>';
                        $parent->appendChild($meNode); 
                        kommentiere die zweite Zeile mal aus. Auf einmal gibt es auch bei "zurueck" wieder einen nodeNamen. Mit der ultra komischen Version des Aufbau des Baumes, indem du $meNode an $parent anhängst, dann aber $parent ignorierst und nur $meNode wieder zurück gibst, bringst du irgendwie alles durcheinander.
                        Ich habe mal eine Grafik angehängt, die den Verlauf der Objekte wiederspiegelt. Die Zahlen am Anfang sind die Zeilennummern, wenn man deinen Code von allem für das Beispiel unnötigem, befreit (global $db, und die Ausgaben)
                        Ab Zeile 13 (getHierarchy
                        PHP-Code:
                        $parent->appendChild($me);
                        $domTree->appendChild($parent); 
                        ) gibt es Warnings, weil die Zeiger offensichtlich komisch gesetzt sind, denn von 30 an 13 wird nicht etwa der Zeiger auf "geschaeftsfeld" zurückgegeben, sondern statt dessen der Zeiger auf "produkt"
                        Du kannst nicht erwarten, dass ein komplett wirres Zeigerrumgespiele funktioniert, und wie man in meiner Grafik sieht, würde es nicht mal das gewünschte Ergebnis liefern, weil das Child vom DomTree produkt wäre, geschaeftsfeld hingegen ein parent ist, was eigentlich gar nicht existieren kann, weil da das Ende des Baumes ist...


                        Das, was du da komplett kompliziert mit deiner Rekursion aufgebaut hast, kann man abgesehen davon auch iterativ lösen, man spart sich 1/3 an Code und es ist auf einen Blick erkennbar, was der Code macht
                        PHP-Code:
                        <?php

                        $domTree 
                        getHierarchy('produktversion');
                        $domTree->save('test.xml');

                        function 
                        getHierarchy($node) {
                            
                        $ancestors = array($node);
                            
                        $act $node;
                            while (!
                        is_null($parent getParent($act))) {
                                
                        $ancestors[] = $parent;
                                
                        $act $parent;
                            }
                            
                        $ancestors array_reverse($ancestors);

                            
                        $domTree = new DOMDocument('1.0''iso-8859-1');
                            
                        $name array_shift($ancestors);
                            
                        $elem $domTree->createElement($name);
                            
                        $domTree->appendChild($elem);
                            foreach (
                        $ancestors as $value) {
                                
                        $elem2 $domTree->createElement($value);
                                
                        $elem $elem->appendChild($elem2);
                            }

                            return 
                        $domTree;
                        }

                        function 
                        getParent($name) {
                            if (
                        $name == 'produktversion') return  'produktrelease';
                            if (
                        $name == 'produktreleaselizenz') return  'produktrelease';
                            if (
                        $name == 'produktrelease') return  'produkt';
                            if (
                        $name == 'produkt') return  'geschaeftsfeld';
                            return 
                        null;
                        }
                        Ausgabe
                        Code:
                        <?xml version="1.0" encoding="iso-8859-1"?>
                        <geschaeftsfeld><produkt><produktrelease><produktversion/></produktrelease></produkt></geschaeftsfeld>
                        wovon ich mal einfach ausgehe, dass es korrekt ist.
                        Angehängte Dateien

                        Ein netter Guide zum übersichtlichen Schreiben von PHP/MySQL-Code!

                        bei Klammersetzung bevorzuge ich jedoch die JavaCoding-Standards
                        Wie man Fragen richtig stellt

                        Kommentar


                        • #13
                          Herrgott nochmal... ich denke wir brechen das hier mal ab. Du scheinst einfach nicht zu verstehen, dass der Algorithmus und was er wie macht überhaupt nicht Thema der Diskussion ist.
                          *closed*

                          Zuletzt geändert von Daniel83; 15.06.2006, 23:46.

                          Kommentar

                          Lädt...
                          X