- 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>
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 UTC