使用XSLT更改节点的位置

时间:2011-04-27 06:35:26

标签: xslt

我正在使用身份转换,在此期间,我需要使用XSLT更改节点的位置。 假设,我有一个像这样的XML:

<root>
    <a>
        <b1>SampleB1</b1>
        <b2>
            <c1>zyx</c1>
            <c2>wvu</c2>
            <c3>tsr</c3>
            <c4>dtg</c4>
            <c5>hkj</c5>
        </b2>
        <b3>SampleB3</b3>
    </a>
</root>

然后我想改变节点'c4'的位置&amp; 'c5'并希望输出为:

<root>
    <c4>dtg</c4>
    <c5>hkj</c5>
    <a>
        <b1>SampleB1</b1>
        <b2>
            <c1>zyx</c1>
            <c2>wvu</c2>
            <c3>tsr</c3>
        </b2>
        <b3>SampleB3</b3>
    </a>
</root>

任何人都可以告诉我,我们怎么能这样做。

谢谢!!!

3 个答案:

答案 0 :(得分:1)

试试这个:

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>

  <!-- By default, recursively copy all nodes unchanged -->
  <xsl:template match="@* | node()">
      <xsl:copy>
          <xsl:apply-templates select="@* | node()"/>
      </xsl:copy>
  </xsl:template>

  <!-- But don't copy root/a/b2/c3 and root/a/b2/c4 -->
  <xsl:template match="root/a/b2/c3" />
  <xsl:template match="root/a/b2/c4" />

  <xsl:template match="root">
    <xsl:copy>
      <!-- Place a copy of a/b2/c3 and a/b2/c4 at the start of root -->
      <xsl:copy-of select="a/b2/c3" />
      <xsl:copy-of select="a/b2/c4" />
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

理解上述内容的关键在于,它不是移动元素,而是复制元素,然后在别处跳过它们。不幸的是,这意味着我们需要指定要移动两次的元素(一次跳过它们然后再次将它们的副本包含在其他位置),但目前我无法想到更简洁的方式。

这个问题 - Move sub nodes into parent attributes with XSLT也可能有所帮助。

答案 1 :(得分:1)

纯拉风格:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:strip-space elements="*"/>
    <xsl:template match="node()|@*" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="a">
        <xsl:apply-templates mode="search"/>
        <xsl:call-template name="identity"/>
    </xsl:template>
    <xsl:template match="c4|c5"/>
    <xsl:template match="c4|c5" mode="search">
        <xsl:call-template name="identity"/>
    </xsl:template>
    <xsl:template match="text()" mode="search"/>
</xsl:stylesheet>

输出:

<root>
    <c4>dtg</c4>
    <c5>hkj</c5>
    <a>
        <b1>SampleB1</b1>
        <b2>
            <c1>zyx</c1>
            <c2>wvu</c2>
            <c3>tsr</c3>
        </b2>
        <b3>SampleB3</b3>
    </a>
</root>

答案 2 :(得分:0)

要重新排列,您需要调整XSL,以便在您想要的顺序和位置中复制您想要的内容。例如:

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

    <!-- At the root element, recurse through any descendant c4 or c5 nodes first -->
    <xsl:template match="root">
        <xsl:copy>
            <xsl:apply-templates select="//c4|//c5"/>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

    <!-- At the b2 element, copy everything but the C4 or C5 nodes -->
    <xsl:template match="b2">
        <xsl:copy>
            <xsl:apply-templates select="node()[not(self::c4|self::c5)]|@*"/>
        </xsl:copy>
    </xsl:template>

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

</xsl:stylesheet>