Re: [xsl] Grouping by attribute

Subject: Re: [xsl] Grouping by attribute
From: Jostein Austvik Jacobsen <josteinaj@xxxxxxxxx>
Date: Tue, 20 Oct 2009 12:56:20 +0200
Thats perfect. Many thanks!

-Jostein

2009/10/20 Martin Honnen <Martin.Honnen@xxxxxx>:
> Jostein Austvik Jacobsen wrote:
>>
>> Now, what if I want to replace all <p>-tags with <para>, and change
>> the namespace of all nodes to "foo"?
>
> If the input is
>
> <document>
>  <metaData>
>    <title>Title</title>
>    <publisher>Publisher</publisher>
>  </metaData>
>  <contentSection>
>    <p>text</p>
>
>    <headline level="2">Headline</headline>
>    <p>text</p>
>    <p>text</p>
>
>    <headline level="2">Section</headline>
>    <p>text</p>
>    <pagenum id="page2"/>
>    <p>text</p>
>    <headline level="3">Subsection</headline>
>    <p>text</p>
>
>    <headline level="2">Section</headline>
>    <p>text</p>
>    <p>text</p>
>  </contentSection>
> </document>
>
> then this stylesheet
>
> <xsl:stylesheet
>  xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
>  version="2.0"
>  xmlns:xs="http://www.w3.org/2001/XMLSchema";
>  xmlns:mf="http://example.com/2009/mf";
>  xmlns="http://example.com/foo";
>  exclude-result-prefixes="xs mf">
>
>  <xsl:output indent="yes"/>
>  <xsl:strip-space elements="*"/>
>
>  <xsl:function name="mf:group" as="node()*">
>    <xsl:param name="nodes" as="node()*"/>
>    <xsl:param name="level" as="xs:integer"/>
>    <xsl:for-each-group select="$nodes" group-starting-with="headline[@level
> = $level]">
>      <xsl:choose>
>        <xsl:when test="self::headline[@level = $level]">
>          <xsl:element name="level{$level}">
>            <xsl:element name="h{$level}">
>              <xsl:value-of select="."/>
>            </xsl:element>
>            <xsl:sequence select="mf:group(current-group() except ., $level
+
> 1)"/>
>          </xsl:element>
>        </xsl:when>
>        <xsl:otherwise>
>          <xsl:apply-templates select="current-group()"/>
>        </xsl:otherwise>
>      </xsl:choose>
>    </xsl:for-each-group>
>  </xsl:function>
>
>  <xsl:template match="@* | node()">
>    <xsl:copy>
>      <xsl:apply-templates select="@* | node()"/>
>    </xsl:copy>
>  </xsl:template>
>
>  <xsl:template match="document">
>    <xsl:variable name="v1" xmlns="">
>      <headline level="1"><xsl:value-of select="metaData/title"/></headline>
>      <xsl:copy-of select="contentSection/node()"/>
>    </xsl:variable>
>    <body>
>      <xsl:sequence select="mf:group($v1/node(), 1)"/>
>    </body>
>  </xsl:template>
>
>  <xsl:template match="p">
>    <para>
>      <xsl:apply-templates select="@* | node()"/>
>    </para>
>  </xsl:template>
>
> </xsl:stylesheet>
>
> creates the following output:
>
> <body xmlns="http://example.com/foo";>
>   <level1>
>      <h1>Title</h1>
>      <para>text</para>
>      <level2>
>         <h2>Headline</h2>
>         <para>text</para>
>         <para>text</para>
>      </level2>
>      <level2>
>         <h2>Section</h2>
>         <para>text</para>
>         <pagenum xmlns="" id="page2"/>
>         <para>text</para>
>         <level3>
>            <h3>Subsection</h3>
>            <para>text</para>
>         </level3>
>      </level2>
>      <level2>
>         <h2>Section</h2>
>         <para>text</para>
>         <para>text</para>
>      </level2>
>   </level1>
> </body>
>
> --
>
>        Martin Honnen
>        http://msmvps.com/blogs/martin_honnen/

Current Thread