Re: [xsl] Problems grouping nested items within a completely flat structure

Subject: Re: [xsl] Problems grouping nested items within a completely flat structure
From: "Heiko Niemann kontakt@xxxxxxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Wed, 6 Aug 2014 16:08:26 -0000
Hi,

this should get you close to the desired result. Just add more templates
necessary.

Regards,
Heiko



<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
version="2.0">
  <xsl:output method="xml" encoding="UTF-8"/>

  <xsl:template match="/textflow">
    <book>
      <xsl:for-each-group select="para" group-starting-with="para[@pgftag
eq 'Chapter']">
        <xsl:apply-templates select="."/>
      </xsl:for-each-group>
    </book>
  </xsl:template>

  <xsl:template match="para[@pgftag eq 'Chapter']">
    <chapter>
      <title>
        <xsl:apply-templates select="*"/>
      </title>
      <xsl:for-each-group group-starting-with="para[@pgftag eq 'Body
text']" select="current-group() except .">
        <p>
          <xsl:apply-templates select="*"/>
        </p>
        <ul>
          <xsl:apply-templates select="."/>
        </ul>
      </xsl:for-each-group>
    </chapter>
  </xsl:template>

  <xsl:template match="para[@pgftag eq 'Body text']">
    <xsl:for-each-group group-starting-with="para[@pgftag = ('Bulleted
text', 'Note')]" select="current-group() except .">
      <xsl:apply-templates select="."/>
    </xsl:for-each-group>
  </xsl:template>

  <xsl:template match="para[@pgftag eq 'Bulleted text']">
    <li>
      <xsl:apply-templates select="*"/>
    </li>
    <xsl:if test="count(current-group()) &gt; 1">
      <ul>
        <xsl:for-each-group select="current-group() except ."
group-starting-with="para[@pgftag eq 'Bullet sub']">
          <xsl:apply-templates select="."/>
        </xsl:for-each-group>
      </ul>
    </xsl:if>
  </xsl:template>

  <xsl:template match="para[@pgftag eq 'Bullet sub']">
    <li>
      <xsl:apply-templates select="*"/>
    </li>
  </xsl:template>

  <xsl:template match="para[@pgftag eq 'Note']">
    <note>
      <xsl:apply-templates select="*"/>
    </note>
  </xsl:template>

  <xsl:template match="paraline|xref">
    <xsl:apply-templates/>
  </xsl:template>

  <xsl:template match="render">
    <xsl:choose>
      <xsl:when test="@charformat eq 'Emphasis'">
        <em>
          <xsl:value-of select="."/>
        </em>
      </xsl:when>
      <xsl:when test="@charformat eq 'Bold'">
        <b>
          <xsl:value-of select="."/>
        </b>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="."/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!--next template for testing purposes only-->
  <xsl:template match="*">
    <bah/>
  </xsl:template>

</xsl:stylesheet>




> Hi.
>
> While there is a lot of information about grouping available, I still have
> problems applying it to my particular case of a document-centric XML file.
> Obviously I havenbt yet understood it fully.
>
> This is my (redacted) source. Please excuse its length, but this better
> illustrates my problem. I use Saxon 9HE, but I am open to both, XSL 1.0 or
> 2.0 solutions.
>
>       <textflow tftag=bAb>
>          <para pgftag=bChapterb>
>             <paraline>Introduction</paraline>
>          </para>
>          <para pgftag="Body text">
>             <paraline>This chapter expains...</paraline>
>          </para>
>          <para pgftag="Bulleted text">
>             <paraline>Display the online help as follows:</paraline>
>          </para>
>          <para pgftag="Bullet sub">
>             <paraline>To view the help for a panel, press the help (PF1)
> key.</paraline>
>          </para>
>          <para pgftag="Bullet sub">
>             <paraline>To view the help for an input field or select a
> parameter from a pop-up window, </paraline>
>             <paraline>press PF1.</paraline>
>          </para>
>          <para pgftag="Note">
>             <paraline>If you do not specify a required parameter, or enter
> an incorrect one, XXXX </paraline>
>             <paraline>will prompt you for the correct
> information.</paraline>
>          </para>
>          <para pgftag="Bulleted text">
>             <paraline>Check relevant sections of <render
> charformat="Emphasis">XXXX</render>.</paraline>
>          </para>
>          <para pgftag="Bulleted text">
>             <paraline>Visit our web site to get...</paraline>
>          </para>
>          <para pgftag="Body text">
>             <paraline>The topics covered are:</paraline>
>          </para>
>          <para pgftag="Bulleted text">
>             <paraline>
>                <xref srctext="55167: 1st Section: What is XXX?"><render
> charformat="Bold">What is XXX?</render></xref>
>             </paraline>
>          </para>
>          <para pgftag="Bulleted text">
>             <paraline>
>                <xref srctext="55167: 1st Section: How Does XXX
> Work?"><render charformat="Bold"> How Does XXX
> Work?</render></xref>
>             </paraline>
>          </para>
>          <para pgftag=bChapterb>
>             <paraline>Next chapter</paraline>
>          </para>
>      </textflow>
>
> The idea is, quite obviously, grouping the relevant list items, so youbd
> end up (ideally!) with something like e.g.:
>
> <book>
>   <chapter>
>      <title>Introduction</title>
>      <p>This chapter explains...</p>
>      <ul>
>         <li>Display the online help as follows:</li>
>         <ul>
>            <li>To view the help for a panel, press the help (PF1)
> key.</li>
>            <li>To view the help for an input field or select a parameter
> from a pop-up window, press PF1.</li>
>        </ul>
>         <note> If you do not specify a required parameter, or enter an
> incorrect one, XXXX will prompt you for the correct
> information.</note>
>         <li>Check relevant sections of <em>XXXX</em>.</li>
>         <li>Visit our web site to get ...</li>
>      </ul>
>      <p> The topics covered are:</p>
>      <ul>
>         <li><b>What is XXX?</b></li>
>         <li><b>How Does XXX Work?</b></li>
>      </ul>
>    </chapter>
>   <chapter>
>      <title>Next chapter</title>
>   </chapter>
> </book>
>
>
> As you can see, the source is a completely flat, linear sequence from
> which I have to establish every kind of structure. Therefore, I use
> something like
>
> <xsl:template match=btextflowb>
>   <book><xsl:apply-templates/></book>
> </xsl:template>
>
> <xsl:template match=bpara[@pgftag=bChapterb]b>
>     <xsl:variable name="chapter-id" select="generate-id()"/>
>     <chapter>
>        <title><xsl:apply-templates/></title>
>          <xsl:apply-templates
> select="following-sibling::*[not(self::*[@pgftag='Chapter'])]
>               [generate-id(preceding-sibling::para[@pgftag='Chapter'][1])
> = $chapter-id]"/>
>     </chapter>
> </xsl:template>
>
> <xsl:template match=bpara[@pgftag=bBulleted textb]b>...
>
> That is, I canbt imagine having a single template matching textflow in
> which I apply <xsl:for-each-group> for all kinds of different paras.
> Instead, I use Muenchian grouping (yep, starting with XSL 1.0, but now I
> use 2.0), but ran into serious recursion trouble when fiddling with nested
> chapter and list structures.
> The other principal problem is how to decide when a structure has ended,
> because all elements are on the same sibling axis. Now, a chapter ends,
> when another <para pgftag=bChapterb> or some <para
> pgftag=bAppendixb> appears. But there is no way to decide when the
> first bulleted list in the example really ends, since the list items may
> include other elements such as notes or nested lists. You could only use
> criteria such as bThis list has ended, when the next paragraph is e.g.
> <para @pgftag=bBody textb> or <para @pgftag=bChapterb>
> appearsb.
>
> Now, if anyone could point me in the right direction, Ibd be very
> grateful, since itbs bugging me for some time now. And, please apologize
> the length...
>
> Thank you,
> Frank
>
>
> Software AG b Sitz/Registered office: UhlandstraCe 12, 64297 Darmstadt,
> Germany b Registergericht/Commercial register: Darmstadt HRB 1562 -
> Vorstand/Management Board: Karl-Heinz Streibich (Vorsitzender/Chairman),
> Dr. Wolfram Jost, Arnd Zinnhardt; - Aufsichtsratsvorsitzender/Chairman of
> the Supervisory Board: Dr. Andreas Bereczky - http://www.softwareag.com

Current Thread