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代码是什么?

非常感谢

XPath从不修改它选择的节点,它只是选择它们。如果您的选择包括(比如)Root元素,那么当序列化时,它将包括输入文档的所有元素,即使您只选择了一个元素。

通过,您可以迭代所有祖先或自轴中没有child21的元素

//*[not(ancestor-or-self::child21)]

但是,如果您想要生成所显示的结果,那么这并不是很有用。

使用xslt过滤掉该元素及其子元素很简单,只需有一个标识模板并添加一个单一模板

<xsl:template match="child21"/>

它丢弃了输入的那个分支,但您不能单独使用XPath。

XPath以排除child21

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

这给出了的结果

child11
child22
child31

根据您的要求进行修改。

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>