Subject: Re: [xsl] Finding Only Initial Following Siblings That Meet Some Criteria From: "Michael Kay mike@xxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> Date: Wed, 5 Feb 2020 23:14:51 -0000 |
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@xxxxxxxxxxxx <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> 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 |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Finding Only Initial Foll, Imsieke, Gerrit, le- | Thread | Re: [xsl] Finding Only Initial Foll, Eliot Kimber ekimber |
Re: [xsl] Finding Only Initial Foll, Imsieke, Gerrit, le- | Date | Re: [xsl] Finding Only Initial Foll, Imsieke, Gerrit, le- |
Month |