选择文档的所有节点的xpath表达式是什么?
给出这个例子XML:
<div class="header"/>
我包含三个节点:<div>
(元素),class=
(属性)和"header"
(文字)。
$doc = new DOMDocument;
$doc->loadXml('<div class="header"/>');
$xpath = new DOMXPath($doc);
我尝试了//node()
:
$xpath->query('//node()');
仅返回所有元素节点(我假设因为//
)。有没有办法在属性值中添加属性和文本节点等其他节点?
附加示例:
我可以使用DOMDocument
API获取每个节点,例如获取属性值的文本节点:
$doc = new DOMDocument;
$doc->loadXml('<div class="header"/>');
$class = $doc->documentElement->getAttributeNode('class');
echo $class->childNodes->item(0)->nodeName;
给出了:
#text
如何使用一个xpath表达式获取所有节点的超集,尤其是包含该示例性class
属性节点子文本节点?
答案 0 :(得分:3)
您的示例实际上只包含两个节点:元素(div
)和属性(class="header"
)。因此,“header”是属性的值,而不是单独的节点。
文本节点确实存在,但它们用于元素之间的文本。例如,在<title>Alice in wonderland</title>
中,有两个节点:元素(title
)和文本节点(Alice in wonderland
)。
因此,在这种情况下,您可以做的最好的事情是//*|//@*
。
编辑,在您更新问题之后。
文本节点的存在是由于特定于php的实现,它不是W3C standard的一部分。无论实现如何,XPath都只考虑2个节点。
话虽如此,你可以使用一些XPath functions来获得你想要的东西。函数name()
返回节点的名称,函数string()
返回字符串值。也许你可以使用这些来获取字符串(而不是节点)。
答案 1 :(得分:3)
使用强>:
//node() | //@* | //namespace::*
这将选择任何节点(类型为文档节点/
,元素节点,文本节点,处理指令节点和注释节点)以及任何属性节点和任何命名空间节点 - 即 all 节点,因为没有其他类型的节点。
如何访问包含所选节点的获取的XmlNodeList取决于您使用的特定XPath引擎的API - 阅读并使用您的文档。
基于XSLT的示例:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:for-each select=
"//node() | //@* | //namespace::*">
Type: <xsl:text/>
<xsl:choose>
<xsl:when test="not(..)">
<xsl:text>document node </xsl:text>
</xsl:when>
<xsl:when test="self::*">
<xsl:text>element </xsl:text>
</xsl:when>
<xsl:when test="self::text()">
<xsl:text>text-node </xsl:text>
</xsl:when>
<xsl:when test="self::comment()">
<xsl:text>comment-node </xsl:text>
</xsl:when>
<xsl:when test="self::processing-instruction()">
<xsl:text>PI-node </xsl:text>
</xsl:when>
<xsl:when test="count(.|../@*) = count(../@*)">
<xsl:text>attribute-node </xsl:text>
</xsl:when>
<xsl:when test=
"count(.|../namespace::*) = count(../namespace::*)">
<xsl:text>namespace-node </xsl:text>
</xsl:when>
</xsl:choose>
<xsl:text>Name: "</xsl:text>
<xsl:value-of select="name()"/>" <xsl:text/>
<xsl:text>Value: </xsl:text>
<xsl:value-of select="."/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
当对任何XML文档应用此XSLT转换时,它使用上述XPath表达式选择所有节点(转换故意排除任何仅限空格的文本节点)并输出(按文档顺序)类型,名称和所选节点的字符串值。
例如,应用于此XML文档时:
<networkOfBridges xmlns:x="x">
<bridge id="1" otherside="A" />
<!-- A Comment -->
<bridge id="2" oneside="A"/>
<?PI Processing Instruction ?>
<bridge id="3" oneside="A" otherside="A" />
</networkOfBridges>
结果是:
Type: element Name: "networkOfBridges" Value:
Type: namespace-node Name: "xml" Value: http://www.w3.org/XML/1998/namespace
Type: namespace-node Name: "x" Value: x
Type: element Name: "bridge" Value:
Type: namespace-node Name: "xml" Value: http://www.w3.org/XML/1998/namespace
Type: namespace-node Name: "x" Value: x
Type: attribute-node Name: "id" Value: 1
Type: attribute-node Name: "otherside" Value: A
Type: comment-node Name: "" Value: A Comment
Type: element Name: "bridge" Value:
Type: namespace-node Name: "xml" Value: http://www.w3.org/XML/1998/namespace
Type: namespace-node Name: "x" Value: x
Type: attribute-node Name: "id" Value: 2
Type: attribute-node Name: "oneside" Value: A
Type: PI-node Name: "PI" Value: Processing Instruction
Type: element Name: "bridge" Value:
Type: namespace-node Name: "xml" Value: http://www.w3.org/XML/1998/namespace
Type: namespace-node Name: "x" Value: x
Type: attribute-node Name: "id" Value: 3
Type: attribute-node Name: "oneside" Value: A
Type: attribute-node Name: "otherside" Value: A
答案 2 :(得分:1)
您是否尝试过类似//*|//@*|//text()
的内容?
答案 3 :(得分:-1)
foreach ($xpath->query('//*[count(*) = 0]') as $node) {
$path = array();
$val = $node->nodeValue;
do {
$path[] = $node->nodeName;
}
while ($node = $node->parentNode);
$result[implode('/', array_reverse($path))] = $val;
}