|
Subject: Re: [xsl] Problems grouping nested items within a completely flat structure From: "Wegmann, Frank frank.wegmann@xxxxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> Date: Thu, 7 Aug 2014 13:50:29 -0000 |
Heiko,
thanks for your approach. While this helped me to grasp the grouping concept
in XSLT 2.0 a little bit better (but only a little bit), I noticed that your
solution is specifically tailored to the exact sequence of nodes that I used
in the example file. But, unfortunately, life doesn't work that way:-) If,
e.g. I put the first para[@pgftag='Body text'] down to right after the note,
the stylesheet yields:
<book>
<chapter>
<title>Introduction</title>
<p>Display the online help as follows:</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>
</ul>
</ul>
<p>This chapter expains...</p>
<ul>
<li>To view the help for an input field or select a parameter from a
pop-up window, press PF1.</li>
<li>Check relevant sections of <em>XXXX</em>.</li>
<li>Visit our web site to get...</li>
</ul>
[...]
Clearly not what is intended. So what is the right strategy to solve this in a
generic way? Sure, you'd want to group all sibling elements to chapter as long
as they are not indicating a new chapter or a subdivision. But then? You
cannot go for a group like
<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>
when you don't know what first child element you have. Instead, I'd imagine
templates that can match single paras and don't need no know about their
context (like para[@pgftag='Body text'] or para[@pgftag='Note']. But as soon
as you have list structures I currently don't see a solution that goes beyond
grouping consecutive list items and if something like a note drops in, you
have to regard the following list item as the first item of a new list.
And here I'm back to square one. I cannot e.g. use
<xsl:for-each-group group-starting-with="para[@pgftag eq 'Bullet text']"
select="current-group() except .">
within the chapter template, since I don't know if and when such a list can be
expected, so to me it looks more like:
<xsl:template match="para[@pgftag='Chapter']">
<chapter><title><xsl:apply-templates/></title>
<xsl:apply-templates select="all siblings that are in the same
chapter until a subdivision comes up"/>
</chapter>
</xsl:template>
<xsl:template match="para[@pgftag='Bulleted text'][1]">
<ul>
<xsl:for-each-group select="following-sibling::*"
group-adjacent="name()">
<xsl:apply-templates select="." mode="listitem"/>
</xsl:for-each-group>
</ul>
</xsl:template>
But Saxon doesn't like that for-each-group and complains: "the only axes
allowed in a pattern are the child and attribute axes".
To complicate matters, subdivisions like '1st Section', ..., '4th Section' may
be nested, so a chapter may consist either of simple content, as shown here,
or some overview, followed by one or more subsections...
>From what I've seen so far, I cannot deduce a generic solution to my problem.
Probably I'm still missing something elementary here...
Thanks so far,
Frank
-----Original Message-----
From: Heiko Niemann kontakt@xxxxxxxxxxxxxxxx
[mailto:xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx]
Sent: Mittwoch, 6. August 2014 18:09
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: Re: [xsl] Problems grouping nested items within a completely flat
structure
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()) > 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 havenC"b,b"t 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=C"b,BAC"b,B>
> <para pgftag=C"b,BChapterC"b,B>
> <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=C"b,BChapterC"b,B>
> <paraline>Next chapter</paraline>
> </para>
> </textflow>
>
> The idea is, quite obviously, grouping the relevant list items, so
> youC"b,b"d 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=C"b,BtextflowC"b,B>
> <book><xsl:apply-templates/></book>
> </xsl:template>
>
> <xsl:template match=C"b,Bpara[@pgftag=C"b,b"ChapterC"b,b"]C"b,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=C"b,Bpara[@pgftag=C"b,b"Bulleted
textC"b,b"]C"b,B>...
>
> That is, I canC"b,b"t 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=C"b,b"ChapterC"b,b"> or some
<para
> pgftag=C"b,b"AppendixC"b,b"> 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 C"b,EThis list has ended, when the next
paragraph is e.g.
> <para @pgftag=C"b,b"Body textC"b,b"> or <para
@pgftag=C"b,b"ChapterC"b,b">
> appearsC"b,B.
>
> Now, if anyone could point me in the right direction, IC"b,b"d be very
> grateful, since itC"b,b"s bugging me for some time now. And, please
> apologize the length...
>
> Thank you,
> Frank
>
>
> Software AG C"b,b Sitz/Registered office: UhlandstraCE8e 12, 64297
> Darmstadt, Germany C"b,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
>
>
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 |
|---|
|
| <- Previous | Index | Next -> |
|---|---|---|
| Re: [xsl] Problems grouping nested , Heiko Niemann kontak | Thread | Re: [xsl] Problems grouping nested , David Rudel fwqhgads |
| [no subject], Unknown | Date | Re: [xsl] Problems grouping nested , David Rudel fwqhgads |
| Month |