具有冲突的XML命名空间前缀的XPath行为



考虑以下XML:

<?xml version="1.0" encoding="utf-8"?>
<movies xmlns:en="http://english-language.com/">
<en:movie>
<title>The Godfather</title>
</en:movie>
<en:movie>
<title>Saving Private Ryan</title>
</en:movie>
<something-something xmlns:en="http://english.com/">
<en:movie>
<title>The Fellowship of the Ring</title>
</en:movie>
</something-something>
</movies>

下面的代码将匹配教父拯救大兵瑞恩。但为什么呢?我原以为会失败。查询似乎忽略了名称空间名称(URI(,而使用了名称空间前缀

$xpath      = new DOMXpath($dom);
$xpath->registerNamespace('en', 'http://complete-nonsense');
$elements   = $xpath->query("//en:movie");

我原以为下面的代码会匹配《魔戒联盟》,但它再次匹配《教父》和《拯救大兵瑞恩》。

$xpath      = new DOMXpath($dom);
$xpath->registerNamespace('en', 'http://english.com/');
$elements   = $xpath->query("//en:movie");

直到现在,URI似乎才有任何区别,现在它与魔戒之友相匹配。

$xpath      = new DOMXpath($dom);
$xpath->registerNamespace('english', 'http://english.com/');
$elements   = $xpath->query("//english:movie");

为什么?PHP的实现有什么问题吗?

DOMXpath::evaluate()/DOMXpath::query()在手动注册的命名空间定义之上注册当前上下文节点的命名空间定义。基本上,文档将覆盖前缀的命名空间。第三个参数(由于PHP>=5.3.3(可以禁用自动注册:

$document = new DOMDocument();
$document->loadXML($xml);
$xpath = new DOMXpath($document);
$xpath->registerNamespace('en', 'http://english.com/');
// the xmlns:en from the document element overrides the registration
var_dump($xpath->evaluate('normalize-space(//en:movie)'));
// automatic registration disabled - works correctly
var_dump($xpath->evaluate('normalize-space(//en:movie)', NULL, FALSE));

输出:

string(13) "The Godfather"
string(26) "The Fellowship of the Ring"

最新更新