问题
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:
- 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. - 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