How to tell apart SimpleXML objects representing element and attribute?

php, reflection, simplexml

Solution

There are no built-in properties in `SimpleXMLElement` which would allow you to tell these apart.

As others have suggested `dom_import_simplexml` can be appropriate, however, that function can change nodes on the fly sometimes, for example, if you pass in a list of childnodes or named childnodes, it will take those and turn them into the first element.

If it's an empty list, for example no attributes returned from `attributes()` or non-existing named childnodes, it will give a warning telling you an invalid nodetype has been given:

Warning: dom_import_simplexml(): Invalid Nodetype to import

So if you need this precise with a snappy boolean `true`/`false`, here is how it works with Simplexml:

$isElement   = $element->xpath('.') == array($element);

$isAttribute = $element[0] == $element
               and $element->xpath('.') != array($element);

It works similar with attribute lists and element lists, I've just blogged about this in the morning, you need to have some specific knowledge about what to evaluate for what, so I created a cheatsheet for it:

+------------------+---------------------------------------------+
| TYPE             | TEST                                        |
+------------------+---------------------------------------------+
| Element          | $element->xpath('.') == array($element)     |
+------------------+---------------------------------------------+
| Attribute        | $element[0] == $element                     |
|                  | and $element->xpath('.') != array($element) |
+------------------+---------------------------------------------+
| Attributes       | $element->attributes() === NULL             |
+------------------+---------------------------------------------+
| Elements         | $element[0] != $element                     |
|                  | and $element->attributes() !== NULL         |
+------------------+---------------------------------------------+
| Single           | $element[0] == $element                     |
+------------------+---------------------------------------------+
| Empty List       | $element[0] == NULL                         |
+------------------+---------------------------------------------+
| Document Element | $element->xpath('/*') == array($element)    |
+------------------+---------------------------------------------+

- SimpleXML Type Cheatsheet (12 Feb 2013; by hakre)

Problem

I need to print arbitrary SimpleXML objects in a specific manner, with special handling of attribute nodes. The problem is that SimpleXML elements and attributes seem to use exactly the same class, attribute node even pretends to support `attributes()` method, and SimpleXML hides its internals, so there doesn't seem to be any way to tell type of node (short of generating XML and reparsing it). Both give identical result: ``` $element = new SimpleXMLElement('<foo>test</foo>'); echo $element; print_r($element); $element = new SimpleXMLElement('<foo attr="test" />'); echo $element['attr']; print_r($element['attr']); ``` Is there a hidden property/method that allows identifying type of node in SimpleXML? Equivalent of DOM's `$node->nodeType` or `$node instanceof DOMAttr`? (I can't use DOM instead, support for SimpleXML is core requirement).

Original source