xsl-list
[Top] [All Lists]

Re: [xsl] Grouping by attribute

2009-10-20 06:43:16
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[(_at_)level = $level]">
      <xsl:choose>
        <xsl:when test="self::headline[(_at_)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/

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--

<Prev in Thread] Current Thread [Next in Thread>