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

"G. Ken Holman [email protected]" <[email protected]> Fri, 19 Feb 2021 02:24:44 -0000
Newsgroups gmane.text.xml.xsl.general.mulberrytech
Message-ID <[email protected]>
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.

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 [email protected] 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">
>Â <xsl:output omit-xml-declaration="yes" indent="yes"/>
>Â <xsl:key name="kPrecedingFoo" match="foo" 
>use="generate-id(following-sibling::*[not(self::foo)])"/>
>Â
>Â  <xsl:template match="/*/*[1]">
>Â  Â  <xsl:copy-of select="key('kPrecedingFoo', 
>generate-id(../*[not(self::foo)][1]))"/>
>Â  </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>
>Â  <!-- <bar/> -->
>Â  <foo ind="1"/>
>Â  <foo ind="2"/>
>Â  <!-- <bar/> -->
>Â  <foo ind="3"/>
></t>
>
>Cheers,
>Dimitre
>
>On Wed, Feb 17, 2021 at 5:32 PM Wolfhart 
>Totschnig 
><mailto:[email protected]>[email protected] 
><<mailto:[email protected]>[email protected]> 
>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:
>
>Â Â Â Â  Â Â Â  Â Â Â  <xsl:choose>
>Â Â Â Â  Â Â Â  Â Â Â  Â Â Â  <xsl:when 
>test="not(following-sibling::*[not(self::foo)])">
>Â Â Â Â  Â Â Â  Â Â Â  Â Â Â  Â Â 
>Â  <xsl:value-of select="following-sibling::*"/>
>Â Â Â Â  Â Â Â  Â Â Â  Â Â Â  </xsl:when>
>Â Â Â Â  Â Â Â  Â Â Â  Â Â Â  <xsl:otherwise>
>Â Â Â Â  Â Â Â  Â Â Â  Â Â Â  Â Â Â  <xsl:value-of
>select="following-sibling::*[not(self::source)][1]/preceding-sibling::*[self::source][preceding-sibling::current()]"/>
>Â Â Â Â  Â Â Â  Â Â Â  Â Â Â  </xsl:otherwise>
>Â Â Â Â  Â Â Â  Â Â Â  </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.
>Â
><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 |
--~----------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
EasyUnsubscribe: http://lists.mulberrytech.com/unsub/xsl-list/3329386
or by email: [email protected]
--~--