5

我想使用 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")])]

有没有更好的(更少的代码,更高效,更干燥)的方式来选择我想要的东西?

4

2 回答 2

5
//blockquote[pre][count(pre)=count(*)]
于 2012-07-11T19:28:16.713 回答
3

使用

//blockquote[* and not(*[not(self::pre)])]

这将选择blockquoteXML 文档中至少具有一个子元素且不具有任何非元素的子元素的所有pre元素。

这只是双重否定定律的应用:)。

请注意,此表达式比计算所有元素子元素的表达式更有效(因为选择在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>
于 2012-07-12T12:50:26.200 回答