[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

Re: [xsl] Copy and group XML


Subject: Re: [xsl] Copy and group XML
From: Michael Kay <mike@xxxxxxxxxxxx>
Date: Wed, 26 Jan 2011 18:53:26 +0000

On 26/01/2011 18:22, Jacobus Reyneke wrote:
Good day, could someone please tell me what I'm doing wrong here.

I'm trying to copy a XML document with 'play' as route. While doing so
I need to group the 'scene' elements under 'act'. The xsl below works
(almost), but throws out anything that falls under play, but outside
of a scene. I need to preserve (copy) elements that are outside of
'scene'.

I would guess that the scenes for a given act are adjacent, so using group-adjacent is preferable to using group-by.


So use

<xsl:for-each-group select="*" group-adjacent="(@act, '?')[1]">
<xsl:choose>
<xsl:when test="@act">
<act>
<xsl:apply-templates select="current-group()"/>
</act>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>

The expression (@act, '?')[1] returns the value of @act if present, or "?" otherwise.

Michael Kay
Saxonica
<?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="play">
             <xsl:for-each-group select="scene"
                 group-by="@act">
                 <act>
                     <xsl:for-each select="current-group()">
                         <xsl:copy>
                             <xsl:apply-templates  select="@*|node()"/>
                         </xsl:copy>
                     </xsl:for-each>
                 </act>
             </xsl:for-each-group>
     </xsl:template>

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

</xsl:stylesheet>

Kind regards,
Jacobus


Current Thread
Keywords