如何使用XPath查找与字符串内容长度约束匹配的最深节点。
给定一大块XHTML(或XML),如下所示:
<html>
<body>
<div id="page">
<div id="desc">
This wool sweater has the following features:
<ul>
<li>4 buttons</li>
<li>Merino Wool</li>
</ul>
</div>
</div>
...
</body>
</html>
一个XPath表达式,例如
//*[string-length() > 50]
将匹配
<html>, <body>, <div id="page"> and <div id="desc">
。如何使XPath选择最深的匹配节点(即:<< cc>)?优点是,如何将约束应用于空间归一化的内容长度?
最佳答案
这不能表示为单个XPath 1.0表达式(不使用变量)
单个XPath 2.0表达式:
//*[string-length(.) > 50]
[count(ancestor::*) >= //*[string-length(.) > 50]/count(ancestor::*)]
使用变量的XPath 1.0表达式:
//*[string-length() > 50]
[not(//*[string-length() > 50
and count(ancestor::*) > $vNumAncestrors])
]
其中变量
vNumAncestrors
保存上下文节点的count(ancestor::*)
值。可以使用托管语言(例如XSLT 1.0或DOM)来实现后一个表达式。
这是一个XSLT 1.0实现:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*">
<xsl:variable name="vLongTextElements"
select="//*[string-length()>50]"/>
<xsl:for-each select="$vLongTextElements">
<xsl:variable name="vNumAncestrors"
select="count(ancestor::*)"/>
<xsl:copy-of select=
"(.)[not(//*[string-length() > 50
and count(ancestor::*) > $vNumAncestrors])
]
"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
当此转换应用于提供的XML文档时:
<html>
<body>
<div id="page">
<div id="desc"> This wool sweater has the following features:
<ul>
<li>4 buttons</li>
<li>Merino Wool</li>
</ul>
</div>
</div> ...
</body>
</html>
所需的正确结果产生了:
<div id="desc"> This wool sweater has the following features:
<ul>
<li>4 buttons</li>
<li>Merino Wool</li>
</ul>
</div>
奖励积分,如何应用
空间标准化内容的约束
长度?
在最后一个解决方案的顶部实现非常简单:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*">
<xsl:variable name="vLongTextElements"
select="//*[string-length(normalize-space())>50]"/>
<xsl:for-each select="$vLongTextElements">
<xsl:variable name="vNumAncestrors"
select="count(ancestor::*)"/>
<xsl:copy-of select=
"(.)[not(//*[string-length(normalize-space()) > 50
and count(ancestor::*) > $vNumAncestrors])
]
"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
现在,初始XPath 2.0表达式已修改为以下表达式:
//*[string-length(normalize-space(.)) > 50]
[count(ancestor::*)
>=
//*[string-length(normalize-space(.)) > 50]/count(ancestor::*)
]
关于xml - Xpath最深节点,其字符串内容长于给定长度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4493323/