在下面的代码中,我希望它选择每个节点,但它只选择每个第二个节点。这是正确的行为还是错误?
<?php
$doc = new DOMDocument('1.0', 'UTF-8');
$doc->loadXML('<root xmlns:ns="foo" ns:id="1"><one/><two/><three/><four/><five/></root>');
$finder = new DOMXPath($doc);
$nodes = $finder->query("//*[namespace::ns]");
foreach ($nodes as $n) {
var_dump($doc->saveXML($n, LIBXML_NOEMPTYTAG));
}
?>
输出:
string '<root xmlns:ns="foo" ns:id="1"><one></one><two></two><three></three><four></four><five></five></root>' (length=101)
string '<two></two>' (length=11)
string '<four></four>' (length=13)
最佳答案
这似乎是 PHP 使用的 libxml 中的一个错误。结果是根、二、四中的名称。
使用 //*[namespace::*]
会更奇怪,然后您将获得根节点和节点一、三、五。
尽管所有子节点都继承了命名空间,但这样做似乎存在一些错误的实现。
使用以下 xslt 会生成所有所需的节点:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<matches>
<xsl:copy-of select="//*[namespace::ns]"/>
</matches>
</xsl:template>
</xsl:stylesheet>
XPath 本身虽然可以更改为//* 以选择所有节点 - 无论命名空间如何。同样,正如 kjhughes 指出的那样,您并没有真正为节点使用命名空间,而只是为属性使用命名空间。
关于php - 命名空间的 XPath 搜索每隔一个节点选择一次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30480738/