|
[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message] Re: Efficently transposing tokenized data
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
|
PURCHASE STYLUS STUDIO ONLINE TODAY!Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced! Download The World's Best XML IDE!Accelerate XML development with our award-winning XML IDE - Download a free trial today! Subscribe in XML format
|

Cart








