Re: [xsl] nesting flat XML based on attribute value.

Subject: Re: [xsl] nesting flat XML based on attribute value.
From: David Holden <dh@xxxxxxxx>
Date: Wed, 14 Dec 2005 13:14:20 +0000
On Wednesday 14 Dec 2005 11:46, Michael Kay wrote:
> > It seems that for each section the recursion groups them
> > nicely but then when
> > it exist the recursion it applies the same again to <sec>
> > tags that have
> > already been grouped therefore sec's are getting output twice, e.g.
>
> Then your template rule for the "ch" element (which you haven't shown us,
> and which I didn't actually write for you) appears not to be selecting the
> "top-level" sections, but is actually processing all of the sections.
>
> I didn't supply this code because I don't know your data well enough. It
> might be that all sec elements with an 8-character id value are top-level,
> or the rule might be more complicated.
>
> Michael Kay
> http://www.saxonica.com/


Yep your right of course (I would say I was being dumb but I don't do XSL
every day).

Many thanks.

 The working (for sec id num's under 10) sheet is:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
    <xsl:output indent="yes"/>
    <xsl:output encoding="US-ASCII"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match="/">
        <xsl:apply-templates/>
    </xsl:template>
    <xsl:template match="ch">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:apply-templates select="./sec[string-length(@id)=8]"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="sec">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:apply-templates
select="//sec[string-length(@id)=string-length(current()/@id)+2 and
starts-with(@id, current()/@id)]"/>
        </xsl:copy>
    </xsl:template>
    <!-- Identity -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>



>
> > <?xml version="1.0" encoding="iso-8859-1"?>
> > <doc>
> >     <ch id="1o1">
> >         <sec id="sec1o1o1" fpage="3" lpage="5"/>
> >         <sec id="sec1o1o1o1" fpage="3" lpage="3"/>
> >         <sec id="sec1o1o1o2" fpage="3" lpage="4"/>
> >         <sec id="sec1o1o1o3" fpage="4" lpage="4"/>
> >         <sec id="sec1o1o1o4" fpage="4" lpage="5"/>
> >         <sec id="sec1o1o1o5" fpage="5" lpage="5"/>
> > ...
> >
> > goes to
> >
> > <?xml version="1.0"?>
> > <doc>
> >     <ch id="1o1">
> >         <sec id="sec1o1o1" fpage="3" lpage="5">
> >             <sec id="sec1o1o1o1" fpage="3" lpage="3"/>
> >             <sec id="sec1o1o1o2" fpage="3" lpage="4"/>
> >             <sec id="sec1o1o1o3" fpage="4" lpage="4"/>
> >             <sec id="sec1o1o1o4" fpage="4" lpage="5"/>
> >             <sec id="sec1o1o1o5" fpage="5" lpage="5"/>
> >         </sec>
> >         <!-- these have already been output -->
> >         <sec id="sec1o1o1o1" fpage="3" lpage="3"/>
> >         <sec id="sec1o1o1o2" fpage="3" lpage="4"/>
> >         <sec id="sec1o1o1o3" fpage="4" lpage="4"/>
> >         <sec id="sec1o1o1o4" fpage="4" lpage="5"/>
> >         <sec id="sec1o1o1o5" fpage="5" lpage="5"/>
> >
> > it needs to some how remember what it has already grouped
> > (sorry for the
> > procedural thinking here.)
> >
> > This isn't too much of a problem in this case because I can
> > remove those extra
> > sec tags with a second script based on depth.
> >
> >    Dave.
> >
> > > The key to this is to do a recursive descent using
> >
> > xsl:apply-templates, but
> >
> > > instead of selecting the physical children of the current
> >
> > node in the XML
> >
> > > tree as you normally would, you select the *logical*
> >
> > children, for example
> >
> > > <xsl:template match="sec">
> > > <xsl:copy>
> > >   <xsl:apply-templates select=
> > >      "//sec[string-length(@id)=string-length(current()/@id)+2 and
> > > starts-with(@id, current()/@id)]"/>
> > > </xsl:copy>
> > > </xsl:template>
> > >
> > > Michael Kay
> > > http://www.saxonica.com/
> > >
> > > > -----Original Message-----
> > > > From: David Holden [mailto:dh@xxxxxxxx]
> > > > Sent: 13 December 2005 17:39
> > > > To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> > > > Subject: [xsl] nesting flat XML based on attribute value.
> > > >
> > > >
> > > >
> > > > Hello,
> > > >
> > > >  I'm not sure whether I'm being dumb or not here but I'm
> > > > stuck on converting a
> > > > flat structure to a nested structure.
> > > >
> > > > the flat structure is like this:-
> > > >
> > > > <?xml version="1.0 " encoding="US-ASCII"?>
> > > > <doc>
> > > >   <ch id="1o1">
> > > >     <sec id="sec1o1o1" fpage="3" lpage="5" />
> > > >     <sec id="sec1o1o1o1" fpage="3" lpage="3"/>
> > > >     <sec id="sec1o1o1o2" fpage="3" lpage="4"/>
> > > >     <sec id="sec1o1o1o3" fpage="4" lpage="4"/>
> > > >     <sec id="sec1o1o1o4" fpage="4" lpage="5"/>
> > > >     <sec id="sec1o1o1o5" fpage="5" lpage="5"/>
> > > >     <sec id="sec1o1o2" fpage="5" lpage="7"/>
> > > >     <sec id="sec1o1o2o1" fpage="5" lpage="5"/>
> > > >     <sec id="sec1o1o2o2" fpage="5" lpage="5"/>
> > > >     <sec id="sec1o1o2o3" fpage="5" lpage="6"/>
> > > >     <sec id="sec1o1o2o4" fpage="6" lpage="7"/>
> > > >     <sec id="sec1o1o2o4o1" fpage="6" lpage="6"/>
> > > >     <sec id="sec1o1o2o4o2" fpage="6" lpage="6"/>
> > > >     <sec id="sec1o1o2o4o3" fpage="6" lpage="7"/>
> > > >     <sec id="sec1o1o3" fpage="7" lpage="10"/>
> > > >     <sec id="sec1o1o3o1" fpage="7" lpage="7"/>
> > > >     <sec id="sec1o1o3o1o1" fpage="7" lpage="7"/>
> > > >   </ch>
> > > > </doc>
> > > >
> > > > I would like to get to
> > > >
> > > > <?xml version="1.0" encoding="US-ASCII"?>
> > > > <doc>
> > > >   <ch id="1o1">
> > > >     <sec id="sec1o1o1" fpage="3" lpage="5">
> > > >       <sec id="sec1o1o1o1" fpage="3" lpage="3"/>
> > > >       <sec id="sec1o1o1o2" fpage="3" lpage="4"/>
> > > >       <sec id="sec1o1o1o3" fpage="4" lpage="4"/>
> > > >       <sec id="sec1o1o1o4" fpage="4" lpage="5"/>
> > > >       <sec id="sec1o1o1o5" fpage="5" lpage="5"/>
> > > >     </sec>
> > > >     <sec id="sec1o1o2" fpage="5" lpage="7">
> > > >       <sec id="sec1o1o2o1" fpage="5" lpage="5"/>
> > > >       <sec id="sec1o1o2o2" fpage="5" lpage="5"/>
> > > >       <sec id="sec1o1o2o3" fpage="5" lpage="6"/>
> > > >       <sec id="sec1o1o2o4" fpage="6" lpage="7">
> > > >         <sec id="sec1o1o2o4o1" fpage="6" lpage="6"/>
> > > >         <sec id="sec1o1o2o4o2" fpage="6" lpage="6"/>
> > > >         <sec id="sec1o1o2o4o3" fpage="6" lpage="7"/>
> > > >       </sec>
> > > >     </sec>
> > > >     <sec id="sec1o1o3" fpage="7" lpage="10">
> > > >       <sec id="sec1o1o3o1" fpage="7" lpage="7">
> > > >         <sec id="sec1o1o3o1o1" fpage="7" lpage="7"/>
> > > >       </sec>
> > > >     </sec>
> > > >   </ch>
> > > > </doc>
> > > >
> > > > i.e.  both the nesting "level" and "order" are in the id
> >
> > attribute.
> >
> > > > any tips appreciated.
> > > >
> > > >  Dave.
> >
> > --
> > Dr. David Holden.
> > Please avoid sending me Word or PowerPoint attachments, thanks.
> > See: <http://www.gnu.org/philosophy/no-word-attachments.html>
> > Public GPG key available on request.
> > -------------------------------------------------------------

Current Thread