xsl-list
[Top] [All Lists]

Re: [xsl] flat list of contents and for-each-group

2009-08-20 07:23:25
Stanislav Pejša wrote:

my input xml file looks like this:

<book>
  <title>SomeTitle</title>
  <description>SomeDescription</description>
  <b_part><level_name>Chapter I: Title of Chapter I</level_name></b_part>
  <b_part><level_name>Section 1: Title of section 1</level_name></b_part>
  <b_part><level_name>Part 1: Title of Part 1</level_name></b_part>
  <b_part><level_name>Part 2: Title of Part 2</level_name></b_part>
  <b_part><level_name>Part n: Title of Part n </level_name></b_part>
  <b_part><level_name>Section 2: Title of Part 2</level_name></b_part>
  <b_part><level_name>Part 1: Title of Part 1</level_name></b_part>
  <b_part><level_name>Part n: Title of Part n</level_name></b_part>
  <b_part><level_name>Chapter II: Title of Chapter II</level_name></b_part>
  <b_part><level_name>A) Title of Section A</level_name></b_part>
  <b_part><level_name>A/1 Title of Part 1</level_name></b_part>
  <b_part><level_name>A/n Title of Part n</level_name></b_part>
  <b_part><level_name>B) Title of Section A</level_name></b_part>
  <b_part><level_name>B/1 Title of Part 1</level_name></b_part>
  <b_part><level_name>B/n Title of Part n</level_name></b_part>
</book>
[snip]

desired output:

<book>
  <title>Some title</title>

  <toc> <p>paragraph</p>
  <chapter><title>Chapter I: Title of Chapter I</title>
  <section><title>Section 1: Title of Section 1</title>
  <part><title>Part 1: Title of Part 1</title></part>
    <part><title>Part 2: Title of Part 2</title></part>
   <part><title>Part n: Title of Part n</title></part>
  </section>
   <section><title>Section 2: Title of Section 2</title></section>
    <part><title>Part 1: Title of Part 1</title></part>
    <part><title>Part n: Title of Part n</title></part>
  </chapter>
   <chapter><title>Chapter II: Title of Chapter II</title>
 <section><title>A) Title of Section A</title>
 <part><title>A/1 Title of Part 1</title></part>
 <part><title>A/n Title of Part n </title></part>
</section>
   <section><title>B) Title of Section B</title>
    <part><title>B/1 Title of Part 1</title></part>
 <part><title>B/n Title of Part n </title></part>
   </section>
   </chapter>
  </toc>>
</book>

Here is a sample stylesheet that uses xsl:for-each-group starting-with inside a function that takes the b_part elements, a list of patterns and a list of element names as it arguments:

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

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

  <xsl:function name="mf:group" as="element()*">
    <xsl:param name="parts" as="element()*"/>
    <xsl:param name="patterns" as="xs:string*"/>
    <xsl:param name="names" as="xs:string*"/>
<xsl:for-each-group select="$parts" group-starting-with="b_part[matches(level_name, $patterns[1])]">
      <xsl:element name="{$names[1]}">
        <title><xsl:value-of select="level_name"/></title>
        <xsl:choose>
          <xsl:when test="$patterns[2]">
<xsl:sequence select="mf:group(current-group() except ., $patterns[position() gt 1], $names[position() gt 1])"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:apply-templates select="current-group() except ."/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:element>
    </xsl:for-each-group>
  </xsl:function>

  <xsl:template match="book">
    <xsl:copy>
      <xsl:copy-of select="title"/>
      <toc>
        <p>Table of contents</p>
<xsl:sequence select="mf:group(b_part, ('^Chapter', '^(Section|[A-Z]\))'), ('chapter', 'section'))"/>
      </toc>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="b_part">
    <part>
      <title><xsl:value-of select="level_name"/></title>
    </part>
  </xsl:template>

</xsl:stylesheet>

When run with Saxon 9.1 the output is

<book>
   <title>SomeTitle</title>
   <toc>
      <p>Table of contents</p>
      <chapter>
         <title>Chapter I: Title of Chapter I</title>
         <section>
            <title>Section 1: Title of section 1</title>
            <part>
               <title>Part 1: Title of Part 1</title>
            </part>
            <part>
               <title>Part 2: Title of Part 2</title>
            </part>
            <part>
               <title>Part n: Title of Part n </title>
            </part>
         </section>
         <section>
            <title>Section 2: Title of Part 2</title>
            <part>
               <title>Part 1: Title of Part 1</title>
            </part>
            <part>
               <title>Part n: Title of Part n</title>
            </part>
         </section>
      </chapter>
      <chapter>
         <title>Chapter II: Title of Chapter II</title>
         <section>
            <title>A) Title of Section A</title>
            <part>
               <title>A/1 Title of Part 1</title>
            </part>
            <part>
               <title>A/n Title of Part n</title>
            </part>
         </section>
         <section>
            <title>B) Title of Section A</title>
            <part>
               <title>B/1 Title of Part 1</title>
            </part>
            <part>
               <title>B/n Title of Part n</title>
            </part>
         </section>
      </chapter>
   </toc>
</book>

which I think is the structure you want, only indented.


--

        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>