Это не может быть выражено как одно выражение 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::*)
]