将重复元素移动到其父级的副本中

时间:2016-05-28 16:51:07

标签: xml xslt-1.0

如果<animal>超过1 <xxx>,那么我需要复制<animal>(重复计数=在相应的<xxx>内重复<animal>的计数)和将重复的<xxx>移到另一个副本中。

在我的xml中<xxx><animal>的第一个实例重复两次,因此在输出中我需要有两个<animals>。第一个<animal>应包含<xxx>的第一个实例,第二个<animal>应包含<xxx>的第二个实例

输入xml

<?xml version="1.0" encoding="UTF-8"?>
<header>
    <animal>
        <element1>element1</element1>
        <element2>element2</element2>
        <element3 lang="en">element3</element3>
        <xxx>
            <code>YY</code>
            <description>code yy</description>
        </xxx>
        <xxx>
            <code>ZZ</code>
            <description>code zz</description>
        </xxx>
    </animal>
    <animal>
        <xxx>
            <code>AA</code>
            <description>code aa</description>
        </xxx>
    </animal>
</header>

必需的转换

<?xml version="1.0" encoding="UTF-8"?>
<header>
    <animal>
        <element1>element1</element1>
        <element2>element2</element2>
        <element3 lang="en">element3</element3>
        <xxx>
            <code>YY</code>
            <description>code yy</description>
        </xxx>        
    </animal>
    <animal>
        <element1>element1</element1>
        <element2>element2</element2>
        <element3 lang="en">element3</element3>        
        <xxx>
            <code>ZZ</code>
            <description>code zz</description>
        </xxx>
    </animal>
    <animal>
        <xxx>
            <code>AA</code>
            <description>code aa</description>
        </xxx>
    </animal>
</header>

任何帮助都很受欢迎。提前致谢

1 个答案:

答案 0 :(得分:2)

我的解决方案通常不是最优雅的,但这会产生所需的输出 - 看看......

<?xml version="1.0" encoding="utf-8" standalone="yes"?>

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


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

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

<xsl:template match="animal">
    <xsl:param name="i" select="xxx[1]"/>
    <xsl:variable name="thisanimal" select="."/>
    <xsl:choose>
        <xsl:when test="count(xxx) = 1">
            <!-- only one here -->
            <xsl:copy-of select="."/>
        </xsl:when>
        <xsl:when test="$i = xxx[1]">
            <!-- more than one here, use the first -->
            <xsl:copy>
                <xsl:apply-templates select="*[name() != 'xxx']"/>
                <xsl:apply-templates select="$i"/>
            </xsl:copy>
            <xsl:for-each select="xxx[position() &gt; 1]">
                <xsl:apply-templates select="$thisanimal">
                    <xsl:with-param name="i" select="."/>
                </xsl:apply-templates>
            </xsl:for-each>
        </xsl:when>
        <xsl:otherwise>
            <!-- more than one here -->
            <xsl:copy>
                <xsl:apply-templates select="*[name() != 'xxx']"/>
                <xsl:apply-templates select="$i"/>
            </xsl:copy>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

</xsl:transform>