This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Re: Key()
- To: xsl-list at mulberrytech dot com
- Subject: Re: Key()
- From: Richard Light <richard at light dot demon dot co dot uk>
- Date: Wed, 28 Jun 2000 09:31:15 +0100
- References: <3959B9F9.252AAE25@n-space.com.au>
- Reply-To: xsl-list at mulberrytech dot com
In message <3959B9F9.252AAE25@n-space.com.au>, Rhonda Fischer <rhonda@n-
space.com.au> writes
>
>I have been drawing result trees and applying XPath expressions
>in an endeavour to fully understand how my use of the key()
>function is working. But still the outcome is not quite right.
>Not only is there an ordering problem but also my index
>seems to contain only a duplication of the first paragraph.
>Perhaps I am missing something obvious?
><Template>
> <Destination>
> <Target doc="contract"/>
> <Target doc="advice"/>
> <Target host="true"/>
> <Section><SectionHeading>My Heading
> </SectionHeading></Section>
> <Para>
> This paragraph appears in both the contract
> and advice documents and is only included
> for those customers hosting.
> </Para>
>Transform.xsl
>-----------
>
><xsl:key name="blueprint" match="Para"
> use="concat(preceding-sibling::Target/@doc, '-',
> preceding-sibling::Target/@host)"/>
Your first preceding-sibling expression asks for all the 'doc'
attributes of Target elements preceding the Para currently in scope.
Since you have three Target elements, this will yield a node-set
containing three 'doc' attribute nodes (in reverse order).
Putting that node-set inside a 'concat' function causes the node-set to
be converted to a string. This is done by providing "the string value
of the node that is first in document order" (quote from Mike Kay's XSLT
Programmer's Reference - an indispensible source - p509).
Thus, according to the letter of the law, you should get the value
'contract' for this part of the 'concat' expression. However, I find
this counter-intuitive - it would make more sense to me to provide the
value of the first node in the node-set, which in this case is an empty
string since the last Target has no 'doc' attribute.
What you probably want is a test that the nodes in your node-sets
actually have the attribute you are interested in:
<xsl:key name="blueprint" match="Para"
use="concat(preceding-sibling::Target[@doc]/@doc, '-',
preceding-sibling::Target[@host]/@host)"/
>
In addition, you might want to specify that you just want the first node
in that node-set (to deal with the case where there is more than one
Target with the required attribute):
<xsl:key name="blueprint" match="Para"
use="concat(preceding-sibling::Target[@doc]/@doc[1], '-',
preceding-sibling::Target[@host]/@host[1]
)"/>
Hope this moves things forward!
Richard Light.
Richard Light
SGML/XML and Museum Information Consultancy
richard@light.demon.co.uk
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list