You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@xalan.apache.org by bu...@apache.org on 2002/04/26 12:02:44 UTC
DO NOT REPLY [Bug 8551] New: -
incorrect order of returned nodeset from xpath expression
DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://nagoya.apache.org/bugzilla/show_bug.cgi?id=8551>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND
INSERTED IN THE BUG DATABASE.
http://nagoya.apache.org/bugzilla/show_bug.cgi?id=8551
incorrect order of returned nodeset from xpath expression
Summary: incorrect order of returned nodeset from xpath
expression
Product: XalanJ2
Version: 2.3
Platform: PC
OS/Version: Other
Status: NEW
Severity: Critical
Priority: Other
Component: Xalan-Xsltc
AssignedTo: xalan-dev@xml.apache.org
ReportedBy: alban.tsui@cognos.com
CC: alban.tsui@cognos.com
I have the following:
<rowset>
<row><indent>1/<indent><item>A</item></row>
<row><indent>2/<indent><item>B</item></row>
<row><indent>2/<indent><item>C</item></row>
<row><indent>1/<indent><item>D</item></row>
<row><indent>2/<indent><item>E</item></row>
<row><indent>3/<indent><item>F</item></row>
</rowset>
They are the indent levels for trees, so
A
B
C
D
E
F
I am using a template and xpath (using position()) to work out the item's
parent position. e.g. For B, its parent is A with position 1, For C, its
parent is A again with position 1. For F its parent is E with position 5.
The result I am after is like:
<rowset>
<row><indent>1/<indent><item>A</item><parent_index>0</parent_index></row>
<row><indent>2/<indent><item>B</item><parent_index>1</parent_index></row>
<row><indent>2/<indent><item>C</item><parent_index>1</parent_index></row>
<row><indent>1/<indent><item>D</item><parent_index>0</parent_index></row>
<row><indent>2/<indent><item>E</item><parent_index>4</parent_index></row>
<row><indent>3/<indent><item>F</item><parent_index>5</parent_index></row>
</rowset>
Using the template in xalan:
<xsl:template match="/rowset">
<rowset>
<xsl:for-each select="row">
<xsl:variable name="currindent" select="indent"/>
<row>
<indent><xsl:value-of select="indent"/></indent>
<item><xsl:value-of select="item"/></item>
<xsl:variable name="pname" select="(preceding-sibling::*
[indent=number($currindent)-1])[last()]"/>
<subset>
<xsl:for-each select="preceding-sibling::*[indent=number
($currindent)-1]">
<item><xsl:value-of select="item"/></item>
</xsl:for-each>
</subset>
<parent_name><xsl:value-of select="$pname/item"/></parent_name>
<xsl:choose>
<xsl:when test="count($pname)=0">
<parent_index>0</parent_index>
</xsl:when>
<xsl:otherwise>
<parent_index><xsl:value-of select="count
($pname/preceding-sibling::row)+1"/></parent_index>
</xsl:otherwise>
</xsl:choose>
</row>
</xsl:for-each>
</rowset>
</xsl:template>
I have the result:
<?xml version="1.0" encoding="UTF-8"?>
<rowset>
<row>
<indent>1</indent>
<item>A</item>
<subset/>
<parent_name/>
<parent_index>0</parent_index>
</row>
<row>
<indent>2</indent>
<item>B</item>
<subset>
<item>A</item>
</subset>
<parent_name>A</parent_name>
<parent_index>1</parent_index>
</row>
<row>
<indent>2</indent>
<item>C</item>
<subset>
<item>A</item>
</subset>
<parent_name>A</parent_name>
<parent_index>1</parent_index>
</row>
<row>
<indent>1</indent>
<item>D</item>
<subset/>
<parent_name/>
<parent_index>0</parent_index>
</row>
<row>
<indent>2</indent>
<item>E</item>
<subset>
<item>A</item>
<item>D</item>
</subset>
<parent_name>D</parent_name>
<parent_index>4</parent_index>
</row>
<row>
<indent>3</indent>
<item>F</item>
<subset>
<item>B</item>
<item>C</item>
<item>E</item>
</subset>
<parent_name>E</parent_name>
<parent_index>5</parent_index>
</row>
</rowset>
which is correct.
Doing the same thing with the same transform compiled in xsltc I got a
DIFFERENT result:
<?xml version="1.0" encoding="UTF-8"?>
<rowset>
<row>
<indent>1</indent>
<item>A</item>
<subset/>
<parent_name/>
<parent_index>0</parent_index>
</row>
<row>
<indent>2</indent>
<item>B</item>
<subset>
<item>A</item>
</subset>
<parent_name>A</parent_name>
<parent_index>1</parent_index>
</row>
<row>
<indent>2</indent>
<item>C</item>
<subset>
<item>A</item>
</subset>
<parent_name>A</parent_name>
<parent_index>1</parent_index>
</row>
<row>
<indent>1</indent>
<item>D</item>
<subset/>
<parent_name/>
<parent_index>0</parent_index>
</row>
<row>
<indent>2</indent>
<item>E</item>
<subset>
<item>D</item>
<item>A</item>
</subset>
<parent_name>A</parent_name>
<parent_index>1</parent_index>
</row>
<row>
<indent>3</indent>
<item>F</item>
<subset>
<item>E</item>
<item>C</item>
<item>B</item>
</subset>
<parent_name>B</parent_name>
<parent_index>1</parent_index>
</row>
</rowset>
The result is wrong because in the <subset> tag the <item>s are returned in
reverse order in xsltc using the same xpath:
select="preceding-sibling::*[indent=number($currindent)-1]"
In order to get the same result I need to modify/hack my template into the
following:
<xsl:template match="/rowset">
<rowset>
<xsl:for-each select="row">
<xsl:variable name="currindent" select="indent"/>
<row>
<indent><xsl:value-of select="indent"/></indent>
<item><xsl:value-of select="item"/></item>
<xsl:variable name="pname" select="(preceding-sibling::*
[indent=number($currindent)-1])[1]"/>
<subset>
<xsl:for-each select="preceding-sibling::*[indent=number
($currindent)-1]">
<item><xsl:value-of select="item"/></item>
</xsl:for-each>
</subset>
<parent_name><xsl:value-of select="$pname/item"/></parent_name>
<xsl:choose>
<xsl:when test="count($pname)=0">
<parent_index>0</parent_index>
</xsl:when>
<xsl:otherwise>
<parent_index><xsl:value-of select="count
((preceding-sibling::*[indent=number($currindent)-1])[1]/preceding-sibling::row)
+1"/></parent_index>
</xsl:otherwise>
</xsl:choose>
</row>
</xsl:for-each>
</rowset>
</xsl:template>
Instead of using "last()" I am using one "1" for the line:
<xsl:variable name="pname" select="(preceding-sibling::*[indent=number
($currindent)-1])[1]"/>
in order to get the right result in xsltc.
Notice that in xsltc hacked version of template, I could not use the line:
<parent_index><xsl:value-of select="count($pname/preceding-sibling::row)
+1"/></parent_index>
because in xsltc it seems that it does NOT store the nodeset into $pname
variable correctly. Therefore I had to use
<parent_index><xsl:value-of select="count((preceding-sibling::*
[indent=number($currindent)-1])[1]/preceding-sibling::row)+1"/></parent_index>
the full line to get it working.