Re: [xsl] problem with XPath count()

Subject: Re: [xsl] problem with XPath count()
From: "ajbufort@xxxxxxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Wed, 1 Nov 2023 05:51:40 -0000
Hello Wolfhart,



Your problem intrigued me, so I went about figuring how I would solve this.



Yes, position() can be a tricky animal in terms of context.  The most concise
way Ibve found to get around this so far was with:

count(preceding::text[ends-with(path(), '[1]') or substring(., 1, 1) = 'x'])



This works the way you would expect, getting what you wanted from position()
with just a tad more verbiage.



I cannot answer for performance-impact specifics, but I imagine that the
deeper the node, the more the performance hit.



I leave you to judge the triviality or lack thereof re performance
degradation.



-Tony Bufort



From: Wolfhart Totschnig wolfhart.totschnig@xxxxxxxxxxx
<xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Sent: Tuesday, October 31, 2023 10:20 PM
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: Re: [xsl] problem with XPath count()



Thank you, Syd, for the prompt reply! I think that, thanks to your reply, I
figured out what is going on: The preceding:: axis constructs a node set in
reverse order. Hence, preceding::text[position() = 1] refers to the
immediately preceding <text> element, not to the first <text> element in
document order. That explains the count that I got with my expression.

Thanks again,
Wolfhart



On 11/1/23 01:53, Bauman, Syd s.bauman@xxxxxxxxxxxxxxxx
<mailto:s.bauman@xxxxxxxxxxxxxxxx>  wrote:

I am not sure I could explain precisely what is going on here with position()
if I were fully awake, but there is no chance I can do so now (it is, after
all way past my bedtime), but the apparent miscount boils down to the basic
problem that position() doesnbt mean what we often, at first blush, think
means. (Although often enough it is close enough to what we think that it
works.)



The problem is solved by replacing the call to position() with another count:



count( preceding::text[ count( preceding::text ) eq 0  or  substring( ., 1, 1
) eq 'x'] )



P.S. I presume your input is something like the following, even though the
initial bxb in the content was missing in the post.

<?xml version="1.0" encoding="UTF-8"?>

<outer>

  <text>foo</text>

  <text>xfoo</text>

  <text>foo</text>

  <text>xfoo</text>

</outer>

If it is much more complicated, you might need to be using preceding-sibling::
instead.

  _____

From: Wolfhart Totschnig wolfhart.totschnig@xxxxxxxxxxx
<mailto:wolfhart.totschnig@xxxxxxxxxxx>
<mailto:xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
<xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>

Sent: Wednesday, November 1, 2023 00:40
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx <mailto:xsl-list@xxxxxxxxxxxxxxxxxxxxxx>
<mailto:xsl-list@xxxxxxxxxxxxxxxxxxxxxx> <xsl-list@xxxxxxxxxxxxxxxxxxxxxx>
Subject: [xsl] problem with XPath count()



Dear list,

There is a seemingly simple XPath problem to which I cannot find the
solution. I'm hoping (or, rather, certain) that one of you can help me.

I have a list of <text> elements, like so:

<text>foo</text>
<text>foo</text>
<text>foo</text>
<text>foo</text>

I want to count, for each element, the number of preceding <text>
elements that satisfy one or both of the following two conditions: 1)
the element is the first of the list or 2) its string value begins with
"x". Here is an example, with the expected number of the count after the
element:

<text>foo</text>        0   (no preceding <text> element that satisfies
either of the conditions)
<text>xfoo</text>      1   (one preceding <text> element that satisfies
condition 1)
<text>foo</text>        2   (one preceding <text> element that satisfies
condition 1 + one preceding <text> element that satisfies condition 2)
<text>xfoo</text>      2   (same as with the previous element)

I thought that it would be as simple as the following:

count(preceding::text[position() = 1 or substring(., 1, 1) = 'x'])

But this XPath expression does not give the expected result. It gives
the following:

<text>foo</text>        0
<text>xfoo</text>      1
<text>foo</text>        1
<text>xfoo</text>      2

That is, on the third element it gives "1" whereas I would expect "2".
What am I misunderstanding?

Thanks in advance for your help!
Wolfhart



XSL-List info and archive <http://www.mulberrytech.com/xsl/xsl-list>

EasyUnsubscribe <http://lists.mulberrytech.com/unsub/xsl-list/2652055>  (by
email)



XSL-List info and archive <http://www.mulberrytech.com/xsl/xsl-list>

EasyUnsubscribe <http://lists.mulberrytech.com/unsub/xsl-list/3322603>  (by
email <> )

Current Thread