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 |