Reputation: 25
If <animal>
has more than 1 <xxx>
then i need to duplicate <animal>
(duplicate count = count of repeating <xxx>
within the corresponding<animal>
) and move the repeating <xxx>
into another copy.
In my xml <xxx>
is repeating twice for the first instance of <animal>
, so in output i need to have two <animals>
. The first <animal>
should contain first instance of <xxx>
and second <animal>
should contain second instance of <xxx>
Input 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>
Required required transformation
<?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>
Any help is much appriciated. Thanks in advance
Upvotes: 0
Views: 197
Reputation: 2187
My solutions typically are not the most elegant, but this would produce the desired output - have a look...
<?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() > 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>
Upvotes: 2