Order of nodes in reversed axes
Mr. Atria, You left out a key element from the answer you got from stack overflow.
Note that Dimitre's response used a filter expression (path expression) [predicate]
not a simple path expression
The ()s are critical.
$test//child/ancestor-or-self::test[ last() ]is very different from
($test//child/ancestor-or-self::test)[ last() ]
The ancestor axis is a reverse axis, but when the xpath expression is complete, the sequence of nodes are then put in document order regardless of what order the last axis had.
In any event, I don't understand what is wrong with simply $test/ancestor::element()[1]
Perhaps I don't understand your question (which is simpler than the Stack Overflow question you linked to). But if you are just looking for the nearest ancestor element, then it seems that $test/ancestor::element()[1] should give it to you.
More specifically, I don't understand what the difference is between "nearest ancestor element" and "parent."
Quoted text · David Rudel · 28 lines
On Wed, Apr 16, 2014 at 8:45 PM, David Rudel <fwqhgads at gmail.com> wrote: > Mr. Atria, > You left out a key element from the answer you got from stack overflow. > > Note that Dimitre's response used a filter expression > (path expression) [predicate] > > not a simple path expression > > The ()s are critical. > > $test//child/ancestor-or-self::test[ last() ] > > is very different from > > ($test//child/ancestor-or-self::test)[ last() ] > > The ancestor axis is a reverse axis, but when the xpath expression is > complete, the sequence of nodes are then put in document order > regardless of what order the last axis had. > > In any event, I don't understand what is wrong with simply > $test/ancestor::element()[1] > > Perhaps I don't understand your question (which is simpler than the > Stack Overflow question you linked to). But if you are just looking > for the nearest ancestor element, then it seems that > $test/ancestor::element()[1] should give it to you.
I apologize if I'm being dense, but I don't understand how the nearest ancestor can be anything other than the parent. Could you please give an example?
I just want to make sure I haven't sent you off with the wrong expression for your intended usage.
Quoted text · José Tomás Atria · 48 lines
On Wed, Apr 16, 2014 at 8:48 PM, José Tomás Atria <jtatria at gmail.com> wrote: > Thank you all for your answers. > > I was just tryig to determine if $test/ancestor::element()[1] would be the > correct way of getting the nearest ancestor, as I couldn't find whether axes > were ordered or not in the xpath specification. > > Thanks! > > ps: Parent doesn't apply, because the relevant node is not always the > parent, but the first node with a given name. > > > On Wed, Apr 16, 2014 at 2:45 PM, David Rudel <fwqhgads at gmail.com> wrote: >> >> Mr. Atria, >> You left out a key element from the answer you got from stack overflow. >> >> Note that Dimitre's response used a filter expression >> (path expression) [predicate] >> >> not a simple path expression >> >> The ()s are critical. >> >> $test//child/ancestor-or-self::test[ last() ] >> >> is very different from >> >> ($test//child/ancestor-or-self::test)[ last() ] >> >> The ancestor axis is a reverse axis, but when the xpath expression is >> complete, the sequence of nodes are then put in document order >> regardless of what order the last axis had. >> >> In any event, I don't understand what is wrong with simply >> $test/ancestor::element()[1] >> >> Perhaps I don't understand your question (which is simpler than the >> Stack Overflow question you linked to). But if you are just looking >> for the nearest ancestor element, then it seems that >> $test/ancestor::element()[1] should give it to you. > > > > > -- > entia non sunt multiplicanda praeter necessitatem
Ah, okay. I didn't catch that you wanted "the nearest ancestor with a particular name." In that case then I think you are golden. If there is a chance that the element itself is a div1 element, then you will want to use ancestor-or-self instead, but otherwise I think you have it right.
Quoted text · José Tomás Atria · 117 lines
On Wed, Apr 16, 2014 at 9:22 PM, José Tomás Atria <jtatria at gmail.com> wrote: > That should have been ancestor::div1[1]. pardon the typo. > > > On Wed, Apr 16, 2014 at 3:21 PM, José Tomás Atria <jtatria at gmail.com> wrote: >> >> let $test := >> element div0{ >> attribute id { 4 }, >> element div1 { >> attribute id { 3 }, >> element div1 { >> attribute id { 2 }, >> element para { >> attribute id { 1 }, >> element child { } >> } >> } >> } >> } >> >> I want to get the "smallest" div1 for a given child. this is, the <div1 >> id=2> element. >> >> As far as I've understood the answers given here, reverse axes are ordered >> from the context node, so the expression >> >> $test//child/ancestor-or-self::div1[1] will get me what i want, while >> $test//child/parent() will give me <para id=1> >> >> Needless to say, my data is not particularly well behaved :) >> >> Thanks! >> >> >> On Wed, Apr 16, 2014 at 3:16 PM, David Rudel <fwqhgads at gmail.com> wrote: >>> >>> I apologize if I'm being dense, but I don't understand how the nearest >>> ancestor can be anything other than the parent. Could you please give >>> an example? >>> >>> I just want to make sure I haven't sent you off with the wrong >>> expression for your intended usage. >>> >>> On Wed, Apr 16, 2014 at 8:48 PM, José Tomás Atria <jtatria at gmail.com> >>> wrote: >>> > Thank you all for your answers. >>> > >>> > I was just tryig to determine if $test/ancestor::element()[1] would be >>> > the >>> > correct way of getting the nearest ancestor, as I couldn't find whether >>> > axes >>> > were ordered or not in the xpath specification. >>> > >>> > Thanks! >>> > >>> > ps: Parent doesn't apply, because the relevant node is not always the >>> > parent, but the first node with a given name. >>> > >>> > >>> > On Wed, Apr 16, 2014 at 2:45 PM, David Rudel <fwqhgads at gmail.com> >>> > wrote: >>> >> >>> >> Mr. Atria, >>> >> You left out a key element from the answer you got from stack >>> >> overflow. >>> >> >>> >> Note that Dimitre's response used a filter expression >>> >> (path expression) [predicate] >>> >> >>> >> not a simple path expression >>> >> >>> >> The ()s are critical. >>> >> >>> >> $test//child/ancestor-or-self::test[ last() ] >>> >> >>> >> is very different from >>> >> >>> >> ($test//child/ancestor-or-self::test)[ last() ] >>> >> >>> >> The ancestor axis is a reverse axis, but when the xpath expression is >>> >> complete, the sequence of nodes are then put in document order >>> >> regardless of what order the last axis had. >>> >> >>> >> In any event, I don't understand what is wrong with simply >>> >> $test/ancestor::element()[1] >>> >> >>> >> Perhaps I don't understand your question (which is simpler than the >>> >> Stack Overflow question you linked to). But if you are just looking >>> >> for the nearest ancestor element, then it seems that >>> >> $test/ancestor::element()[1] should give it to you. >>> > >>> > >>> > >>> > >>> > -- >>> > entia non sunt multiplicanda praeter necessitatem >>> >>> >>> >>> -- >>> >>> "A false conclusion, once arrived at and widely accepted is not >>> dislodged easily, and the less it is understood, the more tenaciously >>> it is held." - Cantor's Law of Preservation of Ignorance. >> >> >> >> >> -- >> entia non sunt multiplicanda praeter necessitatem > > > > > -- > entia non sunt multiplicanda praeter necessitatem
Hello all,
I've been looking for an authoritative answer to this, but have been unable to find one.
I'm trying to reliably get the nearest ancestor of a node. ie with this test data:
let $test :=
element test {
attribute id { 4 },
element test {
attribute id { 3 },
element test {
attribute id { 2 },
element test {
attribute id { 1 },
element child { }
}
}
}
}i want an expression that will return node test/@id=1 from child.
Stackoverflow says that this:
$test//child/ancestor-or-self::test[ last() ]Should work (here<http://stackoverflow.com/questions/6554488/how-to-get-the-nearest-ancestor-or-child-of-an-ancestor-with-xpath>), but since I couldn't find any indication to reversed axes being ordered in the w3c spec for reverse axes in xpath 2.0 (here<http://www.w3.org/TR/xpath20/#doc-xpath-ReverseAxis>), I suspected that this would be implementation dependent, and sure enough, in BaseX, that expression returns
<test id="4">
<test id="3">
<test id="2">
<test id="1">
<child/>
</test>
</test>
</test>
</test>while this
$test//child/ancestor-or-self::test[ 1 ]correctly returns
<test id="1">
<child/>
</test>Is there an authoritative way of getting the nearest ancestor of a given node? Note that in my actual use case, names are the same, and desired ids are unknown.
Thanks!
jta
Thank you all for your answers.
I was just tryig to determine if $test/ancestor::element()[1] would be the correct way of getting the nearest ancestor, as I couldn't find whether axes were ordered or not in the xpath specification.
Thanks!
ps: Parent doesn't apply, because the relevant node is not always the parent, but the first node with a given name.
Quoted text · David Rudel · 29 lines
On Wed, Apr 16, 2014 at 2:45 PM, David Rudel <fwqhgads at gmail.com> wrote: > Mr. Atria, > You left out a key element from the answer you got from stack overflow. > > Note that Dimitre's response used a filter expression > (path expression) [predicate] > > not a simple path expression > > The ()s are critical. > > $test//child/ancestor-or-self::test[ last() ] > > is very different from > > ($test//child/ancestor-or-self::test)[ last() ] > > The ancestor axis is a reverse axis, but when the xpath expression is > complete, the sequence of nodes are then put in document order > regardless of what order the last axis had. > > In any event, I don't understand what is wrong with simply > $test/ancestor::element()[1] > > Perhaps I don't understand your question (which is simpler than the > Stack Overflow question you linked to). But if you are just looking > for the nearest ancestor element, then it seems that > $test/ancestor::element()[1] should give it to you. >
let $test :=
element div0{
attribute id { 4 },
element div1 {
attribute id { 3 },
element div1 {
attribute id { 2 },
element para {
attribute id { 1 },
element child { }
}
}
}
}I want to get the "smallest" div1 for a given child. this is, the <div1 id=2> element.
As far as I've understood the answers given here, reverse axes are ordered from the context node, so the expression
$test//child/ancestor-or-self::div1[1] will get me what i want, while
$test//child/parent() will give me <para id=1>Needless to say, my data is not particularly well behaved :)
Thanks!
Quoted text · David Rudel · 68 lines
On Wed, Apr 16, 2014 at 3:16 PM, David Rudel <fwqhgads at gmail.com> wrote: > I apologize if I'm being dense, but I don't understand how the nearest > ancestor can be anything other than the parent. Could you please give > an example? > > I just want to make sure I haven't sent you off with the wrong > expression for your intended usage. > > On Wed, Apr 16, 2014 at 8:48 PM, José Tomás Atria <jtatria at gmail.com> > wrote: > > Thank you all for your answers. > > > > I was just tryig to determine if $test/ancestor::element()[1] would be > the > > correct way of getting the nearest ancestor, as I couldn't find whether > axes > > were ordered or not in the xpath specification. > > > > Thanks! > > > > ps: Parent doesn't apply, because the relevant node is not always the > > parent, but the first node with a given name. > > > > > > On Wed, Apr 16, 2014 at 2:45 PM, David Rudel <fwqhgads at gmail.com> wrote: > >> > >> Mr. Atria, > >> You left out a key element from the answer you got from stack overflow. > >> > >> Note that Dimitre's response used a filter expression > >> (path expression) [predicate] > >> > >> not a simple path expression > >> > >> The ()s are critical. > >> > >> $test//child/ancestor-or-self::test[ last() ] > >> > >> is very different from > >> > >> ($test//child/ancestor-or-self::test)[ last() ] > >> > >> The ancestor axis is a reverse axis, but when the xpath expression is > >> complete, the sequence of nodes are then put in document order > >> regardless of what order the last axis had. > >> > >> In any event, I don't understand what is wrong with simply > >> $test/ancestor::element()[1] > >> > >> Perhaps I don't understand your question (which is simpler than the > >> Stack Overflow question you linked to). But if you are just looking > >> for the nearest ancestor element, then it seems that > >> $test/ancestor::element()[1] should give it to you. > > > > > > > > > > -- > > entia non sunt multiplicanda praeter necessitatem > > > > -- > > "A false conclusion, once arrived at and widely accepted is not > dislodged easily, and the less it is understood, the more tenaciously > it is held." - Cantor's Law of Preservation of Ignorance. >
That should have been ancestor::div1[1]. pardon the typo.
Quoted text · José Tomás Atria · 106 lines
On Wed, Apr 16, 2014 at 3:21 PM, José Tomás Atria <jtatria at gmail.com> wrote: > let $test := > element div0{ > attribute id { 4 }, > element div1 { > attribute id { 3 }, > element div1 { > attribute id { 2 }, > element para { > attribute id { 1 }, > element child { } > } > } > } > } > > I want to get the "smallest" div1 for a given child. this is, the <div1 > id=2> element. > > As far as I've understood the answers given here, reverse axes are ordered > from the context node, so the expression > > $test//child/ancestor-or-self::div1[1] will get me what i want, while > $test//child/parent() will give me <para id=1> > > Needless to say, my data is not particularly well behaved :) > > Thanks! > > > On Wed, Apr 16, 2014 at 3:16 PM, David Rudel <fwqhgads at gmail.com> wrote: > >> I apologize if I'm being dense, but I don't understand how the nearest >> ancestor can be anything other than the parent. Could you please give >> an example? >> >> I just want to make sure I haven't sent you off with the wrong >> expression for your intended usage. >> >> On Wed, Apr 16, 2014 at 8:48 PM, José Tomás Atria <jtatria at gmail.com> >> wrote: >> > Thank you all for your answers. >> > >> > I was just tryig to determine if $test/ancestor::element()[1] would be >> the >> > correct way of getting the nearest ancestor, as I couldn't find whether >> axes >> > were ordered or not in the xpath specification. >> > >> > Thanks! >> > >> > ps: Parent doesn't apply, because the relevant node is not always the >> > parent, but the first node with a given name. >> > >> > >> > On Wed, Apr 16, 2014 at 2:45 PM, David Rudel <fwqhgads at gmail.com> >> wrote: >> >> >> >> Mr. Atria, >> >> You left out a key element from the answer you got from stack overflow. >> >> >> >> Note that Dimitre's response used a filter expression >> >> (path expression) [predicate] >> >> >> >> not a simple path expression >> >> >> >> The ()s are critical. >> >> >> >> $test//child/ancestor-or-self::test[ last() ] >> >> >> >> is very different from >> >> >> >> ($test//child/ancestor-or-self::test)[ last() ] >> >> >> >> The ancestor axis is a reverse axis, but when the xpath expression is >> >> complete, the sequence of nodes are then put in document order >> >> regardless of what order the last axis had. >> >> >> >> In any event, I don't understand what is wrong with simply >> >> $test/ancestor::element()[1] >> >> >> >> Perhaps I don't understand your question (which is simpler than the >> >> Stack Overflow question you linked to). But if you are just looking >> >> for the nearest ancestor element, then it seems that >> >> $test/ancestor::element()[1] should give it to you. >> > >> > >> > >> > >> > -- >> > entia non sunt multiplicanda praeter necessitatem >> >> >> >> -- >> >> "A false conclusion, once arrived at and widely accepted is not >> dislodged easily, and the less it is understood, the more tenaciously >> it is held." - Cantor's Law of Preservation of Ignorance. >> > > > > -- > entia non sunt multiplicanda praeter necessitatem >
Just for the sake of completion, the authoritative answer is here<http://www.w3.org/TR/xpath/#predicates> : "The proximity position of a member of a node-set with respect to an axis is defined to be the position of the node in the node-set ordered in document order if the axis is a forward axis and *ordered in reverse document order if the axis is a reverse axis*. The first position is 1."
Quoted text · David Rudel · 6 lines
Ah, okay. I didn't catch that you wanted "the nearest ancestor with a > particular name." In that case then I think you are golden. If there > is a chance that the element itself is a div1 element, then you will > want to use ancestor-or-self instead, but otherwise I think you have > it right. >
Hopefully, I will never have to find the nearest div for a div in this collection, the objective was to locate the smallest container for an infringing non-container (ie, not a div) element. So I think I'm done here.
Thanks!
Quoted text · José Tomás Atria · 3 lines
On Wed, 2014-04-16 at 15:59 -0400, José Tomás Atria wrote: > Just for the sake of completion, the authoritative answer is > here<http://www.w3.org/TR/xpath/#predicates>
Erm, http://www.w3.org/TR/xpath-30/#id-predicate is closer - XPath 1.0 is rather old and is not really the basis for XQuery.
XQuery 1.0 - http://www.w3.org/TR/xquery/#id-predicates
XQuery 3.0 (just released) - http://www.w3.org/TR/xquery-30/#id-predicate
Hope this helps.
Liam
Written for BaseX 7.8. BaseX may have changed since: please check the current documentation.