奇怪的 SimpleXML 问题 - 不能按名称引用节点? [英] Weird SimpleXML issue - can't reference nodes by name?

查看:24
本文介绍了奇怪的 SimpleXML 问题 - 不能按名称引用节点?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试解析一个有效的远程 XML 文件:

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

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

根元素是 feed,我试图通过以下方式获取它:

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

怎么回事?

推荐答案

与 DOM 不同,SimpleXML 没有文档对象的概念,只有元素.因此,如果您加载 XML,您总是会获得文档元素.

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());

输出:

string(4) "feed"

这意味着所有 Xpath 表达式都必须相对于该元素或绝对的.简单的 feed 将不起作用,因为上下文已经是 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.

但这是另一个原因.URL 是一个 Atom 提要.所以命名空间http://www.w3.org/2005/Atom 中的XML 元素.SimpleXMLs 魔法语法识别某些调用的默认命名空间 - 但 Xpath 不会.这不是 Xpath 中的默认命名空间.您必须使用前缀注册它们并在 Xpath 表达式中使用该前缀.

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);
}

输出:

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

但是在 SimpleXML 中,必须为您调用 xpath() 方法的每个对象完成注册.

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

将 Xpath 与 DOM 结合使用略有不同,但功能要强大得多.

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));
}

输出:

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

DOMXpath::evaluate() 一起使用的 Xpath 表达式可以返回标量值.

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

这篇关于奇怪的 SimpleXML 问题 - 不能按名称引用节点?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆