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

Re: XQuery Predicate syntax

From: Philippe Michiels <philippe.michiels@ua.ac.be>
Date: Fri, 23 Apr 2004 16:35:47 +0200
To: Jeni Tennison <jeni@jenitennison.com>
Cc: www-ql@w3.org, Murali Mani <mani@CS.UCLA.EDU>
Message-Id: <200404231635.47514.philippe.michiels@ua.ac.be>

XQuery has quite a lot of these pitfalls. Many of them are covered in this 
article:
http://otn.oracle.com/oramag/oracle/04-jan/o14dev_xml.html

On Friday 23 April 2004 14:20, Jeni Tennison wrote:
> 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/

-- 
Philippe Michiels
Universiteit Antwerpen
ADReM (Advanced Database Research and Modelling)
http://www.adrem.ua.ac.be/~michiels
Received on Friday, 23 April 2004 11:21:51 GMT

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