Hercules Dev. wrote:
Hi all,
I'm new in xslt and xpath, so my question might be simple but i'm
learning.
I have an XML document and need to transform it into another XML, I use
xslt and it works, but there is a case that i don't know how to solve,
I need to concat a string from multiple childs into a standard way, the
following is an example of the source and the target XML.
Source:
<Root>
<ParentElementX>
<ChildElement>
<Value>1</Value>
<Value>2</Value>
<Value>3</Value>
<ChildElement>
<ChildElement>
<Value>4</Value>
<Value>5</Value>
<Value>6</Value>
<ChildElement>
</ParentElementX>
<ParentElementX>
<ChildElement>
<Value>1</Value>
<Value>2</Value>
<Value>3</Value>
<ChildElement>
</ParentElementX>
</Root>
That's not XML. Assuming you just mistyped it and that the ChildElements
do actually have start-tags and end-tags, and that you also missed a
slash in the "4/5/6" output, then there are two ways:
1. Concatenation using a recursive named template:
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="Root">
<Root>
<xsl:apply-templates/>
</Root>
</xsl:template>
<xsl:template match="ParentElementX">
<ParentElementX>
<xsl:apply-templates/>
</ParentElementX>
</xsl:template>
<xsl:template match="ChildElement">
<ChildElement>
<xsl:call-template name="join-with-slashes">
<xsl:with-param name="children" select="Value"/>
</xsl:call-template>
</ChildElement>
</xsl:template>
<xsl:template name="join-with-slashes">
<xsl:param name="children"/>
<xsl:param name="counter">
<xsl:text>1</xsl:text>
</xsl:param>
<xsl:choose>
<xsl:when test="$counter>=count($children)">
<xsl:text>/</xsl:text>
<xsl:value-of select="$children[$counter]"/>
</xsl:when>
<xsl:otherwise>
<xsl:if test="$counter>1">
<xsl:text>/</xsl:text>
</xsl:if>
<xsl:value-of select="$children[$counter]"/>
<xsl:call-template name="join-with-slashes">
<xsl:with-param name="children" select="$children"/>
<xsl:with-param name="counter" select="$counter+1"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
2. Concatenation using normal templates (much faster):
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="ChildElement"/>
<xsl:template match="Root">
<Root>
<xsl:apply-templates/>
</Root>
</xsl:template>
<xsl:template match="ParentElementX">
<ParentElementX>
<xsl:apply-templates/>
</ParentElementX>
</xsl:template>
<xsl:template match="ChildElement">
<ChildElement>
<xsl:apply-templates/>
</ChildElement>
</xsl:template>
<xsl:template match="Value">
<xsl:value-of select="."/>
<xsl:if test="position()!=last()">
<xsl:text>/</xsl:text>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
///Peter
--
XML FAQ:
http://xml.silmaril.ie