【问题标题】:Xpath: Complex expression to include some nodes and exclude othersXpath:包含一些节点并排除其他节点的复杂表达式
【发布时间】:2011-11-20 16:48:10
【问题描述】:

示例 xml:

<foo>
    <bar name="bar1">
    </bar>
    <bar name="bar2">
    </bar>
</foo>
<qux>
    <foo>
        <bar name="bar3">
        </bar>
    </foo>
     <bar name="bar4">
     </bar>
</qux>

选择作为根 foo (bar1, bar2, bar4) 但不是嵌套 foo (bar3) 的子元素的所有 bar 元素的表达式是什么?

提前谢谢你!

【问题讨论】:

  • 那不是合法的 XML 文档。有多个根元素。
  • bar4 不是根 foo 的子节点。
  • @Michael Kay - 你是对的,根 foo 也应该覆盖 qux 元素。请看我对第一个答案的第一反应。
  • @MichaelKay:我的解释是 OP 的意思是“后代”——而不是“孩子”

标签: xml xslt xpath


【解决方案1】:

正如@Cheeso 所说,该文件无效,并且似乎与您的问题不符。

如果这是您想要的文档(qux 在第一个 foo 中)

<foo>
    <bar name="bar1">
    </bar>
    <bar name="bar2">
    </bar>
    <qux>
        <foo>
            <bar name="bar3">
            </bar>
        </foo>
        <bar name="bar4">
        </bar>
    </qux>
</foo>

那么这里有两条路径

//bar[not(parent::foo[ancestor::foo])]
//bar[1 >= count(ancestor::foo)]

这将选择您想要的元素(在 .NET 中测试)。

【讨论】:

  • 感谢您的回复!你对 xml 是正确的。要求是 - 可以有多层嵌套的 foo 和 bar 元素。选择所有作为当前 foo 的后代而不是任何其他 foo 的 bar 元素。再次感谢!
  • @user897210,好吧,这更具体。我已经用两种可能的解决方案更新了答案。取决于您发现什么更具可读性。
【解决方案2】:

选择所有 bar 元素的子元素的表达式是什么 根 foo (bar1, bar2, bar4) 但不是嵌套 foo (bar3)?

这可能是最简单和最短的 XPath 表达式之一,当对任何具有顶级元素 foo 并且可能具有任何级别的嵌套 foo 元素的格式良好的 XML 文档进行评估时准确选择只有 foo 祖先是顶部元素的 bar 元素:

//bar[not(ancestor::foo[2])]

此 Xpath 表达式选择文档中具有少于两个 foo 祖先的任何 bar 元素。因为根据定义,顶部元素是foo,这意味着每个bar 都有这个顶部元素foo 作为祖先。如果它在嵌套的foo 内,则它至少有第二个祖先foo,并且不会被上面的XPath 表达式选中,因为在这种情况下boolean(ancestor::foo[2])true()

基于 XSLT 的验证

这种转变

<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:copy-of select=
   "//bar[not(ancestor::foo[2])]"/>
 </xsl:template>
</xsl:stylesheet>

应用于以下 XML 文档时(基于提供的 XML 片段,但使其成为格式良好的 XML 文档并添加了更多的嵌套/复杂性,以使其变得有趣):

<foo>
    <bar name="bar1">
    </bar>
    <bar name="bar2">
    </bar>
    <qux>
        <foo>
           <baz>
             <bar name="bar3">
             </bar>
            </baz>
        </foo>
        <bar name="bar4">
        </bar>
        <qux>
            <foo>
                <bar name="bar5">
                </bar>
            </foo>
            <bar name="bar6">
            </bar>
        </qux>
    </qux>
</foo>

准确输出所需的元素

<bar name="bar1">

</bar>
<bar name="bar2">

</bar>
<bar name="bar4">

</bar>
<bar name="bar6">

</bar>

【讨论】:

  • +1 以获得更好的表达。我就知道迟早会在这里见到你!
猜你喜欢
  • 1970-01-01
  • 2021-10-30
  • 1970-01-01
  • 2021-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-24
相关资源
最近更新 更多