我想使用XPath查找每个<blockquote>
元素,其中至少有一个子<pre>
元素,没有其他类型的子元素,以及可选的文本节点作为子元素:
<body><div><!-- arbitrary nesting -->
<blockquote><pre>YES</pre></blockquote>
<blockquote><p>NO</p></blockquote>
<blockquote><pre>NO</pre><p>NO</p></blockquote>
<blockquote><p>NO</p><pre>NO</pre></blockquote>
<blockquote><pre>YES</pre> <pre>YES</pre></blockquote>
<blockquote>NO</blockquote>
</div></body>
这个XPath似乎有效,但我怀疑它过于复杂:
//blockquote[pre][not(*[not(name()="pre")])]
是否有更好的(更少的代码,更高效,更干的)方式来选择我想要的东西?
答案 0 :(得分:5)
//blockquote[pre][count(pre)=count(*)]
答案 1 :(得分:3)
使用强>:
//blockquote[* and not(*[not(self::pre)])]
这将选择XML文档中至少包含一个元素子元素但没有任何元素子元素不是blockquote
元素的所有pre
元素。
这只是 double negation law :)的应用。
请注意,此表达式比计算所有元素子项的表达式更有效(因为选择在找到非pre
子项时立即停止。)
基于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:copy-of select="//blockquote[* and not(*[not(self::pre)])]"/>
</xsl:template>
</xsl:stylesheet>
在提供的XML文档上应用此转换时:
<body><div><!-- arbitrary nesting -->
<blockquote><pre>YES</pre></blockquote>
<blockquote><p>NO</p></blockquote>
<blockquote><pre>NO</pre><p>NO</p></blockquote>
<blockquote><p>NO</p><pre>NO</pre></blockquote>
<blockquote><pre>YES</pre> <pre>YES</pre></blockquote>
<blockquote>NO</blockquote>
</div></body>
评估XPath表达式并将选定的节点复制到输出中:
<blockquote>
<pre>YES</pre>
</blockquote>
<blockquote>
<pre>YES</pre>
<pre>YES</pre>
</blockquote>