W3C home > Mailing lists > Public > www-ql@w3.org > April to June 2004

Re: XQuery Predicate syntax

From: Jeni Tennison <jeni@jenitennison.com>
Date: Fri, 23 Apr 2004 13:20:29 +0100
Message-ID: <457979046.20040423132029@jenitennison.com>
To: www-ql@w3.org
Cc: Murali Mani <mani@CS.UCLA.EDU>, Philippe Michiels <philippe.michiels@ua.ac.be>

Philippe Michiels wrote:
> These two queries are different:
>
>> //student["Adam"]/advisor
>
> In this query, the predicate's effective boolean value is computed
> and, as it is a non empty string, it evaluates to true.
>
>> //student[text () = "Adam"]/advisor
>
> This query selects all students where the combined text nodes are
> equal to "Adam".

Not the combined text nodes, rather *any* text node. Say you had the
(unvalidated, with comments retained) XML:

  <student>Adam<?editor cursor?>antine</student>

The <student> element here has two text node children, "Adam" and
"antine". The test text() = "Adam" would return true because one of
the text nodes (the first one) has the value "Adam". The test text()
eq "Adam" would give you an error because there are two text nodes and
eq can only be used to compare single values.

(If the <student> element was validated with a type of xs:string or
similar, then different processors might give you different results,
since processors are allowed to interpret the element as having a
single text node child with the full value "Adamantine".)

To test the "combined text nodes", you could use:

  //student[string-join(text(), "") = "Adam"]

but usually that's not what you want either, because this would ignore
text inside elements. If you had:

  <student><capital>A</capital>dam</student>

then string-join(text(), "") would only locate the immediate child
"dam" text node, not the "A" which is a descendant text node.

What you actually want to test is the string value of the <student>
element: the concatenation of all the descendant text nodes. You can
get this using the string() function:

  //student[string(.) = "Adam"]

In unvalidated XML, the typed value is the same as the string value of
an element, so you can use the even easier . to get the typed value of
the context node:

  //student[. = "Adam"]

In validated XML, it depends on the type of the <student> element. If
it just has simple content then you can do the above, but if it has
complex content, you need to use the string() function to get the
string value.
  
Note: The original question used the query //student["Adam"]/advisor.
It's not clear what XML structure that is supposed to query. If it's:

  <student>Adam<advisor>Benny</advisor></student>

then you need //student[text()[1] = "Adam"]/advisor (test the first
child text node against the string), but this is badly designed XML
(mixed content for data-oriented information), so I assume that this
isn't what was wanted.

Cheers,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/
Received on Friday, 23 April 2004 08:20:56 GMT

This archive was generated by hypermail 2.2.0+W3C-0.50 : Saturday, 22 July 2006 00:10:19 GMT