1.我得到节点nodeBase
2.执行 XPATH 查询以从 nodeBase 获取最大深度
3.结果必须是 3 是否有可能在不使用 PHP 编写复杂算法的情况下做到这一点?
与使用 XPath 2.0 不同,在 XPath 1.0 中使用单个 XPath 表达式不可能产生想要的结果。
最简单的解决方案将涉及来自宿主语言(在本例中为 PHP)的一些计算。
您可以获得作为指定元素后代的所有叶元素。
对于它们中的每一个进行评估count(ancestor::*)
,然后在 PHP 中找到其中的最大值。
最后,从这样找到的最大绝对深度中减去指定元素的深度,该深度再次count(ancestor::*)
从该元素评估。
选择所有叶元素的 XPath 表达式(上面 1. 中需要)是:
//node[@id='nodeBase']//*[not(*)]
该算法的 XSLT 1.0 实现:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:variable name="vBase" select="//*[@id='nodeBase']"/>
<xsl:for-each select="$vBase//*">
<xsl:sort select="count(ancestor::*)" data-type="text" order="descending"/>
<xsl:if test="position() = 1">
<xsl:value-of select="count(ancestor::*) - count($vBase/ancestor::*)"/>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
当此转换应用于提供的 XML 文档时:
<node>
<node id="nodeBase">
<node>
<node />
</node>
<node>
<node>
<node />
</node>
</node>
</node>
</node>
产生了想要的正确结果:
3
从这里您可以了解如何在 PHP 中实现该算法。
为了完整起见,这里有一个 XPath 2.0 表达式产生相同的结果:
max((//*[@id='nodeBase'])[1]//*[not(*)]/count(ancestor::*))
-
(//*[@id='nodeBase'])[1]/count(ancestor::*)