4

A test sample of my xml file is shown below:

test.xml

<feed>
  <entry>
    <title>Link ISBN</title>
    <libx:libapp xmlns:libx="http://libx.org/xml/libx2" />
  </entry>
  <entry>
    <title>Link Something</title>
    <libx:module xmlns:libx="http://libx.org/xml/libx2" />
  </entry>
</feed>

Now, I want to write an xquery which will find all <entry> elements which have <libx:libapp> as a child. Then, for all such entries return the title if the title contains a given keyword (such as Link). So, in my example xml document the xquery should return "Link ISBN".

My sample xquery is shown below:

samplequery.xq (here doc_name is the xml file shown above and libapp_matchkey is a keyword such as 'Link')

declare namespace libx='http://libx.org/xml/libx2';
declare variable $doc_name as xs:string external;
declare variable $libpp_matchkey as xs:string external;
let $feeds_doc := doc($doc_name)

for $entry in $feeds_doc/feed/entry
   (: test whether entry has libx:libapp child and has "Link" in its title child :)
   where ($entry/libx:libapp and $entry/title/text()[contains(.,$libapp_matchkey)])
    return $entry/title/text()

This xquery is returning null instead of the expected result 'Link ISBN'. Why is that?

2
  • I've replaced $food_doc declaration as /, corrected the $libapp_matchkey typo, and successfully runned it with your input sample. Commented Dec 14, 2010 at 21:43
  • Good question, +1. See my answer for a short and natural one-liner solution :) Commented Dec 14, 2010 at 22:14

1 Answer 1

8

I want to write an xquery which will find all elements which have as a child. Then, for all such entries return the title if the title contains a given keyword (such as Link).

Just use:

/*/entry[libx:libapp]/title[contains(.,'Link')]/text()

Wrapping this XPath expression in XQuery we get:

declare namespace libx='http://libx.org/xml/libx2';
/*/entry[libx:libapp]/title[contains(.,'Link')]/text() 

when applied on the provided XML document:

<feed> 
  <entry> 
    <title>Link ISBN</title> 
    <libx:libapp xmlns:libx="http://libx.org/xml/libx2" /> 
  </entry> 
  <entry> 
    <title>Link Something</title> 
    <libx:module xmlns:libx="http://libx.org/xml/libx2" /> 
  </entry> 
</feed>

the wanted, correct result is produced:

Link ISBN
Sign up to request clarification or add additional context in comments.

10 Comments

I see the following exception when I try this: for $entry in $feeds_doc/atom:feed/atom:entry return /*/$entry[libx:libapp]/title[contains(.,'Link')]/text() Exception in thread "main" java.io.IOException: Stopped at line 9, column 13: [XPDY0002] No context item set for 'root()'.
@sony: There isn't any $entry in my answer -- You may get any possible exception on anything that isn't my answer, but why are you reporting this as a comment here?
What does /* refer to ? I mean entry elements are inside <feed> element in the document. How are you referring to $feeds_doc/feed
@sony: I have edited my answer to help you arive at a complete XQuery -- you may just execute it and you will get the wanted result.
@sony: This is simple, basic XPath (and I seriously doubt that one can do XQuery without knowledge of XPath). /* selects the top element of any XML document (because in any well-formed XML document there must be a single top element). This is why we don't bother (and thus save time and space) to specify the name of the top element.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.