[英]PHP DOMDocument and DOMXpath - get all input/select/textarea names
[英]How to select all nodes of a DOMDocument with a single DOMXpath expression?
选择文档的所有节点的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
属性 - 节点子文本节点?
您的示例实际上只包含两个节点:元素( div
)和属性( class="header"
)。 因此,“header”是属性的值,而不是单独的节点。
文本节点确实存在,但它们用于元素之间的文本。 例如,在<title>Alice in wonderland</title>
,有两个节点:元素( title
)和文本节点( Alice in wonderland
)。
因此,在这种情况下你能做的最好的是//*|//@*
。
在您对问题进行更新后编辑。
文本节点的存在是由于特定于php的实现,它不是W3C标准的一部分。 无论实现如何,XPath都只考虑2个节点。
话虽如此,您可以使用一些XPath函数来获得您想要的。 函数name()
返回节点的名称,函数string()
返回字符串值。 也许您可以使用这些来获取字符串(而不是节点)。
用途 :
//node() | //@* | //namespace::*
这将选择任何节点(类型为文档节点/
,元素节点,文本节点,处理指令节点和注释节点)以及任何属性节点和任何命名空间节点 - 即所有节点,因为没有其他类型的节点。
如何访问包含所选节点的获取的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>
当这个XSLT转换应用于任何XML文档时,它使用上面的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
你尝试过类似//*|//@*|//text()
吗?
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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.