xsl-list
[Top] [All Lists]

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

2021-02-18 20:24:45
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 dnovatchev(_at_)gmail(_dot_)com 
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:wolfhart(_dot_)totschnig(_at_)mail(_dot_)udp(_dot_)cl>wolfhart(_dot_)totschnig(_at_)mail(_dot_)udp(_dot_)cl <<mailto:xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com>xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com> 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/1167547
or by email: xsl-list-unsub(_at_)lists(_dot_)mulberrytech(_dot_)com
--~--


<Prev in Thread] Current Thread [Next in Thread>