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 -- entia non sunt multiplicanda praeter necessitatem
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." On Wed, Apr 16, 2014 at 8:45 PM, David Rudel <fwqhgads@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.
-- "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.
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@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
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@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@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.
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@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@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@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
That should have been ancestor::div1[1]. pardon the typo. On Wed, Apr 16, 2014 at 3:21 PM, José Tomás Atria <jtatria@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@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@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@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
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. On Wed, Apr 16, 2014 at 9:22 PM, José Tomás Atria <jtatria@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@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@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@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@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
-- "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.
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." 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! -- entia non sunt multiplicanda praeter necessitatem
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 -- Liam Quin - XML Activity Lead, W3C, http://www.w3.org/People/Quin/ Pictures from old books: http://fromoldbooks.org/ Ankh: irc.sorcery.net irc.gnome.org freenode/#xml
participants (3)
-
David Rudel -
José Tomás Atria -
Liam R E Quin