Weird SimpleXML issue - can't reference nodes by name?

孤者浪人 提交于 2019-12-20 04:24:12

问题


I'm trying to parse a remote XML file, which is valid:

$xml = simplexml_load_file('http://feeds.feedburner.com/HammersInTheHeart?format=xml');

The root element is feed, and I'm trying to grab it via:

$nodes = $xml->xpath('/feed'); //also tried 'feed', without slash

Except it doesn't find any nodes.

print_r($nodes); //empty array

Or any nodes of any kind, so long as I search for them by tag name, in fact:

$nodes = $xml->xpath('//entry');
print_r($nodes); //empty array

It does find nodes, however, if I use wildcards, e.g.

$nodes = $xml->xpath('/*/*[4]');
print_r($nodes); //node found

What's going on?


回答1:


Unlike DOM, SimpleXML has no concept of a document object, only elements. So if you load an XML you always get the document element.

$feed = simplexml_load_file($xmlFile);
var_dump($feed->getName());

Output:

string(4) "feed"

That means that all Xpath expression have to to be relative to this element or absolute. Simple feed will not work because the context already is the feed element.

But here is another reason. The URL is an Atom feed. So the XML elements in the namespace http://www.w3.org/2005/Atom. SimpleXMLs magic syntax recognizes a default namespace for some calls - but Xpath does not. Here is not default namespace in Xpath. You will have to register them with a prefix and use that prefix in your Xpath expressions.

$feed = simplexml_load_file($xmlFile);
$feed->registerXpathNamespace('a', 'http://www.w3.org/2005/Atom');
foreach ($feed->xpath('/a:feed/a:entry[position() < 3]') as $entry) {
  var_dump((string)$entry->title);
}

Output:

string(24) "Sharing the goals around"
string(34) "Kouyate inspires Hammers' comeback"

However in SimpleXML the registration has to be done for each object you call the xpath() method on.

Using Xpath with DOM is slightly different but a lot more powerful.

$document = new DOMDocument();
$document->load($xmlFile);
$xpath = new DOMXpath($document);
$xpath->registerNamespace('a', 'http://www.w3.org/2005/Atom');

foreach ($xpath->evaluate('/a:feed/a:entry[position() < 3]') as $entry) {
  var_dump($xpath->evaluate('string(a:title)', $entry));
}

Output:

string(24) "Sharing the goals around"
string(34) "Kouyate inspires Hammers' comeback"

Xpath expression using with DOMXpath::evaluate() can return scalar values.



来源:https://stackoverflow.com/questions/32826683/weird-simplexml-issue-cant-reference-nodes-by-name

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!