Reputation: 127
I have to transform this sample xml in xslt 1.0 or xslt 2.0 Source XML
<root>
<group>
<subgroup>
<name>AAA1</name>
</subgroup>
<subgroup>
<name>AAA2</name>
</subgroup>
<subgroup>
<name>AAA3</name>
</subgroup>
</group>
<group>
<subgroup>
<name>BB1</name>
</subgroup>
<subgroup>
<name>BB2</name>
</subgroup>
<subgroup>
<name>BB3</name>
</subgroup>
</group>
</root>
Required XML OUTPUT
<?xml version="1.0" encoding="UTF-8"?>
<root>
<group>AAA1|BB1|AAA2|BB2|AAA3|BB3</group>
</root>
I tried the following xslt:
XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:template match="root">
<root>
<group>
<xsl:for-each select="group">
<xsl:for-each select="subgroup">
<xsl:choose>
<xsl:when test="position() != last()">
<xsl:value-of select="name" /><xsl:text>|</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="name" />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:for-each>
</group>
</root>
</xsl:template>
</xsl:stylesheet>
Current-output
<?xml version="1.0" encoding="UTF-8"?>
<root>
<group>AAA1|AAA2|AAA3BB1|BB2|BB3</group>
</root>
How can I do this? Should I create a template a call it recursively?
Upvotes: 0
Views: 1686
Reputation: 122374
You need to process just one of the sets of spec
elements, and pull out the corresponding spec
from the other set by position:
<root>
<group>
<xsl:for-each select="group[1]/spec">
<xsl:variable name="pos" select="position()"/>
<xsl:for-each select="../../group">
<!-- put a | in front of everything but the first spec in the first group -->
<xsl:if test="$pos > 1 or position() > 1">|</xsl:if>
<xsl:value-of select="spec[$pos]/name" />
</xsl:for-each>
</xsl:for-each>
</group>
</root>
XSLT 2.0 version: in 2.0 you can do it with a single value-of
:
<group>
<xsl:value-of select="for $n in 1 to count(group[1]/spec)
return (group/spec[$n]/name)" separator="|" />
</group>
Upvotes: 1
Reputation: 640
Came up with this:
Picked up the all other groups except the first and then iterated over all specs for first group while picking up the corresponding specs from all other groups
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:template match="root">
<root>
<group>
<xsl:variable name="firstExcludeGroups" select="//group[position()!=1]"/>
<xsl:variable name="firstGroup" select="//group[position()=1]"/>
<xsl:for-each select="$firstGroup/spec">
<xsl:value-of select="name"/>
<xsl:text>|</xsl:text>
<xsl:variable name="curPosition" select="position()"/>
<xsl:for-each select="$firstExcludeGroups/spec">
<xsl:if test="$curPosition=position()">
<xsl:value-of select="name"/>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</group>
</root>
</xsl:template>
</xsl:stylesheet>
Upvotes: 0