RE: [xsl] xml cells transformed in to a 2-d table, some table cells missing, full table required - constant variables.

Subject: RE: [xsl] xml cells transformed in to a 2-d table, some table cells missing, full table required - constant variables.
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Sat, 3 Jan 2009 07:44:53 -0000
Basically, if you are going to produce output that corresponds to an absent
input, then you have to iterate over the potential inputs rather than the
actual inputs. Essentially you want the logic:

for $x in ('A', 'B', 'C', 'D')
  for $y in ('A', 'B', 'C', 'D')
     let $ig := //intergreen[from = $x and to = $y]
     return
       if (exists($ig))
          then $ig/length
          else 0

Now as it happens, this is not just pseudocode, it is actually XQuery 1.0
syntax, but it also translates very easily into XSLT 2.0 syntax:

<xsl:variable name="doc" select="/"/>
<xsl:for-each select="('A', 'B', 'C', 'D')">
  <xsl:variable name="x" select="."/>
  <xsl:for-each select="('A', 'B', 'C', 'D')">
     <xsl:variable name="y" select="."/>
     <xsl:variable name="ig" select="$doc//intergreen[from = $x and to =
$y]"/>
     <xsl:value-of select="if (exists($ig)) then $ig/length else 0"/>
  </xsl:for-each>
</xsl:for-each>

Now for some reason you have chosen to use XSLT 1.0 rather than XSLT 2.0.
That makes the problem no fun at all. If you really have to use XSLT 1.0,
the simplest solution is probably to have a document phases.xml containing

<phases>
  <phase>A</phase> 
  <phase>B</phase> 
  <phase>C</phase> 
  <phase>D</phase> 
</phases>

and then 

<xsl:variable name="doc" select="/"/>
<xsl:for-each select="document('phases.xml')/phases/phase">
  <xsl:variable name="x" select="."/>
  <xsl:for-each select="document('phases.xml')/phases/phase">
     <xsl:variable name="y" select="."/>
     <xsl:variable name="ig" select="$doc//intergreen[from = $x and to =
$y]"/>
     <xsl:value-of select="if (exists($ig)) then $ig/length else 0"/>
  </xsl:for-each>
</xsl:for-each>

Looking at your XSLT code on the web it seems you might already have this
<phases> information in your source data, but you haven't shown it. Another
approach would be to construct it be extracting the distinct values of
<from> and <to> - but that one is MUCH easier in XSLT 2.0 than in 1.0.

Michael Kay
http://www.saxonica.com/

> -----Original Message-----
> From: Brendan Sleight [mailto:bms@xxxxxxxxxx] 
> Sent: 03 January 2009 02:01
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: [xsl] xml cells transformed in to a 2-d table, some 
> table cells missing, full table required - constant variables.
> 
> Hi All,
> 
> I am having fun with XSL. I am developing an application for 
> traffic signals (traffic-lights) that uses xml and the input 
> and output. I want to make everything based around the xml. 
> So I decided to use stylesheets when I need text output 
> rather than create extra methods on the classes. Basically I 
> now being stubborn and am _going_ to use stylesheets even if 
> it drives me insane.
> 
> I have hit a snag as variables in XSL are constant. So I can 
> not set a flag to tell me when something has not produced a output.
> 
> I am taking a basic xml file:-
>   http://www.barwap.com/files/2008/Dec/30/example-site-2.xml
> Basically with lots of entries such as:-
>    <intergreen>
>     <from>A</from>
>     <to>B</to>
>     <length>7</length>
>    </intergreen>
>    <intergreen>
>     <from>A</from>
>     <to>C</to>
>     <length>5</length>
>    </intergreen>
>    <intergreen>
>     <from>B</from>
>     <to>A</to>
>     <length>7</length>
>    </intergreen>
> 
> Each of the <intergreen> are going to be used to form a 2-d 
> table. So far I have got this stylesheet:-
>   
> http://www.barwap.com/files/2009/Jan/02/site-transform-intergreens.xsl
> 
> Normally I would use python-amara -
> http://uche.ogbuji.net/tech/4suite/amara/ as my XSL 
> processor, but I testing using xmlstarlet. 
> http://xmlstar.sourceforge.net/, version 1.0.1-2. The 
> command:- xmlstarlet tr ./site-transform-intergreens.xsl 
> ./example-site-2.xml
> 
> Gives:-
> <?xml version="1.0"?>
> <b>Intergreen table</b><tt><i>
>  </i><i>  A</i><i>  B</i><i>  C</i><i>  D</i><i>  A</i><b> 7 
> </b><b> 5 </b><i>  B</i><b> 7 </b><i>  C</i><b> 6 </b><i>  
> D</i><b> 5 </b><b> 5 </b><b> 5 </b></tt>
> 
> Or without the <b> and <i>, A table of "from" verus "to" :-
> 
> Intergreen table
>    A  B  C  D
>  A 7  5
>  B 7
>  C 6
>  D 5  5  5
> 
> 
> However I can not find a solution where if i do not have en 
> entry for say, From A to D, a cell is still added to the 
> plain text table. (Long story but I can not use html tables.) 
> So rather then getting a half table I get a full populated 
> table, the ideal answer:-
> 
> Intergreen table
>     A  B  C  D
>  A 0  7  5  0
>  B 7  0  0  0
>  C 6  0  0  0
>  D 5  5  5  0
> 
> I could pre-populate the xml file with null entires, but that 
> makes the file on say a 32x32 table not very friendly for a 
> human to read.
> 
> I have played around with a few options, but hit the snag 
> that variables in XSL are constants so flags are out of the 
> question. Also the stylesheet feel very poorly written by me, 
> as I loop through all the entries of the <intergreen> tag 
> until I find the tag equaling row and column, which feels 
> very in-efficient.
> 
> So any tips on getting the stylesheet to the correct output 
> would be very appreciated as I have hit a bit of a brick wall 
> and run out of ideas. I am very new to style sheets and xml.  
> Can this even be done with stylesheets ?
> 
> Best Regards,
> Brendan M. Sleight
> 
> xmlstarlet tr ./processor-version.xsl ./exmaple.xml <?xml 
> version="1.0"?> <html 
> xmlns="http://www.w3.org/TR/xhtml1/strict";><head><title>XSLT
> Processor Version</title>
> </head><body><p>XSL version: 1.0
> </p><p>Vendor: libxslt
> </p><p>Vendor URL: http://xmlsoft.org/XSLT/ </p><p>Product 
> name: [Undefined] </p><p>Product version: [Undefined] 
> </p><p>Is schema-aware: [Undefined] </p><p>Supports 
> serialization: [Undefined] </p><p>Supports backwards 
> compatibility: [Undefined] </p></body></html>

Current Thread