|
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 |