This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Confusion with the usage of preceding and preceding-sibling axes


I am witnessing a strange behavior with the understanding the concept of
preceding and preceding-sibling axis.     I am using xsl:key to construct a
list of unique elements and later on using xsl:for-each to display these
unique results. I am observing that both preceding and preceding-sibling are
producing the same output, which is surprising since, preceding-sibling is
supposed to return all the siblings that occur before the context node in
the document order and belong to the same parent.


I have used Xalan-j_2_2_D10 and Saxon 6.4.4 but both produce the same result
which makes me believe that I am missing something and there is a concept
that I haven't understood yet.

It would be clearer by reading the example below

source XML( This is a sample XML which has a similar structure to what I am
working on)

<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- File Created on   03-Oct-2001 13:10:34-->
<!DOCTYPE ALBUM_LIST>
<ALBUM_LIST>
	<ALBUM ID="Q9001">
		<TRACK ID="001"/>
		<TRACK ID="002"/>
		<TRACK ID="003"/>
	</ALBUM>
	<ALBUM ID="Q9001">
		<TRACK ID="004"/>
		<TRACK ID="005"/>
		<TRACK ID="003"/>
	</ALBUM>
	<ALBUM ID="Q9001">
		<TRACK ID="006"/>
		<TRACK ID="002"/>
		<TRACK ID="003"/>
	</ALBUM>
</ALBUM_LIST>

I want to extract the list of all unique tracks, which would be tracks with
ID 001,002,003,004,005,006. Here is the XSL that I am using

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
version="1.0" xmlns:lxslt="http://xml.apache.org/xslt";>
<xsl:output method="xml" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:key name="ALBUM_TRACK"
match="ALBUM/TRACK[not(@ID=preceding::node()/@ID)]" use="@ID"/>

<xsl:template match="/" >
  <objects>
    <xsl:apply-templates select="ALBUM_LIST/ALBUM"/>
  </objects>
</xsl:template>

<xsl:template match="ALBUM">
    <xsl:for-each
select="TRACK[generate-id()=generate-id(key('ALBUM_TRACK',@ID))]">
      <object name="TRACK">
	<xsl:value-of select="@ID"/>
      </object>
    </xsl:for-each>
</xsl:template>
</xsl:stylesheet>


OUTPUT

<?xml version="1.0" encoding="UTF-8"?>
<objects>
<object  name="TRACK">001</object>
<object  name="TRACK">002</object>
<object  name="TRACK">003</object>
<object  name="TRACK">004</object>
<object  name="TRACK">005</object>
<object  name="TRACK">006</object>
</objects>

I think that preceding-sibling should produce the following output
<?xml version="1.0" encoding="UTF-8"?>
<objects>
<object  name="TRACK">001</object>
<object  name="TRACK">002</object>
<object  name="TRACK">003</object>
<object  name="TRACK">004</object>
<object  name="TRACK">005</object>
<object  name="TRACK">003</object>
<object  name="TRACK">006</object>
<object  name="TRACK">002</object>
<object  name="TRACK">003</object>
</objects>

As, within each individual ALBUM elemtns there are discinct TRACK elements
and hence I would not get any unique list of TRACK objects

This looks like a very simple XSL transformation. Now if I replace
preceding by preceding-sibling in the xsl:key definition, still the OUTPUT
is the SAME. Though there is a significant performance gain. I thought  that
this is wrong behavior and probably a bug in Xalan  but after getting the
same output with Saxon, I think that I don't understand the concept well .
How can preceding and preceding-sibling produce the same result. Using
preceding-sibling, the xsl-key should NOT store the unique Tracks, as it
cannot look beyond the parent of Track namely Album, but it seems that
preceding-sibling looks into all the ALBUM elements and thus selects unique
TRACK elements.

Please let me know what exactly am I missing in my understanding of
preceding and preceding-sibling.

thanx
Nisheet


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]