XPath表达式以排除某些子节点

时间:2013-05-25 11:47:38

标签: xslt xpath

我有这个源XML树:

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <foo>
    <bar>
      <baz>
        <item>
          <methods>
            <item>
              <id>1</id>
            </item>
          </methods>
          <id>1</id>
        </item>
        <item>
          <methods>
            <item>
              <id>19</id>
            </item>
          </methods>
          <id>2</id>
        </item>
      </baz>
    </bar>
  </foo>
  <bar_method>
    <root>
      <bla id="1">
        <methods>
          <method id="1">
            <calc md="ck" />
            <tm m="14" />
            <price_list>
              <price mse="0">
                <ins re="0" />
              </price>
            </price_list>
          </method>
          <method id="2">
            <calc md="qck" />
            <tm m="4" />
            <price_list>
              <price mse="1">
                <ins re="0" />
              </price>
            </price_list>
          </method>
        </methods>
      </bla>
      <bla id="2">
        <methods>
          <method id="19">
            <calc md="dd" />
            <tm m="3" />
            <price_list>
              <price mse="01">
                <ins re="0" />
              </price>
            </price_list>
          </method>
        </methods>
      </bla>
    </root>
  </bar_method>
</root>

现在我需要使用XPath将此树的片段放在变量中。该片段应如下所示:

<bla id="1">
  <methods>
    <method id="1">
      <calc md="ck" />
      <tm m="14" />
      <price_list>
        <price mse="0">
          <ins re="0" />
        </price>
      </price_list>
    </method>
  </methods>
</bla>
<bla id="2">
  <methods>
    <method id="19">
      <calc md="dd" />
      <tm m="3" />
      <price_list>
        <price mse="01">
          <ins re="0" />
        </price>
      </price_list>
    </method>
  </methods>
</bla>

这些bla个节点不包括method个节点,id/root/foo/bar/baz/item/methods/item/id个属性在<xsl:variable name="meth" select="/root/bar_method/root//*[not(name() = 'method' and count(/root/foo/bar/baz//methods/item[id = @id]) = 0)]" /> 中丢失。我使用以下表达式,但它选择所有重复的节点:

{{1}}

2 个答案:

答案 0 :(得分:1)

XPath只能选择节点,不能更改它们。也就是说,您选择的节点的子节点和子节点将始终与源文档中的节点完全相同。

如果要创建与输入树不同的树,则需要XSLT或XQuery。

答案 1 :(得分:0)

您希望所有bla元素和每个元素中只有第一个methods/method元素。是吗?

您不能在单个XPath表达式中执行此操作,因为您只能限制所选的元素 - 您也不能过滤掉它们的一些后代。但是可以使用模板。

此样式表创建变量$meth并使用copy-of输出。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:strip-space elements="*"/>
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>

  <xsl:template match="/">
    <xsl:variable name="meth">
      <xsl:apply-templates select="root/bar_method/root/bla"/>
    </xsl:variable>
    <xsl:copy-of select="$meth"/>
  </xsl:template>

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

  <xsl:template match="methods">
    <xsl:copy>
      <xsl:apply-templates select="method[1]"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

<强>输出

<bla id="1">
   <methods>
      <method id="1">
         <calc md="ck"/>
         <tm m="14"/>
         <price_list>
            <price mse="0">
               <ins re="0"/>
            </price>
         </price_list>
      </method>
   </methods>
</bla>
<bla id="2">
   <methods>
      <method id="19">
         <calc md="dd"/>
         <tm m="3"/>
         <price_list>
            <price mse="01">
               <ins re="0"/>
            </price>
         </price_list>
      </method>
   </methods>
</bla>