复制XML并重命名其部分节点和嵌套节点

时间:2016-01-22 17:04:58

标签: xslt xpath

我需要将所有内容复制到新的XML,除了我需要重命名的一些元素。

作为“node1”的子节点的所有“子节点”我需要重命名为“child”和“child”节点,它们是“node2”的子节点我需要重命名为“kid”。

完美的解决方案将使用

match="/root/node1/descendant::child"

但正如我在迈克尔凯在主题http://comments.gmane.org/gmane.text.xml.saxon.help/14956

中的回应中找到的那样
  

形式/ descendant :: m__id [1]的模式在两者中都是不合法的   XSLT 1.0或XSLT 2.0,虽然它在XSLT 3.0中变得合法。

您是否有任何建议如何在XSLT 2.0中执行此操作而不执行下面的操作?因为我不知道会有多少嵌套。

这是我的xml示例

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <node1>
        <child>
            <subnode>
                <child></child>
            </subnode>
        </child>
        <child>
            <subnode>
                <child></child>
            </subnode>
        </child>
    </node1>
    <node2>
        <child>
            <subnode>
                <child></child>
            </subnode>
        </child>
        <child>
            <subnode>
                <child></child>
            </subnode>
        </child>
    </node2>
</root>

和XSL:

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

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

    <xsl:template match="/root/node1/child">
        <xsl:element name="children">
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="/root/node1/child/subnode/child">
        <xsl:element name="children">
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="/root/node2/child">
        <xsl:element name="kid">
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="/root/node2/child/subnode/child">
        <xsl:element name="kid">
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

3 个答案:

答案 0 :(得分:1)

这对你有用吗?

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

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

<xsl:template match="child[ancestor::node2]">
    <kid>
        <xsl:apply-templates select="@*|node()"/>
    </kid>
</xsl:template>

</xsl:stylesheet>

答案 1 :(得分:1)

您可以在模式中使用//child

<xsl:template match="/root/node1//child">
    <xsl:element name="children">
        <xsl:apply-templates select="@*|node()"/>
    </xsl:element>
</xsl:template>


<xsl:template match="/root/node2//child">
    <xsl:element name="kid">
        <xsl:apply-templates select="@*|node()"/>
    </xsl:element>
</xsl:template>

我会使用文字结果元素而不是xsl:element:

<xsl:template match="/root/node1//child">
    <children>
        <xsl:apply-templates select="@*|node()"/>
    </children>
</xsl:template>


<xsl:template match="/root/node2//child">
    <kid>
        <xsl:apply-templates select="@*|node()"/>
    </kid>
</xsl:template>

答案 2 :(得分:1)

此解决方案根本不使用任何谓词或轴,具有最短匹配模式,因此比使用谓词的效率更高效。< / p>

<node1>有后代或祖先<node2>时,它也会产生预期的正确结果 - 其余解决方案根本无法处理

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

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

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

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

  <xsl:template match="child" mode="node1">
    <children>
      <xsl:apply-templates select="node()|@*" mode="#current"/>
    </children>
  </xsl:template>
  <xsl:template match="child" mode="node2">
    <kid>
      <xsl:apply-templates select="node()|@*" mode="#current"/>
    </kid>
  </xsl:template>
</xsl:stylesheet>

应用于提供的XML文档

<root>
    <node1>
        <child>
            <subnode>
                <child></child>
            </subnode>
        </child>
        <child>
            <subnode>
                <child></child>
            </subnode>
        </child>
    </node1>
    <node2>
        <child>
            <subnode>
                <child></child>
            </subnode>
        </child>
        <child>
            <subnode>
                <child></child>
            </subnode>
        </child>
    </node2>
</root>

产生了想要的正确结果:

<root>
      <node1>
            <children>
                  <subnode>
                        <children/>
                  </subnode>
      </children>
            <children>
                  <subnode>
                        <children/>
                  </subnode>
      </children>
      </node1>
      <node2>
            <kid>
                  <subnode>
                        <kid/>
                  </subnode>
      </kid>
            <kid>
                  <subnode>
                        <kid/>
                  </subnode>
      </kid>
      </node2>
</root>

在此XML文档上应用相同的转换时,<node1><node2>是彼此的后代或祖先

<root>
    <node1>
        <child>
            <subnode>
              <node2>
                  <child></child>
                  <node1>
                    <child/>
                  </node1>            
              </node2>
            </subnode>
        </child>
        <child>
            <subnode>
                <child></child>
            </subnode>
        </child>
    </node1>
    <node2>
        <child>
            <subnode>
                <child></child>
            </subnode>
        </child>
        <node1>
            <child>
                <subnode>
                    <child></child>
                </subnode>
            </child>
        </node1>
        <child>
            <subnode>
                <child></child>
            </subnode>
        </child>
    </node2>
</root>
再次

正确且需要的结果(<child>的替换名称由其最近的祖先<node1><node2>生成)

<root>
      <node1>
            <children>
                  <subnode>
                     <node2>
                           <kid/>
                           <node1>
                              <children/>
                           </node1>           
                     </node2>
                  </subnode>
            </children>
            <children>
                  <subnode>
                        <children/>
                  </subnode>
            </children>
      </node1>
      <node2>
            <kid>
                  <subnode>
                        <kid/>
                  </subnode>
            </kid>
            <node1>
                  <children>
                        <subnode>
                              <children/>
                        </subnode>
                  </children>
            </node1>
            <kid>
                  <subnode>
                        <kid/>
                  </subnode>
            </kid>
      </node2>
</root>