Re: [xsl] Merging common XML tree

Subject: Re: [xsl] Merging common XML tree
From: Florent Georges <lists@xxxxxxxxxxxx>
Date: Thu, 8 Jul 2010 03:02:02 -0700 (PDT)
Mathieu Malaterre wrote:

  Hi,

> <dirs>
>   <dir name="A">
>     <dir
name="B">
>       <file name="C">
>     </dir>
>   </dir>
>   <dir name="A">
>
<dir name="B">
>       <file name="D">
>     </dir>
>   </dir>
> </dirs>

>
and my target output tree should looks like:

> <dirs>
>   <dir name="A">
>
<dir name="B">
>       <file name="C">
>       <file name="D">
>     </dir>
>
</dir>
> </dirs>

  I would use recursive grouping:

    <xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
xmlns:xs="http://www.w3.org/2001/XMLSchema";
                    xmlns:my="..."
exclude-result-prefixes="#all"
                    version="2.0">
<xsl:output indent="yes"/>

       <xsl:template match="dirs">
<xsl:copy>
             <xsl:call-template name="my:handle-dirs">
<xsl:with-param name="dirs" select="*"/>
             </xsl:call-template>
</xsl:copy>
       </xsl:template>

       <xsl:template
name="my:handle-dirs">
          <xsl:param name="dirs" as="element(dir)+"/>
<xsl:for-each-group select="$dirs" group-by="@name">
             <dir name="{
current-grouping-key() }">
                <xsl:copy-of
select="current-group()/file"/>
                <xsl:if
test="current-group()/dir">
                   <xsl:call-template
name="my:handle-dirs">
                      <xsl:with-param name="dirs"
select="
                         current-group()/dir"/>
</xsl:call-template>
                </xsl:if>
             </dir>
</xsl:for-each-group>
       </xsl:template>

    </xsl:stylesheet>

  You may
have to adapt the content of the for-each-group for the
precise ordering you
want between files and dirs when a dir
contains both.

  Regards,

-- 
Florent
Georges
http://fgeorges.org/

Current Thread