Subject: Re: [xsl] XSLT2: Grouping mixed content between opening and closing marker elements From: "Keith Burt keithburt66@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> Date: Sun, 16 Aug 2020 19:50:00 -0000 |
Martin, thank you for your response. I am not familiar with V3 but will challenge myself to understand your code. Regards. -- Keith On Saturday, August 15, 2020, Martin Honnen martin.honnen@xxxxxx < xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote: > Am 15.08.2020 um 13:56 schrieb Martin Honnen martin.honnen@xxxxxx: > >> Am 15.08.2020 um 12:19 schrieb Keith Burt keithburt66@xxxxxxxxx: >> >> In my simplified example, I have self closing 'e' elements that have a >>> tag attribute that denotes the start and end points of where style (in >>> this case bold and italic) should be applied. >>> I want to group the content within the start and end markers, and create >>> a wrapper element based on the tag attribute. >>> >> >> That sounds like a grouping task for a nested >> for-each-group group-starting-with="e" >> for-each-group group-ending-with="e" >> with some more precise conditions. >> >> Or in XSLT 3 you could think of xsl:iterate or fold-left. >> > > Looking at it closer it seems you could use the for-each-group within an > iterate, to handle the nesting of e.g. <e tag="b">...<e tag="i">...<e > tag="/i">...<e tag="/i>". > > > <?xml version="1.0" encoding="utf-8"?> > <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > version="3.0" > xmlns:xs="http://www.w3.org/2001/XMLSchema" > exclude-result-prefixes="#all" > xmlns:mf="http://example.com/mf" > expand-text="yes"> > > <xsl:function name="mf:wrap" as="node()*"> > <xsl:param name="nodes" as="node()*"/> > <xsl:param name="tag" as="xs:string"/> > <xsl:for-each-group select="$nodes" group-starting-with="e[@tag = > $tag]"> > <xsl:choose> > <xsl:when test="not(self::e[@tag = $tag])"> > <xsl:apply-templates select="current-group()"/> > </xsl:when> > <xsl:otherwise> > <xsl:for-each-group select="tail(current-group())" > group-ending-with="e[@tag = '/' || $tag]"> > <xsl:choose> > <xsl:when test="current-group()[last()][self::e][@tag = > '/' || $tag]"> > <xsl:element name="{$tag}"> > <xsl:apply-templates > select="current-group()[position() lt last()]"/> > </xsl:element> > </xsl:when> > <xsl:otherwise> > <xsl:apply-templates select="current-group()"/> > </xsl:otherwise> > </xsl:choose> > </xsl:for-each-group> > </xsl:otherwise> > </xsl:choose> > </xsl:for-each-group> > </xsl:function> > > <xsl:function name="mf:wrap" as="node()*"> > <xsl:param name="nodes" as="node()*"/> > <xsl:iterate > select="distinct-values($nodes[self::e/@tag[not(starts-with(., > '/'))]]/@tag)"> > <xsl:param name="nodes" as="node()*" select="$nodes"/> > <xsl:on-completion> > <xsl:sequence select="$nodes"/> > </xsl:on-completion> > <xsl:next-iteration> > <xsl:with-param name="nodes" select="mf:wrap($nodes, .)"/> > </xsl:next-iteration> > </xsl:iterate> > </xsl:function> > > <xsl:mode on-no-match="shallow-copy"/> > > <xsl:template match="*[e[@tag]]"> > <xsl:copy> > <xsl:apply-templates select="@*"/> > <xsl:sequence select="mf:wrap(node())"/> > </xsl:copy> > </xsl:template> > > </xsl:stylesheet> > > > That's XSLT 3 obviously, so I am not sure whether it helps as your > original question only mentioned XSLT 2. However, since 2017, we have > XSLT 3 and Saxon 9.8 and later or Altova XML 2017 R3 and later should > support XSLT 3.
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] XSLT2: Grouping mixed con, Martin Honnen martin | Thread | [xsl] Regex in @select Escaping Puz, Eliot Kimber ekimber |
Re: [xsl] problem with transforming, Wolfhart Totschnig w | Date | [xsl] Re: Upward projection?, Imsieke, Gerrit, le- |
Month |