p2p.wrox.com Forums

Need to download code?

View our list of code downloads.


  Return to Index  

xslt thread: Need to radically re-arrange an arbitrarily nested XML tree


Message #1 by "David Moss" <mossd@s...> on Tue, 31 Jul 2001 11:44:51
That's the answer! It works like a charm. Thank you very much for the help.
What an elegant solution. I knew there was a better way than the way I was
trying it. Still thinking far too "procedurally" for my own good. Fancy me
wondering whether or not XSLT was up to the job!?!?! hehehe :) Thanks again.

Extremely happy and very grateful,

David Moss


> -----Original Message-----
> From: atruong@o... [SMTP:atruong@o...]
> Sent: Tuesday, July 31, 2001 6:21 PM
> To: P2P_XSLT
> Subject: [xslt] Re: Need to radically re-arrange an arbitrarily
> nested XML tree
> 
> Hi,
> 
> I'm not sure if this stylesheet is completely robust, but when I ran it 
> with your initial input it correctly picked up on the fact that Data6 and 
> Data7 should be listed in reverse order, and Data4 is actually one level 
> down.
> 
> Give it a whirl:
> 
> XSL:
> ----
> <?xml version="1.0"?>
> <xsl:stylesheet
>     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>     version="1.0">
> <xsl:output method="text"/>
> 
> 
> <xsl:template match="Contents">
>  <xsl:apply-templates select="node|nodeList">
>   <xsl:with-param name="level" select="1"/>
>  </xsl:apply-templates>
> </xsl:template>
> 
> <xsl:template match="node">
> <xsl:param name="level"/>
>  <xsl:call-template name="getLabel">
>   <xsl:with-param name="level" select="$level"/>
>  </xsl:call-template>
> </xsl:template>
> 
> <xsl:template match="nodeList">
> <xsl:param name="level"/>
>  <xsl:call-template name="getLabel">
>   <xsl:with-param name="level" select="$level"/>
>  </xsl:call-template>
>  <xsl:call-template name="getNodeList">
>   <xsl:with-param name="level" select="$level"/>
>  </xsl:call-template>
> </xsl:template>
> 
> <xsl:template name="getLabel">
> <xsl:param name="level"/>
>  <xsl:choose>
>   <xsl:when test="position()=1">
>    <xsl:text>
</xsl:text>
>    <xsl:text>Label </xsl:text>
>    <xsl:value-of select="$level"/>
>    <xsl:text> [</xsl:text>
>    <xsl:call-template name="getNodes">
>     <xsl:with-param name="currentNode" 
> select="."/>
>    </xsl:call-template>
>    <xsl:text>]</xsl:text>
>   </xsl:when>
>  </xsl:choose>
> </xsl:template>
> 
> <xsl:template name="getNodeList">
> <xsl:param name="level"/>
>  <xsl:apply-templates select="node|nodeList">
>   <xsl:with-param name="level">
>    <xsl:value-of select="$level"/>
>    <xsl:text>_</xsl:text>
>    <xsl:value-of select="position()"/>
>   </xsl:with-param>
>  </xsl:apply-templates>
> </xsl:template>
> 
> <xsl:template name="getNodes">
> <xsl:param name="currentNode"/>
>  <xsl:for-each select="$currentNode|$currentNode/following-
> sibling::*">
>   <xsl:choose>
>    <xsl:when test="@desc">
>     <xsl:value-of select="@desc"/>
>    </xsl:when>
>    <xsl:otherwise>
>     <xsl:value-of select="."/>
>    </xsl:otherwise>
>   </xsl:choose>
>   <xsl:if test="following-sibling::*">
>    <xsl:text>,</xsl:text>
>   </xsl:if> 
>  </xsl:for-each> 
> </xsl:template>
> 
> </xsl:stylesheet>
> 
> XML:
> ----
> <?xml version="1.0"?>
> <Contents>
>     <node>Data1</node>
>     <node>Data2</node>
>     <nodeList desc="Data3">
>         <node>Data5</node>
>         <nodeList desc="Data7">
>             <node>Data8</node>
>             <node>Data9</node>
>         </nodeList>
>         <node>Data6</node>
>      <node>Data4</node>
>     </nodeList>
> </Contents>
> 
> 
> Output:
> -------
> Label 1 [Data1,Data2,Data3]
> Label 1_3 [Data5,Data7,Data6,Data4]
> Label 1_3_2 [Data8,Data9]
> 
> 
> 
> 
> > Dear All,
> > 
> > I've seen a few examples regarding "flattening" an XML structure but the
> 
> > issue I'm having hasn't been addressed in anything I've read yet.
> > 
> > I have an XML structure with an arbitrary number of nested levels :-
> > 
> >     <node>Data1</node>
> >     <node>Data2</node>
> >     <nodeList desc="Data3">
> >         <node>Data5</node>
> >         <nodeList desc="Data7">
> >             <node>Data8</node>
> >             <node>Data9</node>
> >         </nodeList>
> >         <node>Data6</node>
> >     <node>Data4</node>
> >     </nodeList>
> > 
> > I'm trying to generate some text output in this flattened form :-
> > 
> >     Level 1
> >     [
> >         Data1, Data2, Data3, Data4
> >     ]
> > 
> >     Level 1_3
> >     [
> >         Data5, Data6, Data7
> >     ]
> > 
> >     Level 1_3_2
> >     [
> >         Data8, Data9
> >     ]
> > 
> > I am using <xsl:template-call>'s recursively to visit each node which is
> 
> > generating all the information I require for the level string. However, 
> > I'm having a problem with how to actually re-arrange the output format 
> > i.e. I'm failng miserably really. I'm sure it probably has a simple 
> > solution but I've got programmer's block!
> > 
> > I would appreciate some input on this nasty problem.
> > 
> > Thanks and regards
> > 
> > David Moss
> > 

  Return to Index