[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Cross-referencing accross multiple documents and sorti

Subject: Cross-referencing accross multiple documents and sorting: Bug in MSXML4 SP1 when using current() in an xsl:sort/@select value
From: David Chryst <dchryst@xxxxxxxxx>
Date: Mon, 29 Apr 2002 11:20:46 -0700 (PDT)
xml id refid
Subject: Cross-referencing accross multiple documents
and sorting: Bug in MSXML4 SP1 when using current() in
an xsl:sort/@select value
Date: 29 Apr, 2002

FYI:
There is a bug in MSXML4 when using current() in an
xsl:sort/@select value.  In that context, current()
resolves to the wrong node.  Microsoft will release a
fix with MSXML 4.0 Serivce Pack 2.  No date has been
set for that release. 

Normally, you can use a key() function when doing a
cross-reference sort.  However, sometimes you have to
cross-reference data in 2 separate XML documents and
do a sort.  For example, suppose you get 1 XML
document from some SOAP service that includes month
names in the data.  You could define the order of
months in some static XML document and cross-refence
that month-order XML document in your XSLT script
using the document() function.  In this case, you
can't use a key element with the data in the static
XML file!  

Using the current() function: rather than performing 2
separate transforms, I was able to use a single
transform, but I had to use the current() function
call in the xsl:sort/@select value.  This worked great
in production for several XSLT scripts when I used
MSXML3, but my sort returned data in document order
once I upgraded to MSXML4.

Here's an example.  This example is simpler than what
I'm using in production, but it demonstrates the bug:

Here's my dynamically-generated XML:  Execute the XSLT
against this document.
<large-collection>
	<collection name = "groupA">
		<ref refid="1"/>
		<ref refid="3"/>
	</collection>
	<collection name = "groupB">
		<ref refid="3"/>
		<ref refid="4"/>
	</collection>
	<collection name = "groupC">
		<ref refid="1"/>
		<ref refid="2"/>
		<ref refid="3"/>
		<ref refid="4"/>
		<ref refid="5"/>
		<ref refid="6"/>
		<ref refid="7"/>
		<ref refid="8"/>
		<ref refid="9"/>
	</collection>
</large-collection>


Here's my static XML document that I am
cross-referencing.  I saved it to c:\temp\parts.xml 
Do not execute the XSLT against this XML document. 
This file is cross_refenced in the xsl.  If you save
this XML as something other than c:\temp\parts.xml,
you must alter the XSLT script.
<parts>
	<part id="1" type="type-a" name="name-a"/>
	<part id="2" type="type-a" name="name-b"/>
	<part id="3" type="type-b" name="name-c"/>
	<part id="4" type="type-d" name="name-d"/>
	<part id="5" type="type-b" name="name-e"/>
	<part id="6" type="type-c" name="name-f"/>
	<part id="7" type="type-d" name="name-g"/>
	<part id="8" type="type-b" name="name-h"/>
	<part id="9" type="type-c" name="name-i"/>
</parts>


Here's my XSLT that takes the parts referenced in
groupC of the dynamically-generated XML, and sorts all
the parts in that group by type, then by name:
<?xml version="1.0"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
	<xsl:output method="html" />
	<xsl:variable
name="MyGroup">groupC</xsl:variable><!--normally this
would be a param-->
	<xsl:variable name="MyParts"
select="document('c:\temp\parts.xml')/parts"/>

	<xsl:template match="/large-collection">
		<xsl:apply-templates select="collection[@name =
$MyGroup]" />
	</xsl:template>

	<xsl:template match="/large-collection/collection">
		<xsl:for-each select="ref">
			<xsl:sort select="$MyParts/part[@id =
(current())/@refid]/@type" order="ascending"/>
			<xsl:sort select="$MyParts/part[@id =
(current())/@refid]/@name" order="ascending"/>
			type: <xsl:value-of
select="concat($MyParts/part[@id =
(current())/@refid]/@type, '  name: ',
$MyParts/part[@id = (current())/@refid]/@name, '  id:
', $MyParts/part[@id = (current())/@refid]/@id)"/>
		</xsl:for-each>
	</xsl:template>

</xsl:stylesheet>


Here's the output I get when I execute the XSLT using
MSXML3 DOM and processor:
type: type-a  name: name-a  id: 1
type: type-a  name: name-b  id: 2
type: type-b  name: name-c  id: 3
type: type-b  name: name-e  id: 5
type: type-b  name: name-h  id: 8
type: type-c  name: name-f  id: 6
type: type-c  name: name-i  id: 9
type: type-d  name: name-d  id: 4
type: type-d  name: name-g  id: 7


Here's the output I get when I execute the same XSLT
using MSXML4 DOM and processor:
type: type-a  name: name-a  id: 1
type: type-a  name: name-b  id: 2
type: type-b  name: name-c  id: 3
type: type-d  name: name-d  id: 4
type: type-b  name: name-e  id: 5
type: type-c  name: name-f  id: 6
type: type-d  name: name-g  id: 7
type: type-b  name: name-h  id: 8
type: type-c  name: name-i  id: 9


Possible workarounds:
1) Normally, one can avoid using the current function
call by simply using a key.  That is not possible in
this case because XSLT does not allow you to form a
key from an outside document XML tree.

2) You could duplicate the data kept in
c:\temp\parts.xml in every dynamically-generated XML
document (by modifying the SOAP service that generates
the XML or by running an extra transform) but that
seems a little in-elegant!

3) You can revert back to MSXML3 or some other XSLT
processor that allows use of current() in an
xsl:sort/@select value.

4) You can wait for MSXML4 SP2

David Chryst


__________________________________________________
Do You Yahoo!?
Yahoo! Health - your guide to health and wellness
http://health.yahoo.com

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.