奇怪的 SimpleXML 问题 - 不能按名称引用节点?
Weird SimpleXML issue - can't reference nodes by name?
我正在尝试解析一个有效的远程 XML 文件:
$xml = simplexml_load_file('http://feeds.feedburner.com/HammersInTheHeart?format=xml');
根元素是 feed
,我试图通过以下方式获取它:
$nodes = $xml->xpath('/feed'); //also tried 'feed', without slash
除了没有找到任何节点。
print_r($nodes); //empty array
或任何类型的任何节点,只要我按标签名称搜索它们,实际上:
$nodes = $xml->xpath('//entry');
print_r($nodes); //empty array
它确实找到了节点,但是,如果我使用通配符,例如
$nodes = $xml->xpath('/*/*[4]');
print_r($nodes); //node found
怎么回事?
与DOM不同,SimpleXML没有文档对象的概念,只有元素。所以如果你加载一个 XML 你总是得到文档元素。
$feed = simplexml_load_file($xmlFile);
var_dump($feed->getName());
输出:
string(4) "feed"
这意味着所有 Xpath 表达式都必须相对于此元素或绝对。简单的 feed
将不起作用,因为上下文已经是 feed
元素。
但这是另一个原因。 URL 是一个 Atom 提要。所以命名空间 http://www.w3.org/2005/Atom
中的 XML 个元素。 SimpleXML 的神奇语法可以识别某些调用的默认命名空间——但 Xpath 不能。这里不是 Xpath 中的默认命名空间。您必须使用前缀注册它们并在您的 Xpath 表达式中使用该前缀。
$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()
方法的每个对象完成注册。
将 Xpath 与 DOM 一起使用略有不同,但功能更强大。
$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 表达式可以 return 标量值。
我正在尝试解析一个有效的远程 XML 文件:
$xml = simplexml_load_file('http://feeds.feedburner.com/HammersInTheHeart?format=xml');
根元素是 feed
,我试图通过以下方式获取它:
$nodes = $xml->xpath('/feed'); //also tried 'feed', without slash
除了没有找到任何节点。
print_r($nodes); //empty array
或任何类型的任何节点,只要我按标签名称搜索它们,实际上:
$nodes = $xml->xpath('//entry');
print_r($nodes); //empty array
它确实找到了节点,但是,如果我使用通配符,例如
$nodes = $xml->xpath('/*/*[4]');
print_r($nodes); //node found
怎么回事?
与DOM不同,SimpleXML没有文档对象的概念,只有元素。所以如果你加载一个 XML 你总是得到文档元素。
$feed = simplexml_load_file($xmlFile);
var_dump($feed->getName());
输出:
string(4) "feed"
这意味着所有 Xpath 表达式都必须相对于此元素或绝对。简单的 feed
将不起作用,因为上下文已经是 feed
元素。
但这是另一个原因。 URL 是一个 Atom 提要。所以命名空间 http://www.w3.org/2005/Atom
中的 XML 个元素。 SimpleXML 的神奇语法可以识别某些调用的默认命名空间——但 Xpath 不能。这里不是 Xpath 中的默认命名空间。您必须使用前缀注册它们并在您的 Xpath 表达式中使用该前缀。
$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()
方法的每个对象完成注册。
将 Xpath 与 DOM 一起使用略有不同,但功能更强大。
$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 表达式可以 return 标量值。