Re: [xsl] with XPath 1.0, select all following sibling elements of name "foo" up to the first non-"foo" element

Subject: Re: [xsl] with XPath 1.0, select all following sibling elements of name "foo" up to the first non-"foo" element
From: "Dimitre Novatchev dnovatchev@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 19 Feb 2021 03:22:34 -0000
On Thu, Feb 18, 2021 at 6:24 PM G. Ken Holman g.ken.holman@xxxxxxxxx <
xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:

> Just eyeballing this, Dmitry, I'm not convinced
> it would work if Wolfhart was sitting at a <foo>
> at the time he made his request, in which case
> the <foo> he was at would incorrectly be included.
>

My reading of the original question is that  " Wolfhart is sitting" at the
first child element of the document (top) element. This is why the template
matches "/*/*[1]".

I believe that most variations of this question do have an efficient
solution using keys.

Cheers,
Dimitre






> Granted the original requirement is
> underspecified in this regard, so perhaps my
> observation is irrelevant. I'm not trying to
> nit-pick but I discounted the use of keys because
> of the arbitrary starting point for evaluation.
>
> Also the use= needs a "[1]" predicate to ensure
> the correct cardinality for generate-id() in the
> general case where there are multiple following siblings that are not
> <foo>.
>
> I'm usually successful with keys when not having
> to deal with the current context.
>
> Wolfhart, am I being too pedantic here?
>
> . . . . . . Ken
>
> At 2021-02-19 01:29 +0000, Dimitre Novatchev dnovatchev@xxxxxxxxx wrote:
> >Here is a short and efficient XSLT 1.0 solution using keys:
> >
> ><xsl:stylesheet version="1.0"
> >xmlns:xsl="<http://www.w3.org/1999/XSL/Transform>
> http://www.w3.org/1999/XSL/Transform";>
> >C <xsl:output omit-xml-declaration="yes" indent="yes"/>
> >C <xsl:key name="kPrecedingFoo" match="foo"
> >use="generate-id(following-sibling::*[not(self::foo)])"/>
> >C
> >C  <xsl:template match="/*/*[1]">
> >C  C  <xsl:copy-of select="key('kPrecedingFoo',
> >generate-id(../*[not(self::foo)][1]))"/>
> >C  </xsl:template>
> ></xsl:stylesheet>
> >
> >Applying this transformation on variations of
> >the following XML document (try uncommenting
> >different subsets of the commented elements) produces always the wanted
> result:
> >
> ><t>
> >C  <!-- <bar/> -->
> >C  <foo ind="1"/>
> >C  <foo ind="2"/>
> >C  <!-- <bar/> -->
> >C  <foo ind="3"/>
> ></t>
> >
> >Cheers,
> >Dimitre
> >
> >On Wed, Feb 17, 2021 at 5:32 PM Wolfhart
> >Totschnig
> ><mailto:wolfhart.totschnig@xxxxxxxxxxx>wolfhart.totschnig@xxxxxxxxxxx
> ><<mailto:xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
> xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
> >wrote:
> >Dear list,
> >
> >I am facing an XPath problem for which I cannot find the solution. I
> >want to select all following sibling elements of name "foo" up to the
> >first non-"foo" element. So, in the following case, the first two <foo>
> >elements should be selected:
> >
> ><foo/>
> ><foo/>
> ><bar/>
> ><foo/>
> >
> >In the following case, all three <foo> elements should be selected:
> >
> ><foo/>
> ><foo/>
> ><foo/>
> >
> >And in the following case, nothing should be selected:
> >
> ><bar/>
> ><foo/>
> ><foo/>
> >
> >I came up with the following non-working approach:
> >
> >C C C C  C C C  C C C  <xsl:choose>
> >C C C C  C C C  C C C  C C C  <xsl:when
> >test="not(following-sibling::*[not(self::foo)])">
> >C C C C  C C C  C C C  C C C  C C
> >C  <xsl:value-of select="following-sibling::*"/>
> >C C C C  C C C  C C C  C C C  </xsl:when>
> >C C C C  C C C  C C C  C C C  <xsl:otherwise>
> >C C C C  C C C  C C C  C C C  C C C  <xsl:value-of
>
>
>select="following-sibling::*[not(self::source)][1]/preceding-sibling::*[self
::source][preceding-sibling::current()]"/>
> >C C C C  C C C  C C C  C C C  </xsl:otherwise>
> >C C C C  C C C  C C C  </xsl:choose>
> >
> >That is, test whether there are non-"foo" following siblings. If there
> >are none, take all following siblings. If there are, go forward to the
> >first non-"foo" sibling, and from there go backwards, taking all the
> >"foo" siblings up to the current node.
> >
> >But this does not work. Apparently, the expression
> >"preceding-sibling::current()" is not a valid construct. So what is the
> >correct way to do what I have in mind (or a simpler solution, if there
> >is one). Please note that this stylesheet needs to be executed by a web
> >browser, and so the solution has to remain within XPath 1.0.
> >
> >Thanks in advance for your help!
> >Wolfhart
> >
> >
> >
> >
> >--
> >Cheers,
> >Dimitre Novatchev
> >---------------------------------------
> >Truly great madness cannot be achieved without significant intelligence.
> >---------------------------------------
> >To invent, you need a good imagination and a pile of junk
> >-------------------------------------
> >Never fight an inanimate object
> >-------------------------------------
> >To avoid situations in which you might make mistakes may be the
> >biggest mistake of all
> >------------------------------------
> >Quality means doing it right when no one is looking.
> >-------------------------------------
> >You've achieved success in your field when you
> >don't know whether what you're doing is work or play
> >-------------------------------------
> >To achieve the impossible dream, try going to sleep.
> >-------------------------------------
> >Facts do not cease to exist because they are ignored.
> >-------------------------------------
> >Typing monkeys will write all Shakespeare's
> >works in 200yrs.Will they write all patents, too? :)
> >-------------------------------------
> >Sanity is madness put to good use.
> >-------------------------------------
> >I finally figured out the only reason to be alive is to enjoy it.
> >C
> ><http://www.mulberrytech.com/xsl/xsl-list>XSL-List info and archive
> ><http://lists.mulberrytech.com/unsub/xsl-list/96802>EasyUnsubscribe
> >(<>by email)
>
>
> --
> Contact info, blog, articles, etc. http://www.CraneSoftwrights.com/s/ |
> Check our site for free XML, XSLT, XSL-FO and UBL developer resources |
> Streaming hands-on XSLT/XPath 2 training class @US$125 (5 hours free) |
> Essays (UBL, XML, etc.) http://www.linkedin.com/today/author/gkholman |
>
>
>

--
Cheers,
Dimitre Novatchev
---------------------------------------
Truly great madness cannot be achieved without significant intelligence.
---------------------------------------
To invent, you need a good imagination and a pile of junk
-------------------------------------
Never fight an inanimate object
-------------------------------------
To avoid situations in which you might make mistakes may be the
biggest mistake of all
------------------------------------
Quality means doing it right when no one is looking.
-------------------------------------
You've achieved success in your field when you don't know whether what
you're doing is work or play
-------------------------------------
To achieve the impossible dream, try going to sleep.
-------------------------------------
Facts do not cease to exist because they are ignored.
-------------------------------------
Typing monkeys will write all Shakespeare's works in 200yrs.Will they write
all patents, too? :)
-------------------------------------
Sanity is madness put to good use.
-------------------------------------
I finally figured out the only reason to be alive is to enjoy it.

Current Thread