cross-document predicates
Tuesday, 11 February 2014 · 4 messages · last reply 12 Feb 2014
SG
Simon Görke11 Feb 2014 18:58 #
Hello there,
I am not really sure if the following is an issue or just a lack of understanding on my side.
I have two documents and try to find elements from one based on (attribute-stored) constraints given in the other.
A basic example structure looks as follows:
<commands>
<create-db name='test1'/>
<add path='doc_a'><a><a1 id='1'/><b1 ref='1'/></a></add>
<add path='doc_b'><b><b1 ref='1'/></b></add>
</commands>Queries:
//a1[@id=//a/b1/@ref]
=> 1 hit
//a1[@id=//b/b1/@ref]
=> no hits?
When putting the nodes in one and the same document (adding a common parental node), either query returns 1 hit:
<commands>
<create-db name='test2'/>
<add path='doc'><any><a><a1 id='1'/><b1 ref='1'/></a><b><b1
ref='1'/></b></any></add>
</commands>What I would have expected is 1 hit in any of the cases, but finding the correct context in predicate expressions confused me more than one time...
Regards,
Simon
(BaseX Version is 7.8 beta 8f51466)
CG
Christian Grün11 Feb 2014 19:27 #
Hi Simon,
thanks for your mail. The reason for the surprising query result is that the root expression ("/") points to the document node of the node which is in the current context. In your query, this is the first document ("doc_a"):
//a1[@id = /......
I agree that the result is somewhat surprising, because you would possibly expect "/" to return all documents of your collection.
The following query will return the expected results (and it will usually be evaluated faster if you have indexed your documents):
let $refs := //b/b1/@ref
return //a1[@id = $refs]In this case, "/" is applied to all nodes in your initial context. As you are starting with the document nodes anyway, the following query would be equivalent:
let $refs := descendant::b/b1/@ref
return descendant::a1[@id = $refs]Hope this helps; feel free to ask for more details,
Christian
Quoted text · Simon Görke · 44 lines
On Tue, Feb 11, 2014 at 6:58 PM, Simon Görke <simon.goerke at ils.uni-stuttgart.de> wrote: > Hello there, > > I am not really sure if the following is an issue or just a lack of > understanding on my side. > I have two documents and try to find elements from one based on > (attribute-stored) constraints given in the other. > A basic example structure looks as follows: > > <commands> > <create-db name='test1'/> > <add path='doc_a'><a><a1 id='1'/><b1 ref='1'/></a></add> > <add path='doc_b'><b><b1 ref='1'/></b></add> > </commands> > > Queries: > //a1[@id=//a/b1/@ref] > => 1 hit > > //a1[@id=//b/b1/@ref] > => no hits? > > When putting the nodes in one and the same document (adding a common > parental node), either query returns 1 hit: > > <commands> > <create-db name='test2'/> > <add path='doc'><any><a><a1 id='1'/><b1 ref='1'/></a><b><b1 > ref='1'/></b></any></add> > </commands> > > What I would have expected is 1 hit in any of the cases, but finding the > correct context in predicate expressions confused me more than one time... > > Regards, > Simon > (BaseX Version is 7.8 beta 8f51466) > > > _______________________________________________ > BaseX-Talk mailing list > BaseX-Talk at mailman.uni-konstanz.de > https://mailman.uni-konstanz.de/mailman/listinfo/basex-talk
SG
Simon Görke12 Feb 2014 09:57 #
Christian,
many thanks for your elaborations.
It seems this is not really a 100% baseX topic any more, but maybe you (or somebody else) can give me another hint anyway.
Quoted text · Christian Grün · 1 line
> I agree that the result is somewhat surprising, because you would possibly
expect "/" to return all documents of your collection.
This is exactly what I assumed (and hoped for) :-(
Quoted text · Christian Grün · 1 line
> The following query will return the expected results (and it will usually
be evaluated faster if you have indexed your documents):
Quoted text · Christian Grün · 2 lines
> let $refs := //b/b1/@ref > return //a1[@id = $refs]
The problem is that for my application, I require pure xpath expressions (we have a GUI which is configurable by defining tuples of 1. a xpath expression to address data and 2. the desired gui / widget representation). However, if I got the implications of your explanation right, it seems to be impossible to solve my issue by using xpath only as it would require using two different contexts in one and the same expression.
Could you (or another xpath pro) confirm this assumption of mine or maybe even come up with an alternate (non-xquery) idea?
TIA
Simon
CG
Christian Grün12 Feb 2014 12:51 #
Quoted text · Simon Görke · 3 lines
> The problem is that for my application, I require pure xpath expressions (we > have a GUI which is configurable by defining tuples of 1. a xpath expression > to address data and 2. the desired gui / widget representation).
If your application supports functions, or if it's compliant with XPath 2.0, you could use doc() and collection() inside your query:
collection('db')//a1[@id = collection('db')//b/b1/@ref]
As an alternative, you could store your documents in a single database:
create db test1 <root/>
insert node <a><a1 id='1'/><b1 ref='1'/></a> into /
insert node <b><b1 ref='1'/></b> into /
optimize (...optional)
xquery //a1[@id=//b/b1/@ref]
This makes no real difference to BaseX, but it may not be an option in your application (?).
Christian
[1] http://www.w3.org/TR/xpath-functions/#func-collection
Written for BaseX 7.7, 7.8. BaseX may have changed since: please check the current documentation.
⚡Generated with XQuery