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).
Unfortunately there is no hidden property or method that allows identifying the type of node in SimpleXML. SimpleXML only uses one Class and elements do not have anything that point to their parents. If you try the below reflection you will see that there is nothing to distinguish element or attribute.
However if an element has attributes you can detect that. So you would have to assume that all elements passed in have attributes. With that assumption you could tell them apart.
This is the best I can come up with. Remember it's possible for an element with no attributes to still return false with this.
Using what palako pointed out, a function like this might work:
You need SimpleXMLElement::attributes:
May need a bit of tweaking.
Yes there is a way. Well, nothing elegant that you can retrieve via the API, but somewhere in the guts of the SimpleXML is keeping track of what it is and it makes a differences, for example, when you call functions such as getName() or asXML().
Your code won't win a beauty contest, but at least you can do it.
The answer is no... and yes. SimpleXML doesn't have such a property but here's the good news: SimpleXML and DOM are two faces of the same coin. (the coin is libxml ;)) You don't have to choose one or the other, you can use both! You can turn
SimpleXMLElement
intoDOMNode
and vice versa. In your case, you could do something like:If that's something you do often, or you don't want to handle the DOM/SimpleXML juggling, you can take a look at SimpleDOM.
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:So if you need this precise with a snappy boolean
true
/false
, here is how it works with Simplexml: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: