This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Re: nested block elements in xml -> html
- To: "Jeni Tennison" <Jeni dot Tennison at epistemics dot co dot uk>
- Subject: Re: nested block elements in xml -> html
- From: "Michael Beddow" <gll6mb at smlc01 dot leeds dot ac dot uk>
- Date: Mon, 5 Jun 2000 15:57:39 +0100
- Cc: <xsl-list at mulberrytech dot com>
- References: <200005301520.LAA26183@mulberrytech.com> <3.0.6.32.20000605151114.01309d00@NTServer>
- Reply-To: xsl-list at mulberrytech dot com
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