Subject: Re: nested block elements in xml -> html From: Jeni Tennison <Jeni.Tennison@xxxxxxxxxxxxxxxx> Date: Mon, 05 Jun 2000 15:11:14 +0100 |
Hi Michael, >My templates transform this to an html fragment > ><p class="myclass"> > Text before list > <ol class="mylist"> > <li>first item</li> > <li>second item</li> > </ol> > Text after list ></p> > >which looks fine, but isn't. In the xml, as my dtd allows, the >list is nested within the p. But in html, the new ol block >element >implicitly closes the p element, so that the browser >in effect rewrites to > ><p class="myclass"> > Text before list ></p> <<=============== !!!! > <ol class="mylist"> > <li>first item</li> > <li>second item</li> > </ol> > Text after list ></p> A possible way around your problem is to actually produce valid HTML so that the browser doesn't have to resort to guessing where the paragraph ends. In other words to produce: <p class="myclass"> Text before list </p> <ol class="mylist"> <li>first item</li> <li>second item</li> </ol> <p class="myclass"> Text after list </p> This would be fairly easy if the text before and after the list does not contain any other markup (make a template matching p/text() which wraps said text within a 'p' element). I think it's more likely, though, that you have emphasised text or something in there as well, and that you could have several lists within a particular paragraph in your source document. 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 Dr Jeni Tennison Epistemics Ltd, Strelley Hall, Nottingham, NG8 6PE Telephone 0115 9061301 ? Fax 0115 9061304 ? Email jeni.tennison@xxxxxxxxxxxxxxxx XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: nested block elements in xml ->, RSuiter | Thread | Re: nested block elements in xml ->, Michael Beddow |
RE: if - will this work?, Kay Michael | Date | Re: null pointer exception in Saxon, Dave Carlson |
Month |