[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

RE: [xsl] Generating implicit wrapper element


Subject: RE: [xsl] Generating implicit wrapper element
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Tue, 30 Aug 2005 20:05:25 +0100

Using d-o-e for this kind of exercise is very much frowned upon. The reason
is that it only works if the result tree is immediately serialized after the
transformation, by a serializer that's closely coupled with the XSLT
transformation. This prevents it working in a pipelined environment where
the result tree that's output from the XSLT transformation is then input (in
tree form) to another process. An example of such a pipeline is the Netscape
browser, which is why d-o-e doesn't work on Netscape or Mozilla browsers.

It's a classic example of something that violates an architectural boundary,
in this case the boundary between transformation and serialization. Very
often this appears attractive at the time, but it's sometimes that you
always come to regret later. And it's as well to learn the proper way to do
it, because it's a technique that you'll be able to use again and again.

In XSLT 2.0 this problem is easily solved using <xsl:for-each-group
group-adjacent="node-name()">. It's not all that hard in 1.0 either. My
preferred approach is sibling recursion:

<xsl:template match="li"/>

<xsl:template match="li[not(preceding-sibling::*[1][self::li])]"/>
  <ul>
   <xsl:apply-templates select="." mode="in-list"/>
  </ul>
</xsl:template>

<xsl:template match="li" mode="in-list"/>
  <xsl:copy-of select="."/>
  <xsl:apply-templates select="following-sibling::*[1][self::li]" 
                       mode="in-list"/>
</xsl:template>

That's hardly any longer than the d-o-e solution...

But some people prefer to use Muenchian grouping with the generate-id() of
the first li in a consecutive sequence as the grouping key.

Michael Kay
http://www.saxonica.com/ 

> -----Original Message-----
> From: Ferdinand Soethe [mailto:xsl-list@xxxxxxxxxx] 
> Sent: 30 August 2005 17:37
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: [xsl] Generating implicit wrapper element
> 
> 
> I have a question about the problem below which has already been
> identified as a 'positional grouping problem'. (I think) I understand
> the Muenchian method-based solutions suggested (at least in theory).
> 
> What I don't understand is what is wrong about using the 
> following simple
> solution that I pieced together from different postings:
> 
> <xsl:template match="li">
>     <xsl:if test="(name(preceding-sibling::*[1])!='li' )">
>         <xsl:text disable-output-escaping="yes">&lt;ul&gt;</xsl:text>
>     </xsl:if>
>     <li><xsl:copy-of select="@*"/><xsl:apply-templates/></li>
>     <xsl:if test="(name(following-sibling::*[1])!='li' )">
>         <xsl:text disable-output-escaping="yes">&lt;/ul&gt;</xsl:text>
>     </xsl:if>
>   </xsl:template>
> 
> Seems like it fits much better into my context of using
> 'apply-templates' as much as possible (no need to process all li's at
> once and ignore them later) and - except for that hack of
> smuggling half the ul-element into my output - it also seems quite
> reasonable xsl, not?
> 
> Your input much appreciated,
> 
> --
> Ferdinand Soethe
> 
> 
> --- The problem ---
> 
> I have an XML-document with paragraphs and list items that have no
> wrapper element around each list.
> 
> Something like this:
> 
> <par>my first para</par>
> <par>second para</par>
> <li>first list item of first list</li>
> <li>second list item of first list</li>
> <li>third list item of first list</li>
> <par>third para</par>
> <li>first list item of second list</li>
> <par>fourth para</par>
> <li>first list item of third list</li>
> <li>second list item of third list</li>
> 
> In my transformation I would like to add these implicit wrapper
> element around each of the list to get something like
> 
> <p>my first para</p>
> <p>second para</p>
> <ul>
> <li>first list item of first list</li>
> <li>second list item of first list</li>
> <li>third list item of first list</li>
> </ul>
> <p>third para</p>
> <ul>
> <li>first list item of second list</li>
> </ul>
> <p>fourth para</p>
> <ul>
> <li>first list item of third list</li>
> <li>second list item of third list</li>
> </ul>


Current Thread
Keywords