命名空间和 XPath
Namespaces and XPath
我正在探索 XML 和 PHP,主要是 XPath 和其他解析器。
这里是 xml:
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:foo="http://www.foo.org/" xmlns:bar="http://www.bar.org">
<actors>
<actor id="1">Christian Bale</actor>
<actor id="2">Liam Neeson</actor>
<actor id="3">Michael Caine</actor>
</actors>
<foo:singers>
<foo:singer id="4">Tom Waits</foo:singer>
<foo:singer id="5">B.B. King</foo:singer>
<foo:singer id="6">Ray Charles</foo:singer>
</foo:singers>
<items>
<item id="7">Pizza</item>
<item id="8">Cheese</item>
<item id="9">Cane</item>
</items>
</root>
这是我的路径和代码:
$xml = simplexml_load_file('xpath.xml');
$result = $xml -> xpath('/root/actors');
echo '<pre>'.print_r($result,1).'</pre>';
现在,说路径 returns:
Array
(
[0] => SimpleXMLElement Object
(
[actor] => Array
(
[0] => Christian Bale
[1] => Liam Neeson
[2] => Michael Caine
)
)
)
虽然看似相似的代码行(我本以为会产生歌手)却没有。含义:
$result = $xml -> xpath('/root/foo:singers');
结果:
Array
(
[0] => SimpleXMLElement Object
(
)
)
现在我会认为 foo: 命名空间在这种情况下不是问题,两条路径应该分别产生相同类型的 singers/actors 数组?怎么不是这样?
谢谢!
注意:正如你可能知道的那样,我对 xml 很陌生,所以请保持温和。
编辑:当我去 /root/foo:singers/foo:singer 时,我得到了结果,但之前没有。同样仅使用 /root 我只得到演员和项目作为结果,foo:singers 被完全省略。
您可以使用 //
表达式,例如:
$xml -> xpath( '//foo:singer' );
到 select 所有 foo:singer
元素,无论它们在哪里。
编辑:
SimpleXMLElement 是 selected,你只是看不到带有 print_r()
的子节点。使用像 SimpleXMLElement::children 这样的 SimpleXMLElement 方法来访问它们。
// example 1
$result = $xml->xpath( '/root/foo:singers' );
foreach( $result as $value ) {
print_r( $value->children( 'foo', TRUE ) );
}
// example 2
print_r( $result[0]->children( 'foo', TRUE )->singer );
出于多种原因,SimpleXML 简直就是一个糟糕的 API。
对于大多数用途,我建议 PHP 的 DOM extension. (Or for very large documents a combination of it along with XMLReader。)
要在 xpath 中使用命名空间,您需要 register those you'd like to use, and the prefix you want to use them with, with your xpath processor。
示例:
$dom = new DOMDocument();
$dom->load('xpath.xml');
$xpath = new DOMXPath($dom);
// The prefix *can* match that used in the document, but it's not necessary.
$xpath->registerNamespace("ns", "http://www.foo.org/");
foreach ($xpath->query("/root/ns:singers") as $node) {
echo $dom->saveXML($node);
}
输出:
<foo:singers>
<foo:singer id="4">Tom Waits</foo:singer>
<foo:singer id="5">B.B. King</foo:singer>
<foo:singer id="6">Ray Charles</foo:singer>
</foo:singers>
DOMXPath::query returns a DOMNodeList containing matched nodes. You can work with it essentially the same way you would in any other language with a DOM 实施。
我正在探索 XML 和 PHP,主要是 XPath 和其他解析器。
这里是 xml:
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:foo="http://www.foo.org/" xmlns:bar="http://www.bar.org">
<actors>
<actor id="1">Christian Bale</actor>
<actor id="2">Liam Neeson</actor>
<actor id="3">Michael Caine</actor>
</actors>
<foo:singers>
<foo:singer id="4">Tom Waits</foo:singer>
<foo:singer id="5">B.B. King</foo:singer>
<foo:singer id="6">Ray Charles</foo:singer>
</foo:singers>
<items>
<item id="7">Pizza</item>
<item id="8">Cheese</item>
<item id="9">Cane</item>
</items>
</root>
这是我的路径和代码:
$xml = simplexml_load_file('xpath.xml');
$result = $xml -> xpath('/root/actors');
echo '<pre>'.print_r($result,1).'</pre>';
现在,说路径 returns:
Array
(
[0] => SimpleXMLElement Object
(
[actor] => Array
(
[0] => Christian Bale
[1] => Liam Neeson
[2] => Michael Caine
)
)
)
虽然看似相似的代码行(我本以为会产生歌手)却没有。含义:
$result = $xml -> xpath('/root/foo:singers');
结果:
Array
(
[0] => SimpleXMLElement Object
(
)
)
现在我会认为 foo: 命名空间在这种情况下不是问题,两条路径应该分别产生相同类型的 singers/actors 数组?怎么不是这样?
谢谢!
注意:正如你可能知道的那样,我对 xml 很陌生,所以请保持温和。
编辑:当我去 /root/foo:singers/foo:singer 时,我得到了结果,但之前没有。同样仅使用 /root 我只得到演员和项目作为结果,foo:singers 被完全省略。
您可以使用 //
表达式,例如:
$xml -> xpath( '//foo:singer' );
到 select 所有 foo:singer
元素,无论它们在哪里。
编辑:
SimpleXMLElement 是 selected,你只是看不到带有 print_r()
的子节点。使用像 SimpleXMLElement::children 这样的 SimpleXMLElement 方法来访问它们。
// example 1
$result = $xml->xpath( '/root/foo:singers' );
foreach( $result as $value ) {
print_r( $value->children( 'foo', TRUE ) );
}
// example 2
print_r( $result[0]->children( 'foo', TRUE )->singer );
出于多种原因,SimpleXML 简直就是一个糟糕的 API。
对于大多数用途,我建议 PHP 的 DOM extension. (Or for very large documents a combination of it along with XMLReader。)
要在 xpath 中使用命名空间,您需要 register those you'd like to use, and the prefix you want to use them with, with your xpath processor。
示例:
$dom = new DOMDocument();
$dom->load('xpath.xml');
$xpath = new DOMXPath($dom);
// The prefix *can* match that used in the document, but it's not necessary.
$xpath->registerNamespace("ns", "http://www.foo.org/");
foreach ($xpath->query("/root/ns:singers") as $node) {
echo $dom->saveXML($node);
}
输出:
<foo:singers>
<foo:singer id="4">Tom Waits</foo:singer>
<foo:singer id="5">B.B. King</foo:singer>
<foo:singer id="6">Ray Charles</foo:singer>
</foo:singers>
DOMXPath::query returns a DOMNodeList containing matched nodes. You can work with it essentially the same way you would in any other language with a DOM 实施。