[xsl] xsl-grouping two different elements together

Subject: [xsl] xsl-grouping two different elements together
From: gregor FELLENZ <gregor@xxxxxxxxxxxx>
Date: Tue, 16 Mar 2010 15:42:14 +0100
hey all,

i've got another grouping problem. i'm a little stuck where to look for.

given the following structure:

<?xml version="1.0" encoding="UTF-8"?>
<kapitel>
	<abs>first</abs>
	<einschub1>first_ein</einschub1>
	<einschub1>second_ein</einschub1>
	<leerzeile/>
	<einschub1>third_ein</einschub1>
	<abs>second</abs>
	<einschub2>first_ein2</einschub2>
	<abs>end</abs>
</kapitel>

this should transform to:

<?xml version="1.0" encoding="UTF-8"?>
<kapitel>
	<abs>first</abs>
	<einschub typ="1">
		<abs>first_ein</abs>
		<abs>second_ein</abs>
		<leerzeile/>
		<abs>third_ein</abs>
	</einschub>
	<abs>second</abs>
	<einschub typ="2">
		<abs>first_ein2</abs>
	</einschub>
	<abs>end</abs>
</kapitel>

my current xslt is:


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
xmlns:xs="http://www.w3.org/2001/XMLSchema"; exclude-result-prefixes="xs" version="2.0">


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

<xsl:template match="kapitel">
<xsl:element name="kapitel">
<xsl:for-each-group select="*" group-adjacent="local-name()" >
<xsl:choose>
<xsl:when test="starts-with(current-grouping-key(),'einschub')">
<xsl:element name="einschub">
<xsl:attribute name="typ" select='replace(local-name(), "[^\d]+", "")'/>
<xsl:apply-templates select="current-group()"/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:element>
</xsl:template>


<xsl:template match="einschub1|einschub2">
<xsl:element name="abs">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>


</xsl:stylesheet>

but this creates two <einschub typ="1"> container. this makes absolutely sense, but i've no idea how to get the <leerzeile> element into the container.

my only idea is to make a 2 pass solution:
1. rename all <leerzeile> elements with a template
... <xsl:when test="preceding-sibling::*[1][starts-with(local-name(),'einschub')] and following-sibling::*[1][starts-with(local-name(),'einschub')] ">
<xsl:element name="{local-name(preceding-sibling::*[1])}"> ...
2. grouping works.



is there any better/more elegant solution? or ideas where to look for?


thanks in advance,
regards,
gregor

Current Thread