Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
280 views
in Technique[技术] by (71.8m points)

php - How to tell apart SimpleXML objects representing element and attribute?

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).

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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)    |
+------------------+---------------------------------------------+

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...