Re: nested block elements in xml -> html

Subject: Re: nested block elements in xml -> html
From: "Michael Beddow" <gll6mb@xxxxxxxxxxxxxxxxxx>
Date: Mon, 5 Jun 2000 15:57:39 +0100
Jeni,

Many thanks for this reply. You were quite right about why this
was such a problem: I have nested lists inside the xml <p>
elements, so a simple solution doesn't work, and I need
something that will cope with the more complex test source you
devised.

In fact, after Dan's response I stopped thinking of it as an XSL
problem and managed to hide the symptoms by using a combination
of <div> and <span>s in my html. But I realised that I hadn't
got a truly general solution, which I think your approach
supplies. And I can see it pointing the way to solving a few
other problems that I've been afraid even to acknowledge yet.

Michael
-------
Michael Beddow
University of Leeds UK


> In other words, I'm testing with a source of:
>
> <p>
>  <em>Emphasised</em> text before lists
>  <list>
>    <item>first item, first list</item>
>    <item>second item, first list</item>
>  </list>
>  Text between lists
>  <list>
>    <item>first item, second list</item>
>    <item>second item, second list</item>
>  </list>
>  Text after lists
> </p>
>
> After some playing around, the best I can come up with is the
following,
> though there may be a simpler way.
>
> First, generate the groups of text and elements that need to
be put into
> paragraphs together using keys.  The following xsl:key element
groups
> together all children of 'p' that are not called 'list' by
indexing them
> according to the unique id of the next sibling 'list' element.
>
>   <xsl:key name="content" match="doc/p/node()[name() !=
'list']"
>     use="generate-id(following-sibling::list)" />
>
> Now that we have them in groups, given a node we can generate
a paragraph
> that contains a copy of (to maintain existing HTML styling)
all the nodes
> in that group.  So first, we want to only look at nodes that
are (a) the
> first node in the paragraph; (b) the first node after a list;
or (c) a list
> (since we want to process them too!).  I could have selected
those nodes
> that appear first in the keyed groups, but I didn't because
this way was
> shorter.
>
>   <xsl:template match="p">
>     <xsl:apply-templates
>       select="node()[1] |
>               node()[name(preceding-sibling::node()[1]) =
'list'] |
>               list" />
>   </xsl:template>
>
> Then, for those nodes that aren't lists, we want to take them,
and all
> other nodes in their group, and put them in a paragraph:
>
>   <xsl:template match="p/node()[name() != 'list']">
>     <p class="myclass">
>       <xsl:apply-templates mode="copy"
>         select="key('content',
generate-id(following-sibling::list))" />
>     </p>
>   </xsl:template>
>
>   <xsl:template match="node()" mode="copy">
>     <xsl:copy-of select="." />
>   </xsl:template>
>
> This enables you to keep your existing template matching
'list', which
> probably looks something like:
>
>   <xsl:template match="list">
>     <ol>
>       <xsl:for-each select="item">
>         <li><xsl:value-of select="." /></li>
>       </xsl:for-each>
>     </ol>
>   </xsl:template>
>
> I've tested this and it works with SAXON.
>
> I hope this helps,
>
> Jeni



 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread