all groups > dotnet xml > may 2004 >
You're in the

dotnet xml

group:

xmlTransform transform <xsl:number> - possible Bug


xmlTransform transform <xsl:number> - possible Bug b0yce
5/26/2004 5:40:22 PM
dotnet xml: Hi Group,

I think I have found a problem with the <xsl:element> when being
transformed by the .NET xmlTransform class. When using XmlSpy for
development and debugging, the <xsl:number> subsitutes the position of the
node correctly as I expected. This is fine with MSXML 3.0 & MSXML 4.0 plus
the XmlSpy internal engine.

I have been able to reproduce using a simpler Xml and Xsl to demonstrate;
XML
===
<?xml version="1.0" encoding="UTF-8"?>
<html>
<head><title>Tester</title></head>
<body>
<h4 class="no">Table 1</h4>
<table><tbody><tr><td>Some Data</td></tr></tbody></table>
<h4 class="yes">Table 2</h4>
<table><tbody><tr><td>Some Data</td></tr><tr><td>Some Data
2</td></tr><tr><td>Some Data 3</td></tr></tbody>
</table>
<h4 class="yes">Table 3</h4>
<table><tbody><tr><td>Some Data</td></tr><tr><td>Some Data
2</td></tr><tr><td>Some Data 3</td></tr></tbody></table>
<h4 class="yes">Table 4</h4>
<table><tbody><tr><td>Some Data</td></tr><tr><td>Some Data
2</td></tr></tbody></table>
</body>
</html>

My XSL needs to return all rows that are in a table that has @class = 'yes'
and set an id attribute to the absolute position in the document - in
relation to all tables with @class = 'yes'.

XSL that achieves this
===============
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/">
<xsl:element name="TableMatch">
<xsl:apply-templates select="//h4[@class='yes']" />
</xsl:element>
</xsl:template>
<xsl:template match="h4">
<xsl:element name="Table">
<xsl:for-each select="following-sibling::table[1]/tbody/tr">
<xsl:element name="row">
<xsl:attribute name="id">
<xsl:number level="any" from="//h4[@class='yes'][1]" />
</xsl:attribute>
<xsl:value-of select="td" />
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template>
</xsl:stylesheet>

This produces Output
==============
<?xml version="1.0" encoding="UTF-16"?>
<TableMatch>
<Table>
<row id="1">Some Data</row>
<row id="2">Some Data 2</row>
<row id="3">Some Data 3</row>
</Table>
<Table>
<row id="4">Some Data</row>
<row id="5">Some Data 2</row>
<row id="6">Some Data 3</row>
</Table>
<Table>
<row id="7">Some Data</row>
<row id="8">Some Data 2</row>
</Table>
</TableMatch>

Which is great! Now when I try the transformation using the following code
(C#);

public static void Main()
{
doc = new XPathDocument(inputFile); // Create New
XPath Document to open File
XPathNavigator navi = doc.CreateNavigator(); // Create
XPathNavigator to navigate through document

writer = new XmlTextWriter("xlsnumberOutput.xml" , Encoding.UTF8); //
Create new xmlTextWriter

// Now need to transform into Xml format
XslTransform transform = new XslTransform();
transform.Transform(doc, null, writer, new XmlUrlResolver());

// Kill Writer
writer.Flush();
writer.Close();
}

The <xsl:number> element is returning a blank string i.e. nothing and the
output is as follows;

<TableMatch>
<Table>
<row id="">Some Data</row>
<row id="">Some Data 2</row>
<row id="">Some Data 3</row>
</Table>
<Table>
<row id="">Some Data</row>
<row id="">Some Data 2</row>
<row id="">Some Data 3</row>
</Table>
<Table>
<row id="">Some Data</row>
<row id="">Some Data 2</row>
</Table>
</TableMatch>

@id is blank! The reason I want the @id in this way is because I want to
generate a unique identity across *all* matching rows. The .NET transform
has some problem achieving this.

Can anyone advise what the problem is here or some way of working around
this?

TIA (if you got this far :p)

b0yce

xslTransform transform <xsl:number> - possible Bug b0yce
5/26/2004 5:48:04 PM
<snip>
[quoted text, click to view]

Forgot to mention (pressed Send too early :) ) that I have narrowed it down
to the <xsl:number> from="" parameter.

Changing
<xsl:number level="any" from="//h4[@class='yes'][1]"/>
to
<xsl:number level="any" from="body"/>

now produces;
<?xml version="1.0" encoding="UTF-16"?>
<TableMatch>
<Table>
<row id="2">Some Data</row>
<row id="3">Some Data 2</row>
<row id="4">Some Data 3</row>
</Table>
<Table>
<row id="5">Some Data</row>
<row id="6">Some Data 2</row>
<row id="7">Some Data 3</row>
</Table>
<Table>
<row id="8">Some Data</row>
<row id="9">Some Data 2</row>
</Table>
</TableMatch>

in by all engines. Starting from 2 is not ideal since there could be n
number of tables @class='no' beforehand.

So it could be that in .NET XslTransform <xsl:number> doesn't like "//"
document root references?


Re: xslTransform transform <xsl:number> - possible Bug b0yce
5/27/2004 9:12:26 AM
Another time while playing around to get this to work, I changed the *from*
parameter again from "body" to "//h4[@class='yes']" (without the 1 indexer)
and it works, but the number is in relation to the ordinal position from the
current table and not the first table in the document - which is what I am
after. :(

So <xsl:number from="..."> works ok in MSXML 3.0 & 4.0 and in XML .NET. But
in the XML .NET it doesn't work when the @from parameter contains ordinal
position indexer. Seems strange.

???

b0yce


[quoted text, click to view]

<xsl:number> problem - Solution using position() b0yce
5/27/2004 10:01:18 AM
I have managed to get this to work now in XML .NET.

One that don't work (only in XML .NET but fine in MSXML 3.0 and 4.0);

<xsl:number level="any" from="//H4[@class='yes'][1]" />

One that works in all versions;

<xsl:number level="any" from="//H4[@class='yes'][position()=1] />

I am surprised myself that I never tried this before, but I *always* use the
shorthand of [1] instead of [position() = 1] - just my lazy development
techniques ;).

The shorthand works in all but XML .NET version so I am not sure if this is
by design that it doesn't work or whether it is a slight oversight.
Eitherway I am happy I have found a solution.

So hopefully this will serve as some useful information for others out
there!

Enjoy

b0yce

AddThis Social Bookmark Button