RE: [xsl] xsl-grouping two different elements together

Subject: RE: [xsl] xsl-grouping two different elements together
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Tue, 16 Mar 2010 16:11:39 -0000
group-starting-with="abs" would solve the problem for this example, but I've
no idea if it solves the general problem.

Regards,

Michael Kay
http://www.saxonica.com/
http://twitter.com/michaelhkay 

 

> -----Original Message-----
> From: gregor FELLENZ [mailto:gregor@xxxxxxxxxxxx] 
> Sent: 16 March 2010 14:42
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: [xsl] xsl-grouping two different elements together
> 
> 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(),'einsch
> ub')]  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