xsl-list
[Top] [All Lists]

Re: [xsl] variable outside a for-each loop: second try

2007-09-21 06:30:17
On 9/20/07, Abel Braaksma <abel(_dot_)online(_at_)xs4all(_dot_)nl> wrote:
Mathieu Malaterre wrote:
$  java -jar /usr/share/Dart/Source/Server/saxon/saxon8.jar  -t
Saxon 8.0 from Saxonica
Java version 1.6.0_01
No source file name


ouch, that must be at least three years old! High time to upgrade to 8.9
at the very least! So much has changed since then.

    <xsl:for-each select="//informaltable">


someone already told you this on this thread, but really, try to refrain
from //. It is very costly and will cause you more harm (walking the
full tree of all nodes to find whether they match 'informaltable') than
good. Just use the path as it is, in your case: select="informaltable".

When I tried your solution here is what I get:.

    <entry ie="{(entry[1]/para[. != ''] |
preceding-sibling::row[entry[1]/para != ''][1])[1]}"
module="{entry[2]/para}" reference="{entry[3]/para}"
usage="{entry[4]/para}"/>
  </xsl:template>


My solution was meant as a hint, not as a full solution. But my
apologies for leaving such an obvious bug into the stylesheet; that
happens when you only type them in the mail and don't try them before
sending. There are two bugs:

  1. The obvious one: the prec-sibl statement requests for the element
"row", not for the element "para", which is what you were after.
  2. The less obvious is the one of document order: the last [1] will
select the *first* to appear in document order of the two elements
specified between the parentheses before it. That means: the prec-sibl
row will always be chosen. Change it to use the , (comma) operator or
change [1] to [last()].

After these fixes the @ie-statement becomes:

{(entry[1]/para[. != ''] , preceding-sibling::row/entry[1]/para[. !=
''][1])[1]}



Gives:

<?xml version="1.0" encoding="UTF-8"?>
<entry ie="Col1 A" module="Col2 A" reference="" usage=""/>
<entry ie="&#xA;   &#xA;     Col1 A&#xA;   &#xA;   &#xA;     Col2
A&#xA;   &#xA; " module="Col2 B" reference="" usage=""/>
<entry ie="&#xA;   &#xA;     Col1 A&#xA;   &#xA;   &#xA;     Col2
A&#xA;   &#xA; " module="Col2 C" reference="" usage=""/>
<entry ie="&#xA;   &#xA;     Col1 A&#xA;   &#xA;   &#xA;     Col2
A&#xA;   &#xA; " module="Col2 D" reference="" usage=""/>


Weird behavior like this is what happens when you use a very out of date
processor that is implemented on a very old draft version of a now
completely finalized (and in quite some areas changed) specification.
The whitespace that you see is caused by the preceding-sibling::row
elements, which contain non-significant whitespace. With a correctly
behaving processor, this whitespace would normally be ignored (note that
&#xA; is also whitespace! It is the newline that is between <row> and
<entry> and between <entry> and <para> etc).

The output with my original stylesheet, just as you put it above, is as
follows with a normal recent version of any XSLT 2.0 processor:

<?xml version="1.0" encoding="UTF-8"?>
<table>
   <entry ie="Col1 A" module="Col2 A" reference="" usage=""/>
   <entry ie="Col1 ACol2 A" module="Col2 B" reference="" usage=""/>
   <entry ie="Col1 ACol2 A" module="Col2 C" reference="" usage=""/>
   <entry ie="Col1 ACol2 A" module="Col2 D" reference="" usage=""/>
</table>

Which is not correct, of course, but vastly different from your output.
By now I hope you are convinced to upgrade your processor ;) it will
save you (and us) gazillions of time.

This is the XSLT I used to test my bug fixes (but still: it is not more
than a hint, I am sure you want to tweak it further). Note the comma
operator and the absence of //:

    <xsl:template match="/">
        <xsl:apply-templates select="*" />
    </xsl:template>

    <xsl:template match="informaltable">
        <table>
            <xsl:apply-templates />
        </table>
    </xsl:template>

    <xsl:template match="row">
        <entry ie="{(entry[1]/para[. != ''] ,
preceding-sibling::row/entry[1]/para[. != ''][1])[1]}"
            module="{entry[2]/para}" reference="{entry[3]/para}"
            usage="{entry[4]/para}"/>
    </xsl:template>


This is the output:

<?xml version="1.0" encoding="UTF-8"?>
<table>
   <entry ie="Col1 A" module="Col2 A" reference="" usage=""/>
   <entry ie="Col1 A" module="Col2 B" reference="" usage=""/>
   <entry ie="Col1 A" module="Col2 C" reference="" usage=""/>
   <entry ie="Col1 D" module="Col2 D" reference="" usage=""/>
</table>


Hope this info will help you further.


Thanks,

  This should close the thread. I don't think I was able to describe
my problem correctly using both your solution and the xsl:transform I
am not getting what I called the 'last' preceeding entry.

Docs are here:

 https://gdcm.svn.sourceforge.net/svnroot/gdcm/Sandbox/xslt/

In both case I get something like:


<?xml version="1.0" encoding="UTF-8"?>
<table>
   <entry ie="Col1 A" module="Col2 A" reference="" usage=""/>
   <entry ie="Col1 A" module="Col2 B" reference="" usage=""/>
   <entry ie="Col1 A" module="Col2 C" reference="" usage=""/>
   <entry ie="Col1 D" module="Col2 D" reference="" usage=""/>
   <entry ie="Col1 E" module="Col2 E" reference="" usage=""/>
   <entry ie="Col1 A" module="Col2 F" reference="" usage=""/>
   <entry ie="Col1 A" module="Col2 G" reference="" usage=""/>
</table>

The last two lines contains 'Col1 A' which is not what I called 'last'
preceeding. It should have been:


<?xml version="1.0" encoding="UTF-8"?>
<table>
   <entry ie="Col1 A" module="Col2 A" reference="" usage=""/>
   <entry ie="Col1 A" module="Col2 B" reference="" usage=""/>
   <entry ie="Col1 A" module="Col2 C" reference="" usage=""/>
   <entry ie="Col1 D" module="Col2 D" reference="" usage=""/>
   <entry ie="Col1 E" module="Col2 E" reference="" usage=""/>
   <entry ie="Col1 E" module="Col2 F" reference="" usage=""/>
   <entry ie="Col1 E" module="Col2 G" reference="" usage=""/>
</table>

Thanks again all for your help. I did not meant to be rude. But I felt
like I would ask a very simple question on the C++ newsgroup and
people would tell me to use C++0x .


I have ordered an XSLT book,

-- 
Mathieu

--~------------------------------------------------------------------
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>
--~--