xsl-list
[Top] [All Lists]

Re: [xsl] Efficently transposing tokenized data

2008-11-04 19:21:00
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(_at_)yahoo(_dot_)com(_dot_)au> 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


--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: 
<mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--



--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--