XSLT复制 - 从1个节点创建2个节点

时间:2016-06-02 01:46:56

标签: xml xslt

我有以下XML:

    <records>
        <record>
            <id>111</id>
            <amount>123.45</amount>
            <taxCode>A</taxCode>
        </record>

    </records>

我需要复制上面的所有节点,但也要创建一些具有特定值的节点的额外副本,比如说,taxCode。 我将如何实现以下目标:

<records>
        <record>
            <id>111</id>
            <amount>123.45</amount>
            <taxCode>A</taxCode>
        </record>

        <!-- copy of the node above with amount and taxCode changed -->
        <record>
            <id>111</id>
            <amount>-123.45</amount>
            <taxCode>B</taxCode>
        </record>
    </records>

我尝试使用以下简单的XSL,但只复制一次:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml"
                encoding="UTF-8"
                omit-xml-declaration="no"
                indent="yes" />

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

    <xsl:template match="records/taxCode[text() = 'A']" >
        <xsl:copy select="node()" />
    </xsl:template>

</xsl:stylesheet>

对此有任何帮助表示赞赏。

2 个答案:

答案 0 :(得分:1)

怎么样:

<xsl:stylesheet version="1.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="records">
    <xsl:copy>
        <xsl:apply-templates/>
        <xsl:apply-templates select="record[taxCode='A']" mode="B"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="record" mode="B">
    <xsl:copy>
        <xsl:copy-of select="id"/>
        <amount>
            <xsl:value-of select="-amount"/>
        </amount>
        <taxCode>B</taxCode>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

或者,如果您愿意:

<xsl:stylesheet version="1.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="record[taxCode='A']" >
    <xsl:copy>
        <xsl:apply-templates/>
    </xsl:copy>
    <xsl:copy>
        <xsl:copy-of select="id"/>
        <amount>
            <xsl:value-of select="-amount"/>
        </amount>
        <taxCode>B</taxCode>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

答案 1 :(得分:1)

这是一个通用转换,它允许动态指定新旧税码之间的映射

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my" exclude-result-prefixes="my">
 <xsl:output omit-xml-declaration="yes"/>

 <my:Mapping>
   <code old="A">B</code>
   <code old="M">P</code>
 </my:Mapping>

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

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

  <xsl:template match="record[taxCode = document('')/*/my:Mapping/*/@old]">
    <xsl:call-template name="identity"/>
    <xsl:apply-templates select="." mode="new"/> 
  </xsl:template>

  <xsl:template mode="new"
       match="record[taxCode = document('')/*/my:Mapping/*/@old]/amount/text()" >
   <xsl:value-of select="-1*."/>
  </xsl:template>

  <xsl:template mode="new"
       match="record[taxCode = document('')/*/my:Mapping/*/@old]/taxCode/text()" >
   <xsl:value-of select="document('')/*/my:Mapping/*[@old = current()]"/>
  </xsl:template>
</xsl:stylesheet>

将此转换应用于以下XML文档

<records>
    <record>
        <id>111</id>
        <amount>123.45</amount>
        <taxCode>A</taxCode>
    </record>
    <record>
        <id>111</id>
        <amount>123.45</amount>
        <taxCode>C</taxCode>
    </record>
    <record>
        <id>111</id>
        <amount>123.45</amount>
        <taxCode>M</taxCode>
    </record>
</records>

产生了想要的正确结果

<records>
    <record>
        <id>111</id>
        <amount>123.45</amount>
        <taxCode>A</taxCode>
    </record><record>
        <id>111</id>
        <amount>-123.45</amount>
        <taxCode>B</taxCode>
    </record>
    <record>
        <id>111</id>
        <amount>123.45</amount>
        <taxCode>C</taxCode>
    </record>
    <record>
        <id>111</id>
        <amount>123.45</amount>
        <taxCode>M</taxCode>
    </record><record>
        <id>111</id>
        <amount>-123.45</amount>
        <taxCode>P</taxCode>
    </record>
</records>

请注意

my:Mapping树通常位于自己独立的XML文档(文件)中,当映射发生更改时,不必更改转换。