William
William

Reputation: 986

Are SimpleXMLElement and SimpleXMLElement::children() the same thing?

Consider the following code:

<?php
$foo = new SimpleXmlElement(
'<foo>
    <bar>
        <baz id="b1"/>
        <baz id="b2"/>
        <baz id="b3"/>
    </bar>
</foo>
');
echo "<pre>";print_r($foo);echo "</pre><br/>";
echo "<pre>";print_r($foo->children());echo "</pre><br/>";
echo "foo===foo->children():".($foo===$foo->children()?"true":"false")."<br/>";//false
echo "foo==foo->children():".($foo==$foo->children()?"true":"false");//true

print_r shows the same content for foo and foo->children(). $foo==$foo->children() is true but $foo===$foo->children() is false. What the heck is $foo->children()?

The official document has a note that may be related to this question, but I cannot understand exactly its meaning.

Note: SimpleXML has made a rule of adding iterative properties to most methods. They cannot be viewed using var_dump() or anything else which can examine objects.

Upvotes: 1

Views: 100

Answers (2)

IMSoP
IMSoP

Reputation: 97728

Despite its name, instances of the SimpleXMLElement class can represent a few different things:

  • A single XML element; in your example, $foo represents the <foo> element at the root of your XML document
  • A collection of XML elements with the same name; for instance, $foo->bar gives you an object with all child elements named bar
  • A collection of XML elements with different names, but the same parent; this is what ->children() gives you
  • A single XML attribute; $foo->bar[0]->baz[0]['id'] will give you an object for the id attribute of the first baz in your example
  • A collection of XML attributes on the same element; this is what ->attributes() gives you

A lot of the time, you don't actually notice which of these you have, because various short-hands let you treat them interchangeably; for instance:

  • Property, method, and attribute calls on collections of elements and attributes generally refer to the first element in the collection. So $foo->bar->baz['id'] is the same as $foo->bar[0]->baz[0]['id']
  • Conversely, using a foreach loop with an object representing a single node automatically loops over the children of that element, as though you'd called ->children()

There are however times when you need to tell the difference. For instance, foreach ( $foo->bar as $item ) will loop over all elements named bar; but foreach ( $foo->bar->children() as $item ) will access the first element named bar, and loop over its children.

The children() method is also used to switch between namespaces, see Reference - How do I handle Namespaces (Tags and Attributes with a Colon in their Name) in SimpleXML?

Upvotes: 2

Vishnu S Vyshakh
Vishnu S Vyshakh

Reputation: 27

As the name indicates SimpleXMLElement::children is a member function is simply returns the children elements as objects from SimpleXMLElement class object. It always return a 'SimpleXMLElement' class object unless the node represents an attribute (id, class etc can be consider as attributes), in which case null is returned.

Consider this example

$foo = new SimpleXmlElement(
'<foo>
  <bar>
    <baz id="b1">b1</baz>
    <baz id="b2">b2</baz>
    <baz id="b3">b3</baz>
    <pas id="p1">p1</pas>
  </bar>
 </foo>');
$mainfoo = json_encode($foo); var_dump($mainfoo); // string(50) "{"bar":{"baz":["b1","b2","b3"],"pas":["p1","p2"]}}"
$children = json_encode($foo->children()); var_dump($children ); // string(50) "{"bar":{"baz":["b1","b2","b3"],"pas":["p1","p2"]}}"
$childrenofbar = json_encode($foo->bar->children()); var_dump($childrenofbar ); //string(42) "{"baz":["b1","b2","b3"],"pas":["p1","p2"]}"
$children_bar_pas = json_encode($foo->bar->pas); var_dump($children_bar_pas); //string(45) "{"@attributes":{"id":"p1"},"0":"p1","1":"p2"}"

We can not use var_dump to view and verify SimpleXmlElement object. So for convenient manner , we can simply json_encode them and var_dump them ;)

Here the first statement converts an xml/markup string to SimpleXmlElement class object.

$foo->children() brings the children elements as a SimpleXmlElement class objects

$foo->bar->children() brings the children elements of 'bar'.

As per the documentation, object of a SimpleXmlElement is iterable using php loops such as for/ foreach etc..

foreach($foo as $f1) {
  var_dump(json_encode($f1)); // "{"baz":["b1","b2","b3"],"pas":["p1","p2"]}"
}

foreach($foo->children() as $f2) {
  var_dump(json_encode($f2)); // string(42) "{"baz":["b1","b2","b3"],"pas":["p1","p2"]}"
}

children() method can also use to access child elements for the markups having valid namespace. Please see the Example #2 in documentation!

Upvotes: 1

Related Questions