XPath排除节点及其后代

时间:2012-03-10 13:20:59

标签: xml xpath

我有这样的XML:

<Root xmlns:test1="http://www.test1.com" xmlns:test2="http://www.test2.com" Attr="root">
  <test1:Child1 Attribute1="c1" Bttribute="c2" Cttribute="c3">
    <child11 Attribute11="c11">Element11</child11>
  </test1:Child1>
  <test2:Child2 Attribute2="c2">
    <child21 Attribute21="c21">
        <child211 />
        <child212 />
        <child213 />
    </child21>
    <child22 Attribute22="c22">Element22</child22>
  </test2:Child2>
  <test2:Child3 Attribute3="c3">
    <child31>Element31</child31>
  </test2:Child3>
</Root>

我想写一个XPath,这样我就可以选择除child21元素及其后代之外的所有元素。因此输出应如下所示:

<Root xmlns:test1="http://www.test1.com" xmlns:test2="http://www.test2.com" Attr="root">
  <test1:Child1 Attribute1="c1" Bttribute="c2" Cttribute="c3">
    <child11 Attribute11="c11">Element11</child11>
  </test1:Child1>
  <test2:Child2 Attribute2="c2">
    <child22 Attribute22="c22">Element22</child22>
  </test2:Child2>
  <test2:Child3 Attribute3="c3">
    <child31>Element31</child31>
  </test2:Child3>
</Root>

这是什么xpath代码?

非常感谢

3 个答案:

答案 0 :(得分:1)

XPath永远不会修改它选择的节点,它只是选择它们。如果您的选择包括(比方说)Root元素,那么在序列化时它将包含输入文档的所有元素,即使您只选择该单个元素。

您可以通过

遍历其祖先或自身轴上没有child21的所有元素
//*[not(ancestor-or-self::child21)]

但是如果你想生成显示的结果,这不是很有用。

使用xslt过滤掉该元素及其后代是微不足道的,只需拥有一个标识模板并添加一个模板

<xsl:template match="child21"/>

丢弃输入的那个分支,但是你不能单独使用XPath。

答案 1 :(得分:0)

要排除child21

的XPath
/Root/*/*[not(local-name()='child21')]

这将结果显示为

child11
child22
child31

根据您的要求进行修改。

答案 2 :(得分:0)

XPath会选择节点,但是如果你想实际复制XML,跳过某些元素你需要的是一个XSLT - 这将产生你想要的输出:

<xsl:stylesheet 
  version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <!-- Template to copy everything-->
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <!-- Template to skip 'child21' elements -->
  <xsl:template match="child21">
  </xsl:template>

</xsl:stylesheet>