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]

Re: simple XPath question


Hi Chris,

Yours is a problem that nicely demonstrates why position() can be tricky to 
use except in very clearly controlled situations. (It's sometimes 
recommended as an alternative to more expensive operations, but it has its 
own traps to watch out for.)

The function returns the "context position" of the node being processed. 
This is tricky because the context position is the position of the node 
among the nodes it is picked up with, when it's picked up, i.e. the 
"current node list". And what, exactly, the current node list is, is 
sometimes a bit hard to see -- especially when things like whitespace-only 
nodes (which are easy not to see) get involved.

At 09:47 PM 7/2/01, you wrote:
>I am trying to work through an example in Khun Yee Fung's XSLT book.  It is
>not giving me the solution he claims it should, but I do not understand why
>not.
>
>Here is the sample XML:
>[snipped]
>And here is the stylesheet:
>[more snipped]
><xsl:template match='warehouse'>
>   <storage>
>     <xsl:apply-templates select='item/country'/>
>   </storage>
></xsl:template>
>
><xsl:template match='country'>
>   <xsl:copy-of select='.'/>
></xsl:template>
>
><xsl:template match='country[1]'>
>   <first-country>
>     <xsl:copy-of select='.'/>
>   </first-country>
></xsl:template>
>
></xsl:stylesheet>
>
>The output I am getting [using Saxon] is:
><?xml version="1.0" encoding="utf-8"?>
><storage>
>    <first-country>
>       <country>US</country>
>    </first-country>
>    <first-country>
>       <country>Canada</country>
>    </first-country>
></storage>
>
>i.e., the first-country template is getting matched both times, even though
>the XPath expression uses country[1].

This is correct behavior. Each time the country element in your source is 
selected, it is the first country element among country element children of 
its parent. So both of them match the expression 
"child::country[position()=1]" (which is the unabbreviated form of the 
expression "country[1]").

>   What seems strange to me is that when
>I include the line <xsl:copy-of select='position()'/> at the beginning of
>the template matching country[1], I get a 1 and a 2.

This is also correct (though perhaps a bit arguable). Both 'country' 
elements were selected by the <xsl:apply-templates select="item/country"/> 
instruction in the template matching the 'warehouse' element. This is short 
for select="child::item/child::country". Since each is the first 'country' 
child of its parent 'item', both get position()=1. (The reason I say it's 
arguable is that I can see someone saying "but isn't the current node list 
the list of country children of item children"? But I'm not quite willing 
to dig into the spec this second and hash out why it's not.)

>I believe I am supposed to get:
><storage>
><first-country>
>   <country>US</country>
></first-country>
><country>Canada</country>
></storage>
>
>Am I doing something wrong, or is the example in Fung's book (Chapter 6, p.
>149) wrong?  How should the stylesheet be structured to get the intended
>output?

I can't speak to Fung's book since I don't have a copy. :-(

But a more robust match to do what you want would be

<xsl:template match="country[not(preceding::country)]" >

or, if you're concerned about performance (since this match will be slow on 
large documents), you can try

<xsl:template match="country[not(preceding::country)[1]]" >

which will allow some processors to optimize the test somewhat.

Hope that helps,
Wendell

======================================================================

Wendell Piez                            mailto:wapiez@mulberrytech.com
Mulberry Technologies, Inc.                http://www.mulberrytech.com
17 West Jefferson Street                    Direct Phone: 301/315-9635
Suite 207                                          Phone: 301/315-9631
Rockville, MD  20850                                 Fax: 301/315-8285
----------------------------------------------------------------------
   Mulberry Technologies: A Consultancy Specializing in SGML and XML
======================================================================


 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]