Re: [xsl] Create xml file with recursive childnodes

Subject: Re: [xsl] Create xml file with recursive childnodes
From: "Mukul Gandhi" <gandhi.mukul@xxxxxxxxx>
Date: Thu, 14 Aug 2008 09:27:56 +0530
Hi Chun,
  Thanks for pointing the error. Below is the stylesheet, which has this fix ...

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                       version="2.0">

<xsl:output method="xml" indent="yes" />

<xsl:template match="Objs">
<xsl:variable name="start" select="obj[not(@name = ../obj/@child)]" />
<xsl:variable name="startName" select="distinct-values($start/@name)" />
<Obj name="{$startName}">
   <xsl:for-each select="obj[(@name = $startName) and not(../obj/@name
= @child)]">
     <Obj name="{@child}" />
   </xsl:for-each>
   <xsl:call-template name="makeTree">
     <xsl:with-param name="list" select="obj[@name = $start/@child]" />
   </xsl:call-template>
</Obj>
</xsl:template>


<xsl:template name="makeTree">
  <xsl:param name="list" />

  <Obj name="{$list[1]/@name}">
    <xsl:for-each select="$list">
      <xsl:variable name="child" select="@child" />
      <xsl:choose>
        <xsl:when test="not(../obj[@name = $child])">
          <Obj name="{$child}" />
        </xsl:when>
        <xsl:otherwise>
          <xsl:call-template name="makeTree">
            <xsl:with-param name="list" select="../obj[@name = $child]" />
          </xsl:call-template>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:for-each>
  </Obj>
</xsl:template>

</xsl:stylesheet>

I think, we don't really need for-each-group. I have modified the
stylesheet accordingly, using a normal for-each loop.

Kindly do report any bugs in this version, and I'll attempt to solve it.

On 8/14/08, chun ji <cji_work@xxxxxxxxx> wrote:
> Hi Mukul,
> thank you for 2 solutions. But I see an issue for the
> second one if the root obj has more that 1 child.
>
> For example, if the input xml is :
> "
> <Objs>
>  <obj name="a" child="b"/>
>  <obj name="b" child="c"/>
>  <obj name="b" child="d"/>
>  <obj name="c" child="e"/>
>  <obj name="b" child="f"/>
>  <obj name="a" child="u"/>
> </Objs>
> "
> , I get such results
>
> "
> <?xml version="1.0" encoding="UTF-8"?>
> <Obj name="a a">
>   <Obj name="b">
>      <Obj name="c">
>         <Obj name="e"/>
>      </Obj>
>      <Obj name="d"/>
>      <Obj name="f"/>
>   </Obj>
> </Obj>
> ".
>
>
> Regards,
>
>
>
> Chun
>
>
>
>
>
>
> --- Mukul Gandhi <gandhi.mukul@xxxxxxxxx> wrote:
>
> > Here is a slightly better solution.
> >
> > <xsl:stylesheet
> > xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
> >                        version="2.0">
> >
> > <xsl:output method="xml" indent="yes" />
> >
> > <xsl:template match="Objs">
> >   <xsl:variable name="start" select="obj[not(@name =
> > ../obj/@child)]" />
> >   <Obj name="{$start/@name}">
> >     <xsl:choose>
> >       <xsl:when test="not(obj[@name =
> > $start/@child])">
> >         <Obj name="{$start/@child}" />
> >       </xsl:when>
> >       <xsl:otherwise>
> >         <xsl:call-template name="performGrouping">
> >           <xsl:with-param name="list"
> > select="obj[@name = $start/@child]" />
> >         </xsl:call-template>
> >       </xsl:otherwise>
> >     </xsl:choose>
> >   </Obj>
> > </xsl:template>
> >
> > <xsl:template name="performGrouping">
> >   <xsl:param name="list" />
> >
> >   <xsl:for-each-group select="$list"
> > group-by="@name">
> >     <Obj name="{current-grouping-key()}">
> >       <xsl:for-each select="current-group()">
> >         <xsl:variable name="child" select="@child"
> > />
> >         <xsl:choose>
> >           <xsl:when test="not(../obj[@name =
> > $child])">
> >             <Obj name="{$child}" />
> >           </xsl:when>
> >           <xsl:otherwise>
> >             <xsl:call-template
> > name="performGrouping">
> >       <xsl:with-param name="list" select="../obj[@name =
> > $child]" />
> >             </xsl:call-template>
> >           </xsl:otherwise>
> >         </xsl:choose>
> >       </xsl:for-each>
> >     </Obj>
> >   </xsl:for-each-group>
> > </xsl:template>
> >
> > </xsl:stylesheet>
> >
> > The stylesheet I earlier posted did execution in two
> > pass. This one
> > does the whole processing in a single pass.
> >
> > On Sat, Aug 9, 2008 at 10:44 AM, Mukul Gandhi
> > <gandhi.mukul@xxxxxxxxx> wrote:
> > > The following stylesheet works ...
> >
> > --
> > Regards,
> > Mukul Gandhi


-- 
Regards,
Mukul Gandhi

Current Thread