xsl-list
[Top] [All Lists]

Re: [xsl] Finding Only Initial Following Siblings That Meet Some Criteria

2020-02-05 17:43:05
I like the use of xsl:iterate here--it seems to be a clean match for the 
behavior.

Cheers,

E.

--
Eliot Kimber
http://contrext.com
 

On 2/5/20, 5:14 PM, "Michael Kay mike(_at_)saxonica(_dot_)com" 
<xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com> wrote:

    I think the ability to select items from a sequence until some condition is 
true is something that's always been far too difficult.
    In my paper for XML Prague next week I propose:
    
    fn:items-before(
      ($this,$this/following-sibling::node()), 
      function($n){$n/@outputclass != $this/@outputclass})
    
    as a function that selects everything in a sequence up to, and excluding, 
the first item where some condition is true.
    
    You could consider implementing this function using xsl:iterate:
    
    <xsl:function name="f:items-before" as="item()*">
      <xsl:param name="in" as="item()*"/>
      <xsl:param name="predicate" as="function(item()) as xs:boolean"/>
      <xsl:iterate select="$in">
        <xsl:choose>
          <xsl:when test="$predicate(.)">
             <xsl:break/>
           </xsl:when>
          <xsl:otherwise>
             <xsl:sequence select="."/>
          </xsl:otherwise>
       </xsl:choose>
     </xsl:iterate>
    </xsl:function>
    
    And I've always thought a following-sibling-or-self axis would be handy, 
though the name is horrendous.
    
    Michael Kay
    Saxonica
    
    
    
    
    On 5 Feb 2020, at 22:29, Eliot Kimber ekimber(_at_)contrext(_dot_)com 
<xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com> 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
    
    
    
    
    
    
    
    
    
    XSL-List info and archive 
<http://www.mulberrytech.com/xsl/xsl-list>EasyUnsubscribe 
<http://lists.mulberrytech.com/unsub/xsl-list/1278982>
    (by email <>)
    
    
    
--~----------------------------------------------------------------
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>