Hi,
I was having issues manipulating text nodes. I found a way around my issue, but I'm still thinking that my 1st syntax to get the first text node of a sequence should have worked.
My question is given all the example below, is #2 returning the expected value? I was expecting it would work like the syntax for elements in #3 and return the same result as #4 and #5
let $node := <p><b>allo!</b> Il pleut des clous.</p> let $node2 := <ul><li>1</li><li>2</li></ul> let $text-node := $node//text() return <ul> <li>{$text-node}</li> <li>{$node//text()[1]}</li> <li>{$node2//li[1]}</li> <li>{($node//text())[1]}</li> <li>{$text-node[1]}</li> <li>{$node//text()[1][1]}</li> <li>{for $i in $node//text() return <span>{$i}</span>}</li> <li>{for $i in $text-node return <span>{$i}</span>}</li> </ul>
<ul> <li>allo! Il pleut des clous.</li> <li>allo! Il pleut des clous.</li> <li> <li>1</li> </li> <li>allo!</li> <li>allo!</li> <li>allo! Il pleut des clous.</li> <li> <span>allo!</span> <span> Il pleut des clous.</span> </li> <li> <span>allo!</span> <span> Il pleut des clous.</span> </li> </ul>
This is a matter of precedence.
<li>{ $node//text()[1] }</li>
Has the meaning of "return all text nodes, that are in first position of their encapsulating element". Consider the intermediate result after partial evaluation to be something like
("allo!"[1], "Il pleut des clous."[1])
Applying parenthesis as you proposed in #4 resolves the issue:
<li>{ ($node//text())[1] }</li>
resulting in
("allo!", "Il pleut des clous.")[1]
instead.
This is not an issue in $5, as all text nodes are stored in a sequence (which is flattened), and you return the first result of the flattened sequence.
And a little addition:
$node//text()[1]
…is an abbreviation for…
$node/descendant-or-self::node()/child::text()[1]
However, you are probably looking for:
$node/descendant::text()[1]
It’s completely fine to use parentheseses, as in this case, your query will exactly be rewritten as shown above.
On Wed, Mar 2, 2016 at 8:28 PM, Jens Erat jens.erat@uni-konstanz.de wrote:
This is a matter of precedence.
<li>{ $node//text()[1] }</li>
Has the meaning of "return all text nodes, that are in first position of their encapsulating element". Consider the intermediate result after partial evaluation to be something like
("allo!"[1], "Il pleut des clous."[1])
Applying parenthesis as you proposed in #4 resolves the issue:
<li>{ ($node//text())[1] }</li>
resulting in
("allo!", "Il pleut des clous.")[1]
instead.
This is not an issue in $5, as all text nodes are stored in a sequence (which is flattened), and you return the first result of the flattened sequence.
-- Jens Erat Universität Konstanz Kommunikations-, Infomations-, Medienzentrum (KIM) Abteilung Basisdienste D-78457 Konstanz Mail: jens.erat@uni-konstanz.de
Thanks for taking the time to look at this so quickly. I'm still unsure how #2 isn't a sequence if #3 is.
Anyhow, if it all works as intended, I'm fine with using a variable or () to make sure the returned nodes are cast into a sequence.
I'm just a bit surprised that text nodes and element nodes are returned differently.
Regards,
France
On Wed, Mar 2, 2016 at 3:43 PM, Christian Grün christian.gruen@gmail.com wrote:
And a little addition:
$node//text()[1]
…is an abbreviation for…
$node/descendant-or-self::node()/child::text()[1]
However, you are probably looking for:
$node/descendant::text()[1]
It’s completely fine to use parentheseses, as in this case, your query will exactly be rewritten as shown above.
On Wed, Mar 2, 2016 at 8:28 PM, Jens Erat jens.erat@uni-konstanz.de wrote:
This is a matter of precedence.
<li>{ $node//text()[1] }</li>
Has the meaning of "return all text nodes, that are in first position of their encapsulating element". Consider the intermediate result after partial evaluation to be something like
("allo!"[1], "Il pleut des clous."[1])
Applying parenthesis as you proposed in #4 resolves the issue:
<li>{ ($node//text())[1] }</li>
resulting in
("allo!", "Il pleut des clous.")[1]
instead.
This is not an issue in $5, as all text nodes are stored in a sequence (which is flattened), and you return the first result of the flattened sequence.
-- Jens Erat Universität Konstanz Kommunikations-, Infomations-, Medienzentrum (KIM) Abteilung Basisdienste D-78457 Konstanz Mail: jens.erat@uni-konstanz.de
Thanks for taking the time to look at this so quickly. I'm still unsure how #2 isn't a sequence if #3 is.
Do you mean the result of #2 and #3? All results (values) of XQuery expressions are "sequences" (with 0 or more items), so the result of #2 is a sequence as well.
I'm just a bit surprised that text nodes and element nodes are returned differently.
This is actually not about text or element nodes, it’s about descendant vs. child axis:
The following two queries are identical:
$node//text()[1] $node/descendant-or-self::node()/child::text()[1]
If evaluated, you will get the first child text node of all nodes of $node. In contrast..
($node//text())[1] $node/descendant::text()[1]
..will give you the first descendant text node of $node. Do you see the difference?
Hope this helps, Christian
Doh! Got it!
Thanks!
On Fri, Mar 4, 2016 at 4:30 AM, Christian Grün christian.gruen@gmail.com wrote:
Thanks for taking the time to look at this so quickly. I'm still unsure
how
#2 isn't a sequence if #3 is.
Do you mean the result of #2 and #3? All results (values) of XQuery expressions are "sequences" (with 0 or more items), so the result of #2 is a sequence as well.
I'm just a bit surprised that text nodes and element nodes are returned differently.
This is actually not about text or element nodes, it’s about descendant vs. child axis:
The following two queries are identical:
$node//text()[1] $node/descendant-or-self::node()/child::text()[1]
If evaluated, you will get the first child text node of all nodes of $node. In contrast..
($node//text())[1] $node/descendant::text()[1]
..will give you the first descendant text node of $node. Do you see the difference?
Hope this helps, Christian
basex-talk@mailman.uni-konstanz.de