[XSL-LIST Mailing List Archive Home]
[By Thread]
[By Date]
[xsl] flattening nested xml
Subject: [xsl] flattening nested xml From: "Andrew Welch" <awelch@xxxxxxxxxxxxxxx> Date: Thu, 16 May 2002 15:57:27 +0100 |
(reasonbly long and hard) I am having problems with nested xml. Because it is nested, it makes it very hard to convert it to html in the structure that I need... I will explain a bit: Consider the following xml: <subpara1> <para>first</para> <subpara2> <para>second</para> <subpara3> <para>third</para> </subpara3> </subpara2> </subpara1> The output I am looking for is a numbered list, such as: 1 first 2 second 3 third This isnt so bad - I could just populate a table... but when tables get large they get remarkably slow, even fixed-width tables, and its difficult to with nested xml. So, I use a combination of spans and divs: <div> <span>1</span><span id="spacer">  </span><span>first</span> </div> (the closing and opening spans must have zero whitespace between them) 'spacer' gets sized to 5em - previousSibling.clientWidth to provide the correct amount of space between the number and the data. Ok, so far so good. But if the data wraps, it will wrap beneath the number and not indented where it should, so I contain the whole lot in a div indented by 5em. Of course, this simply shifts the whole lot to the right by 5em, but if I include a text-indent of -5em it produces the required output by reverse-indenting(?:) only the top line by -5em, giving the impression of a neatly tabbed list. Great. But this has brought with it problems. If the para's contain any block elements in them it treats the next line as a first line and indents that by -5em. Also, it affects the widths of divs if they are effectively the 'first line' (and caused numerous other issues other markup, but were all solvable). So, getting back to xslt, if the data *wasnt* nested, I could simply do: <div> <span height=height of next sibling>1</span> <span id=spacer/> <span>data goes here</span> </div> <div>..next subpara</div> (currently, the next subpara would be in the 'data goes here' bit because of the nesting) This would then make it easy. So my questions are: - Can I alter my templates so that the nesting doesnt matter? - If I need to do a two pass transformation, what would the template look like? [the source xml cannot be changed] Please paste in the snipped xml and xsl into your editor and apply it to see what Im talking about. Many thanks for any interest in this. Example xml: ============ <?xml version="1.0"?> <root> <subpara1> <para>first</para> <subpara2> <para>second</para> <subpara3> <para>third</para> </subpara3> </subpara2> <subpara2> <para>wrap me to see what happens xxx xxx xxx xxx xxx xxx</para> </subpara2> <subpara2> <para>some text with a <list>block</list> item in the middle</para> </subpara2> </subpara1> </root> Example xsl: (you may need to put the script back on one line) ============ <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match="/"> <html> <head> <script> <xsl:comment> <![CDATA[ function doSpacer() { try { for (var x = 0; x<spacer.length; x++) <!--*** here ****--> spacer[x].style.width = spacerWidth.scrollWidth - spacer[x].previousSibling.scrollWidth; } catch(e){} } ]]> </xsl:comment> </script> </head> <body onload="doSpacer();"> <xsl:apply-templates/> </body> </html> </xsl:template> <xsl:template match="root"> <div style="padding-left:5em;text-indent:-5em"> <xsl:apply-templates/> </div> <span id="spacerWidth" style="width:5em"> </span> </xsl:template> <xsl:template match="subpara1|subpara2|subpara3"> <div> <xsl:apply-templates/> </div> </xsl:template> <xsl:template match="para"> <span><xsl:number level="multiple" format="1.1.1" count="subpara1|subpara2|subpara3"/> </span><span id="spacer">  </span><span><xsl:apply-templates/></span> </xsl:template> <xsl:template match="list"> <ul><li><xsl:value-of select="."/></li></ul> </xsl:template> </xsl:stylesheet> Output should like: =================== <html> <head> <META http-equiv="Content-Type" content="text/html; charset=UTF-16"> <script><!-- function doSpacer() { try { for (var x = 0; x<spacer.length; x++) spacer[x].style.width = spacerWidth.scrollWidth - spacer[x].previousSibling.scrollWidth; } catch(e){} } --></script></head> <body onload="doSpacer();"> <div style="padding-left:5em;text-indent:-5em"> <div><span>1</span><span id="spacer"> </span><span>first</span><div><span>1.1</span><span id="spacer"> </span><span>second</span><div><span>1.1.1</span><span id="spacer"> </span><span>third</span></div> </div> <div><span>1.2</span><span id="spacer"> </span><span>wrap me to see what happens xxx xxx xxx xxx xxx xxx</span></div> <div><span>1.3</span><span id="spacer"> </span><span>some text with a <ul><li>block</li></ul> item in the middle</span></div> </div> </div><span id="spacerWidth" style="width:5em"> </span></body> </html> Cheers! Andrew --- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.350 / Virus Database: 196 - Release Date: 17/04/2002 XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
RE: [xsl] Variable confusion, Tompkins Tim | Thread | RE: [xsl] flattening nested xml, Stuart Celarier |
[xsl] Variable confusion, Tompkins Tim | Date | RE: [xsl] msxml, Stuart Celarier |
Month |