[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: Finding Only Initial Following Siblings That Meet

Subject: Re: Finding Only Initial Following Siblings That Meet Some Criteria
From: "Eliot Kimber ekimber@xxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Wed, 5 Feb 2020 23:42:07 -0000
Re:  Finding Only Initial Following Siblings That Meet
In my case, I must start with the first instance of the matching phrase
anywhere in the source document (I'm pulling stuff that could be anywhere to a
specific location) and then only want to consider things that immediately
follow that specific <ph> element.

So unless I'm missing a subtlety of your solution, I don't think it would do
quite what I want because it's too inclusive.

Cheers,

E.
--
Eliot Kimber
http://contrext.com


o;?On 2/5/20, 5:07 PM, "Imsieke, Gerrit, le-tex gerrit.imsieke@xxxxxxxxx"
<xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:

    Grouping should liberate you from looking ahead or behind. So instead of
    matching the first <ph outputclass="x">, you'd match <p> (or more
    generally '*[ph[@outputclass]]') and do the group-adjacent grouping for
    the child nodes, like this:

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
       version="3.0">
       <xsl:template match="*[ph[@outputclass]]">
         <xsl:copy>
           <xsl:apply-templates select="@*" mode="#current"/>
           <xsl:for-each-group select="node()"
             group-adjacent="string(self::ph/@outputclass)">
             <xsl:choose>
               <xsl:when test="current-grouping-key()">
                 <xsl:element name="{current-grouping-key()}">
                   <xsl:value-of select="current-group()"
                     separator=""/>
                 </xsl:element>
               </xsl:when>
               <xsl:otherwise>
                 <xsl:apply-templates select="current-group()"
                   mode="#current"/>
               </xsl:otherwise>
             </xsl:choose>
           </xsl:for-each-group>
         </xsl:copy>
       </xsl:template>

       <xsl:mode on-no-match="shallow-copy"/>
    </xsl:stylesheet>

    This is not shorter in terms of lines of code than what you suggested.
    In terms of performance, it could be a bit more efficient than your
    solution, depending on the cost of identifying the first
    ph[@output-class] and its following siblings, compared to the cost of
    identifying a parent of ph[@output-class] and selecting its children.

    But as I wanted to say above, in terms of idiomatic XSLT 2+ purity, I'd
    always prefer a solution that doesn't look along the preceding/following
    axes, even when it is done just once for selecting the for-each-group
    population.

    Gerrit

    On 05.02.2020 23:29, Eliot Kimber ekimber@xxxxxxxxxxxx wrote:
    > In my XML I can have adjacent elements that should be processed as a
unit, where the adjacent elements all have the same value for a given
attribute. Other elements with the same attribute could be following siblings
but separated by other elements or text nodes, i.e.:
    >
    > <p>Text <ph outputclass="x">1</ph><ph outputclass="x">2</ph> more text
<ph outputclass="x">New sequence</ph></p>
    >
    > Where the rendered result should combine the first two <ph> elements but
not the third, i.e.:
    >
    > <p>Text <x>12</x> more text <x>New sequence</x></p>
    >
    > Processing is applied to the first element in the document with the
@outputclass value "x" and then I want to grab any immediately following
siblings with the same @outputclass value and no intervening text or element
nodes.
    >
    > My solution is to use for-each-group like so:
    >
    >      <xsl:variable name="this" as="element()" select="."/>
    >      <xsl:variable name="adjacent-sibs" as="element()+">
    >        <xsl:for-each-group select="($this,
$this/following-sibling::node())"
    >          group-adjacent="string(@outputclass)">
    >          <xsl:if test=". is $this">
    >            <xsl:sequence select="current-group()"/>
    >          </xsl:if>
    >        </xsl:for-each-group>
    >      </xsl:variable>
    >
    > Which works, but I'm thinking there must be a more compact way to do the
same selection, but the formulation is escaping me.
    >
    > Is there a more compact or more efficient way to make this selection of
only immediately-adjacent following siblings?
    >
    > Thanks,
    >
    > E.
    > --
    > Eliot Kimber
    > http://contrext.com

Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.