RE: [xsl] group by tags

Subject: RE: [xsl] group by tags
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Wed, 2 Jul 2008 10:57:13 +0100
A bit tricky, this one!

I think I would tackle it by first flattening the structure into something
like this:

<Book rdf:ID="boo2">
   <address rdf:dataytpe="aaa" path="">Almogavers 56</address>
   <month rdf:dataytpe="bbb" path="event/Inbook">July</month>
   <year rdf:dataytpe="ccc" path="event/Inbook">2006</year>
   <year rdf:dataytpe="ddd" path="proceedings/Proceedings">2008</year>
   <month rdf:dataytpe="ddd" path="proceedings/Proceedings">May</month>

etc.

That part can be done by

<xsl:for-each select="//*[not(*)]">
  <xsl:copy>
    <xsl:copy-of select="@*"/>
    <xsl:attribute name="path" select="string-join(ancestor::*/name(),
'/')"/>
  </xsl:copy>
</xsl:for-each>

Then you can construct the output with

<xsl:for-each-group select="*" group-by="@path">
  <xsl:sequence select="f:nest(tokenize(@path, '/'), current-group())"/>
</xsl:for-each>

using the recursive function

<xsl:function name="f:nest" as="element()*">
  <xsl:param name="path" as="xs:string*"/>
  <xsl:param name="content" as="element()*"/>
  <xsl:choose>
    <xsl:when test="exists($path)">
      <xsl:element name="{$path[1]}">
         <xsl:sequence select="f:nest(remove($path, 1), $content)"/>
      </xsl:element>
    </xsl:when>
    <xsl:otherwise>
       <xsl:sequence select="$content"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:function>

Not tested. Needs refinement if namespaces are involved. 

Michael Kay
http://www.saxonica.com/

> -----Original Message-----
> From: IZASKUN GUTIERREZ GUTIERREZ 
> [mailto:igutierrez027@xxxxxxxxxxxxx] 
> Sent: 02 July 2008 10:22
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: [xsl] group by tags
> 
> Hello everybody!
> 
> I need group by tags this xml for example. The problem is 
> that I dont know the name of the tags. Only I know the tag 
> "Book" and the ID "boo2". I dont know too the extension of de 
> levels of the subtrees, but the groupment must be make by the 
> tags that are writed in lowercase, and only group by tags 
> writed in upperecase if the tags are the same. (I dont 
> control all of the data). I need one generic template .
> 
> 
> <?xml version="1.0"?>
> <rdf:RDF   xmlns:foaf="http://xmlns.com/foaf/0.1/";
>      xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";>
> 
> <Book rdf:ID="boo2">
>     <address rdf:dataytpe="aaa">Almogavers 56</address>
> 
>     <event>
>        <Inbook>
>           <month rdf:dataytpe="bbb">July</month>
>        </Inbook>
>     </event>
>     <event>
>        <Inbook>
>           <year rdf:dataytpe="ccc">2006</year>
>        </Inbook>
>     </event>
> 
>     <proceedings>
>        <Proceedings>
>          <year rdf:dataytpe="ddd">2008</year>
>        </Proceedings>
>     </proceedings>
>     <proceedings>
>        <Misc>
>          <month rdf:dataytpe="ddd">May</month>
>        </Misc>
>     </proceedings>
> 
>     <art>
>        <Manual>
>             <man>
>                 <Article>
>                     <month rdf:dataytpe="nnn">September</month>
>                 </Article>
>             </man>
>             <city rdf:dataytpe="ppp">September</city>
>        </Manual>
>     </art>
>     <art>
>        <Manual>
>             <man>
>                  <Article>
>                    <year rdf:dataytpe="eee">2004</year>
>                  </Article>
>             </man>
>        </Manual>
>     </art>
> 
> 
> </Book>
> 
> </rdf:RDF>
> 
> 
> 
> I want this result:
> 
> <?xml version="1.0"?>
> <rdf:RDF   xmlns:foaf="http://xmlns.com/foaf/0.1/";
>      xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";>
> <Book rdf:ID="boo2">
>     <address rdf:dataytpe="aaa">Almogavers 56</address>
> 
>     <event>
>        <Inbook>
>           <month rdf:dataytpe="bbb">July</month>
>           <year rdf:dataytpe="ccc">2006</year>
>        </Inbook>
>     </event>
> 
> 
>     <proceedings>
>        <Proceedings>
>          <year rdf:dataytpe="ddd">2008</year>
>        </Proceedings>
>        <Misc>
>          <month rdf:dataytpe="ddd">May</month>
>        </Misc>
>     </proceedings>
> 
>     <art>
>        <Manual>
>             <man>
>                 <Article>
>                     <month rdf:dataytpe="nnn">September</month>
>                     <year rdf:dataytpe="eee">2004</year>
>                 </Article>
>             </man>
>             <city rdf:dataytpe="ppp">September</city>
>        </Manual>
>     </art>
> 
> 
> </Book>
> 
> </rdf:RDF>
> 
> 
> 
> Anybody can help me ?
> 
> Thank you, Regards
> 
> IZASKUN

Current Thread