2016-06-02 3 views
2

У меня есть следующий XML:XSLT копия - сделать 2 узла от 1 узла

<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> 

Любая помощь с этим ценится.

ответ

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

Вот типичное преобразование, которое позволяет сопоставление между старыми и новыми налоговыми-кодов, которые будут задаваться динамически :

<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-документе (файле), и преобразование не нужно изменять, если есть изменения в mappin г.

Смежные вопросы