Re: [xsl] xsl value-of

Subject: Re: [xsl] xsl value-of
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Tue, 2 Apr 2002 19:32:25 +0100
Hi Matias,

> I created a key in the top of the document
>
> <xsl:key name="labels" match="xml/group/questionAnswered/label/text()"
> use="concat(xml/group/@id, '_', xml/group/questionAnswered/label/@id)" />

Hmm... OK, this is the problem.

Keys build up named tables of nodes and values which enable you to
quickly get at a set of nodes that are associated with a particular
value.

When an XSLT processor builds up one of these tables, it goes through
the document and finds all the nodes that match the pattern held in
the match attribute. With your definition, a processor would locate
all the text nodes in the document that are children of a label
element that is a child of a questionAnswered element that is a child
of a group element that is a child of an xml element.

(By the way 'xml' is an illegal name for an element -- XML parsers
should object to you using it.)

When it finds a matching node, the XSLT processor evaluates the
expression held in the use attribute to create a value for the node,
by which the node is indexed. When it evaluates this expression, it
uses the node that it's indexing as the current node -- so any
relative paths are evaluated relative to the matched node.

In your case, the expression is:

  concat(xml/group/@id, '_', xml/group/questionAnswered/label/@id)

The current node is a text node under a label element. You're asking
the processor to concatenate the id of the group element of the xml
element *child* of the *text node* with an underscore and the id of
the label element of the ... of the xml element *child* of the *text
node*. Text nodes don't have children, so these paths are doomed to
failure.

What you're trying to do is index the text node by the id of the text
node's *ancestor* group element, concatenated with an underscore and
the id of the text node's *parent* label element. So what you need is:

<xsl:key name="labels" match="xml/group/questionAnswered/label/text()"
         use="concat(ancestor::group/@id, '_', parent::label/@id)" />

Personally, since the label element doesn't hold mixed content, and
since the label elements don't occur anywhere aside from within
questionAnswered elements that are children of group elements that are
children of xml elements, I'd use the definition:

<xsl:key name="labels" match="label"
         use="concat(ancestor::group/@id, '_', @id)" />

The fact that the label elements don't contain mixed content means
that getting the value of a label element gives you exactly the same
as getting the value of the label element's text node child. The fact
that you're interested in all label elements means that there's no
need to add all that checking of ancestor elements to the match
pattern -- not having to check that the label element is a child of
questionAnswered and so on will save the processor a little bit of
work. The definition looks easier, too!

The rest of the code should work fine.

Cheers,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/


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


Current Thread