Claudius L.: Verhalten von SimpleXML unklar

Guten Abend zusammen!

Ich habe noch nicht sonderlich viel Erfahrung mit OOP, sowohl im Zusammenhang mit PHP als auch allgemein. Allerdings bin ich bisher per „learning by doing“ ganz gut zurecht gekommen. Bisher …

Ich versuche, eine Klasse zu schreiben, die sich ähnlich wie die SimpleXML Klasse verhält (ähnlich, nicht gleich, darum bastle ich selbst). Dazu habe ich erstmal versucht, mir die SimpleXML Objekte möglichst genau anzuschauen, um zu verstehen, wie darin welche Daten gespeichert sind. Mit Hilfe von var_dump() soweit auch so gut. Jetzt bin ich aber auf ein Verhalten von SimpleXML gestoßen, das ich absolut nicht nachvollziehen kann. Darum bin ich mal wieder bei euch gelandet …

Ein Beispiel:

<root>  
 <elementA>  
  <elementB>Foo</elementB>  
  <elementB>Bar</elementB>  
 </elementA>  
</root>

Nach

$xml = simplexml_load_file(getcwd()."/test.xml");  
  
var_info($xml); // var_info() ist im Prinzip var_dump, gibt aber noch <pre> mit aus

ist das Ergebnis noch wie erwartet.
Mir unklar wird es erst, wenn ich jetzt noch Text direkt in elementA einfüge:

<root>  
 <elementA>ABC  
  <elementB>Foo</elementB>  
  <elementB>Bar</elementB>  
 </elementA>  
</root>

Denn dann ergibt der Dump folgendes:

object(SimpleXMLElement)#1 (1) {
  ["elementA"]=>
  string(11) "ABC

"
}

Um die Frage ganz direkt auf den Punkt zu bringen: Wo sind die beiden elementB geblieben? Noch mysteriöser ist für mich, dass echo $xml->elementA->elementB; immernoch „Foo“ ergibt, obwohl laut dem Dump elementB in dem Objekt doch garnicht existiert.

Oder, um meine Frage etwas anders zu formulieren: Wie kann es sein, dass echo $xml->elementA; „ABC“ ergibt – sich elementA also wie eine String-Variable innerhalb des Objekts $xml verhält – obwohl es zugleich doch offensichtlich selbst ein SimpleXML Objekt ist, da echo $xml->elementA->elementB; den Zugriff auf das erste elementB erlaubt?

So, ich hoffe, meinen Gedankengang (und seine Grenzen ;-)) einigermaßen klar dargestellt zu haben – und dass ihr wie gewohnt wunderprächtige Tipps und Hinweise für mich habt. Bin wie immer gespannt …

Viele Grüße,

Claudius

  1. Hi,

    <root>

    <elementA>ABC
      <elementB>Foo</elementB>
      <elementB>Bar</elementB>
    </elementA>
    </root>

    
    >   
    > Denn dann ergibt der Dump folgendes:  
    >   
    > object(SimpleXMLElement)#1 (1) {  
    >   ["elementA"]=>  
    >   string(11) "ABC  
    >   
    >   
    >  "  
    > }  
    >   
    > Um die Frage ganz direkt auf den Punkt zu bringen: Wo sind die beiden elementB geblieben? Noch mysteriöser ist für mich, dass `echo $xml->elementA->elementB;`{:.language-php} immernoch „Foo“ ergibt, obwohl laut dem Dump elementB in dem Objekt doch garnicht existiert.  
      
    Dann luegt der Dump eben :-)  
      
    
    > Oder, um meine Frage etwas anders zu formulieren: Wie kann es sein, dass `echo $xml->elementA;`{:.language-php} „ABC“ ergibt – sich elementA also wie eine String-Variable innerhalb des Objekts `$xml`{:.language-php} verhält – obwohl es zugleich doch offensichtlich selbst ein SimpleXML Objekt ist, da `echo $xml->elementA->elementB;`{:.language-php} den Zugriff auf das erste elementB erlaubt?  
      
    Wenn du ein komplexes Objekt, das nicht aus elementaren, "darstellbaren" Elementen (wie String, Number, ...) besteht, "ausgeben" willst, muss dafuer eine (interne) Methode aufgerufen werden, die es in einen Textstring umwandelt.  
    (Wenn du bspw. per echo ein Array ausgeben willst, dann bekommst du von PHP ja auch nur den Text "Array" ausgegeben).  
      
    Es ist durchaus denkbar, dass die Methode des SimpleXML-Element hier fehlerhaft arbeitet.  
      
    MfG ChrisB  
      
    
    -- 
    „This is the author's opinion, not necessarily that of Starbucks.“
    
  2. Hallo Claudius.

    Dieser Artikel und dieser Forumsbeitrag werden dir weiterhelfen.

    Servus,
    Flo

  3. echo $begrüßung;

    Mir unklar wird es erst, wenn ich jetzt noch Text direkt in elementA einfüge:

    <root>

    <elementA>ABC
      <elementB>Foo</elementB>
      <elementB>Bar</elementB>
    </elementA>
    </root>

    
    >   
    > Denn dann ergibt der Dump folgendes:  
    >   
    > object(SimpleXMLElement)#1 (1) {  
    >   ["elementA"]=>  
    >   string(11) "ABC  
    >   
    >   
    >  "  
    > }  
      
    Das Problem ist, dass elementA nun sowohl skalare Daten als auch Nodes enthält. Das kann man mit einer PHP-Variablen nicht so einfach abbilden. Als Ausweg könnte man ein Textnode-Objekt für das ABC zu verwenden. Dann könnte man statt des Strings ABC… ein Array oder Objekt simulieren (dazu später mehr), das sowohl Textnodes als auch XML-Nodes enthält. Stattdessen werden hier zur Stringdarstellung nur die reinen Textbestandteile außerhalb von XML-Elementen verwendet, also ABC, Zeilenumbrüche und Leerzeichen.  
      
    
    > Um die Frage ganz direkt auf den Punkt zu bringen: Wo sind die beiden elementB geblieben?  
      
    Ent-oder-weder. Text oder XML-Nodes. Beides gleichzeitig geht nicht. Jedenfalls nicht mit SimpleXML, das sich hier Textnode-Elemente spart.  
      
    Neben den allgemeinen OOP-Dingen ist unter PHP einige Magie zu beachten. Beschrieben ist diese im [PHP5-OOP-Kapitel](http://www.php.net/manual/en/language.oop5.php), speziell [Overloading](http://www.php.net/manual/en/language.oop5.overloading.php) und [Magic Methods](http://www.php.net/manual/en/language.oop5.magic.php). Außerdem spielt auch die [SPL](http://www.php.net/manual/en/book.spl.php) eine Rolle. Mit der man noch weitere Spielereien machen kann, die vom Standardverhalten abweichen.  
      
    In deinem Fall hat sich PHP oder SimpleXML entschieden, einen Stringkontext anzunehmen und für elementA \_\_toString() aufzurufen.  
      
    
    > Noch mysteriöser ist für mich, dass `echo $xml->elementA->elementB;`{:.language-php} immernoch „Foo“ ergibt, obwohl laut dem Dump elementB in dem Objekt doch garnicht existiert.  
      
    In dem Fall wird elementA nicht im Stringkontext befragt.  
      
    
    > Oder, um meine Frage etwas anders zu formulieren: Wie kann es sein, dass `echo $xml->elementA;`{:.language-php} „ABC“ ergibt – sich elementA also wie eine String-Variable innerhalb des Objekts `$xml`{:.language-php} verhält – obwohl es zugleich doch offensichtlich selbst ein SimpleXML Objekt ist, da `echo $xml->elementA->elementB;`{:.language-php} den Zugriff auf das erste elementB erlaubt?  
      
    Stringkontext oder nicht => \_\_toString() oder nicht.  
      
      
    echo "$verabschiedung $name";