run xpath from xquery against a database?

北城余情 提交于 2019-12-08 11:37:39

问题


How do I run an xpath query from within an xquery script with the basex GUI?

successful xpath query of a database:

failed xquery attempt:

The simplest possible xquery code for this database:

thufir@dur:~/basex$ 
thufir@dur:~/basex$ cat db_list_items.xq 

let $db := db:open("list")

return root()/descendant::li/a/text()

thufir@dur:~/basex$ 

Not quite sure how to return results above.

error log from the basex GUI:

Error:
Stopped at /home/thufir/basex/db_list_items.xq, 4/12:
[XPDY0002] root(): no context value bound.
Compiling:
- pre-evaluate db:open(database[,path]) to document-node(): db:open("list") -> db:open-pre("list", 0)
- inline $db_0
- simplify gflwor
Optimized Query:
root()/descendant::li/a/text()
Query:
let $db := db:open("list") return root()/descendant::li/a/text()
Query plan:
<QueryPlan compiled="true" updating="false">
  <CachedPath type="text()*">
    <FnRoot name="root([node])" type="node()?"/>
    <IterStep axis="descendant" test="li" type="element()*"/>
    <IterStep axis="child" test="a" type="element()*"/>
    <IterStep axis="child" test="text()" type="text()*"/>
  </CachedPath>
</QueryPlan>

looking for simple query of this database using basex.


回答1:


Just like navigating a filesystem (or any other tree based structure), we need to know our place within that structure, in order to be able to use path expressions:

/home/logname/documents/work #> cd todo
/home/logname/documents/work/todo #>

How did the command line interpreter know, where to find the todo directory? It knew this, because, by convention, it assumed the context for the cd command to be the current directory, which is /home/logname/documents/work, in this case.

When you load a document/database into BaseX, it does the same for XPath expressions and also XQuerys, as long the context is clear. If you, for example, place a single dot . in the query editor, and then execute that query, it will give you back the whole document, since this is what . stands for: the current context item. Here, BaseX knows this context from the convention, that it executes, by default, queries against the currently loaded document, just like a command line interpreter assumes the current directory as the current context. One could say, that by loading the document/database, you cd'ed into the root of that document. So far so good...

As soon as you use XQuery, you are using a complete programming language, that allows for much more, than just querying single documents. You could query a whole bunch of documents within one script.

Take this (incomplete) code fragment:

let $db  := db:open("list")
let $db2 := db:open("list2")

If you now place queries the way you did, where do they go? Are they using $db as context or $db2?

What you need to do is to tell the processor about this. This can be done several ways:

  1. in the prolog of your script: declare context item := db:open("list"); (see also: BaseX documentation on this and, very important, read about the difference between "static context" and "dynamic context" here) to learn more about context, in general.
  2. in the XPath expression itself:
let $db := db:open("list")
return $db/root()/descendant::li/a/text()

or, simplified:

let $db := db:open("list")
return $db//li/a/text()

or:

declare context item := db:open("list");

.//li/a/text()


来源:https://stackoverflow.com/questions/53995730/run-xpath-from-xquery-against-a-database

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!