xsl-list
[Top] [All Lists]

Re: [xsl] RE: Nested list, from flat to structure

2011-02-08 09:35:14
Kjellaug Johansen wrote:
Additional info on this issue: I use XSL version 1.0 and the total
number of levels in the list is unknown.

Here is my attempt at an XSLT 2.0 solution doing any number of levels:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
  xmlns:mf="http://example.com/mf";
  xmlns:xs="http://www.w3.org/2001/XMLSchema";
  exclude-result-prefixes="xs mf"
  version="2.0">

  <xsl:strip-space elements="*"/>
  <xsl:output indent="yes"/>

  <xsl:function name="mf:group" as="node()*">
    <xsl:param name="nodes" as="node()*"/>
    <xsl:param name="level" as="xs:integer"/>
    <xsl:choose>
<xsl:when test="$nodes[self::*[local-name() eq concat('lnum', $level)]]">
        <list>
<xsl:for-each-group select="$nodes" group-starting-with="*[local-name() eq concat('lnum', $level)]">
            <xsl:choose>
<xsl:when test="self::*[local-name() eq concat('lnum', $level)]">
                <point>
                  <xsl:apply-templates select="."/>
<xsl:sequence select="mf:group(current-group() except ., $level + 1)"/>
                </point>
              </xsl:when>
              <xsl:otherwise>
                <xsl:apply-templates select="current-group()"/>
              </xsl:otherwise>
            </xsl:choose>
          </xsl:for-each-group>
        </list>
      </xsl:when>
      <xsl:otherwise>
        <xsl:apply-templates select="$nodes"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:function>

  <xsl:template match="root">
    <xsl:copy>
      <xsl:sequence select="mf:group(*, 1)"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="lnum1 | lnum2 | lp1 | lp2">
    <p>
      <xsl:apply-templates/>
    </p>
  </xsl:template>

</xsl:stylesheet>

With Saxon 9.3 and the input being

<root>
<lnum1>list 1 A</lnum1>
<lp1>list 1 A paragraph</lp1>
<lnum1>list 1 B</lnum1>
<lnum2>list 2 A</lnum2>
<lnum2>list 2 B</lnum2>
<lp2>list 2 paragraph</lp2>
<lnum2>list 2 C</lnum2>
<lnum1>list 1 C</lnum1>
</root>

the result is

<root>
   <list>
      <point>
         <p>list 1 A</p>
         <p>list 1 A paragraph</p>
      </point>
      <point>
         <p>list 1 B</p>
         <list>
            <point>
               <p>list 2 A</p>
            </point>
            <point>
               <p>list 2 B</p>
               <p>list 2 paragraph</p>
            </point>
            <point>
               <p>list 2 C</p>
            </point>
         </list>
      </point>
      <point>
         <p>list 1 C</p>
      </point>
   </list>
</root>

which I think is what you want.


--

        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>