This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Re: simple XPath question
- To: xsl-list at lists dot mulberrytech dot com
- Subject: Re: [xsl] simple XPath question
- From: Wendell Piez <wapiez at mulberrytech dot com>
- Date: Mon, 02 Jul 2001 18:45:32 +0100
- Reply-To: xsl-list at lists dot mulberrytech dot com
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