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

Re: Key()

Subject: Re: Key()
From: Richard Light <richard@xxxxxxxxxxxxxxxxx>
Date: Wed, 28 Jun 2000 09:31:15 +0100
my space.com.au
In message <3959B9F9.252AAE25@xxxxxxxxxxxxxx>, 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@xxxxxxxxxxxxxxxxx


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


Current Thread

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.