Subject: Re: [xsl] Efficently transposing tokenized data From: "Dimitre Novatchev" <dnovatchev@xxxxxxxxx> Date: Tue, 4 Nov 2008 17:20:32 -0700 |
THe following solution transforms the initial xml document into a well-structured matrix (sequence of structured rows), then the transposition is trivial: <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:my ="my:my" exclude-result-prefixes="my xs" > <xsl:output omit-xml-declaration="yes" method="html"/> <xsl:template match="/"> <table> <xsl:apply-templates/> </table> </xsl:template> <xsl:template match="MultiLine"> <tr> <xsl:apply-templates select="*/@title"/> </tr> <xsl:variable name="vMatrix" as="element()*" select="my:makeMatrix(Line)"/> <xsl:for-each select="1 to @samples"> <xsl:variable name="vRow" as="xs:integer" select="."/> <tr> <xsl:for-each select="$vMatrix"> <td> <xsl:value-of select="mdata[$vRow]"/> </td> </xsl:for-each> </tr> </xsl:for-each> </xsl:template> <xsl:template match="Line/@title"> <th> <xsl:value-of select="."/> </th> </xsl:template> <xsl:function name="my:makeMatrix" as="element()*"> <xsl:param name="pLines" as="element()*"/> <xsl:for-each select="$pLines"> <mrow> <xsl:for-each select="tokenize(@data, ' ')"> <mdata> <xsl:value-of select="."/> </mdata> </xsl:for-each> </mrow> </xsl:for-each> </xsl:function> </xsl:stylesheet> when the above transformation is applied against the original input (".." replaced with "."): <MultiLine samples="5"> <Line title="Line 1" data="0.1 0.4 0.6 0.4 0.8" /> <Line title="Line 2" data="0.4 0.2 0.5 1.4 3.8" /> </MultiLine> the wanted result is produced: <table> <tr> <th>Line 1</th> <th>Line 2</th> </tr> <tr> <td>0.1</td> <td>0.4</td> </tr> <tr> <td>0.4</td> <td>0.2</td> </tr> <tr> <td>0.6</td> <td>0.5</td> </tr> <tr> <td>0.4</td> <td>1.4</td> </tr> <tr> <td>0.8</td> <td>3.8</td> </tr> </table> -- Cheers, Dimitre Novatchev --------------------------------------- Truly great madness cannot be achieved without significant intelligence. --------------------------------------- To invent, you need a good imagination and a pile of junk ------------------------------------- Never fight an inanimate object ------------------------------------- You've achieved success in your field when you don't know whether what you're doing is work or play On Tue, Nov 4, 2008 at 4:13 PM, Beldaz Jalfrezi <beldazj@xxxxxxxxxxxx> wrote: > Hi XSL-List members, > > I have been learning my way around XSLT (2.0) over the past couple of weeks, principally using Saxon-B 9.1. I have an immediate need to transform existing XML data, initially to HTML. The XML contains, similar to SVG, space-tokenized numerical data held within attributes. What I am having trouble understanding is how to transform several nodes with such data into individual columns of data. > > The XML is like this: > <MultiLine samples="5"> > <Line title="Line 1" data="0.1 0.4 0.6 0.4 0..8" /> > <Line title="Line 2" data="0.4 0.2 0.5 1.4 3.8" /> > </MultiLine> > > There can be any number of <Line> nodes (typically 3 or 4) and the number of values (samples) in each data attribute for each <Line> must match the samples attribute of the parent <MultiLine> node. The number of samples can be very long, typically several thousand. At present this is the data that I am being supplied, so regardless of any shortcomings of the structure (although suggestions for improvement are welcome) I am stuck with it. > > I want to transform such data into, e.g., HTML columns, like: > <TABLE> > <TR> > <TH>Line 1</TH><TH>Line 2</TH> > </TR> > <TR> > <TD>0.1</TD><TD>0.4</TD> > </TR> > <TR> > <TD>0.4</TD><TD>0.2</TD> > </TR> > <TR> > <TD>0.6</TD><TD>0.5</TD> > </TR> > ... > </TABLE> > > I have seen similar questions where people have wanted to transpose HTML table data, but the problem here is that the input data has to be tokenized. I can output the data sequentially for each Line with a template such as: > <xsl:template match="Line"> > <TR><TH><xsl:value-of select="@title" /></TH><TR> > <xsl:for-each select="tokenize(@data,' ')"> > <TR><TD> > <xsl:value-of select="position()" /> > </TD></TR> > <xsl:value-of select="." /> > </xsl:for-each> > </xsl:template> > > To format the data as adjacent columns the only approach I can think of is a for-each loop over the number of samples, and in each case call index-at(tokenize(../Line[n]/@data, ' '), position()) for each Line. But this looks horribly inefficient, since I appear to be tokenizing every @data attribute repeatedly, presumably giving complexity O(count(Line)*samples^2). What would be far more preferable is to tokenize all the lines, and then at each index obtain the appropriate value from each sequence. But I have no idea how to do that in XSLT. > > I have spent at least a day trying to solve this conumdrum, so if anyone has any suggestions I would be very grateful. > > Kind regards, > > Beldaz > > > > Search 1000's of available singles in your area at the new Yahoo!7 Dating. Get Started http://au.dating.yahoo.com/?cid=53151&pid=1011
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Efficently transposing to, Michael Ludwig | Thread | Re: [xsl] Efficently transposing to, Beldaz Jalfrezi |
RE: [xsl] Efficently transposing to, Michael Kay | Date | [xsl] RE: fn:contains multiple stri, Tony Nassar |
Month |