xml - Merge specific elements but keep document order using XSLT 1.0 -
given following document:
<doc> <a>a</a> <b>1</b> <b>2</b> <b>3</b> <c>c</c> </doc>
i want turned into:
<doc> <a>a</a> <b>1,2,3</b> <c>c</c> </doc>
what have far (mostly taken post here @ so):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform"> <xsl:template match="node()|@*"> <xsl:copy> <xsl:apply-templates select="node()|@*" /> </xsl:copy> </xsl:template> <xsl:template match="doc"> <xsl:copy> <xsl:apply-templates select="*[not(self::b)]"/> <b><xsl:apply-templates select="b/text()"/></b> </xsl:copy> </xsl:template> <xsl:template match="b/text()"> <xsl:if test="position() > 1">,</xsl:if> <xsl:value-of select="."/> </xsl:template> </xsl:stylesheet>
this creates following result:
<doc><a>a</a><c>c</c><b>1,2,3</b></doc>
but i'm struggling find solution keeps document order intact. run of <b>
elements should replaced single element containing text of original elements comma separated list. other elements should not reordered.
you can use sibling recursion in different mode:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/xsl/transform" version="1.0"> <xsl:output indent="yes"/> <xsl:strip-space elements="*"/> <xsl:template match="node()|@*"> <xsl:copy> <xsl:apply-templates select="node()|@*" /> </xsl:copy> </xsl:template> <xsl:template match="b[not(preceding-sibling::*[1][self::b])]"> <xsl:copy> <xsl:apply-templates select="." mode="merge"/> </xsl:copy> </xsl:template> <xsl:template match="b[preceding-sibling::*[1][self::b]]"/> <xsl:template match="b" mode="merge"> <xsl:value-of select="."/> <xsl:variable name="next" select="following-sibling::*[1][self::b]"/> <xsl:if test="$next"> <xsl:text>,</xsl:text> <xsl:apply-templates select="$next" mode="merge"/> </xsl:if> </xsl:template> </xsl:stylesheet>
Comments
Post a Comment