Re: [xsl] Wrapping nodes outside tables into paragraphs

Subject: Re: [xsl] Wrapping nodes outside tables into paragraphs
From: "Martynas Jusevičius martynas@xxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Thu, 22 May 2014 20:23:51 -0000
Thanks a lot Graydon! And sorry, yes I'm using XSLT 2.0.

I suspected xsl:for-each-group can be used to solved this. I just
never seem to get the group- criteria right, or maybe I didn't realize
the grouping key could be used so flexibly.

My template now looks like this and seems to work:

<xsl:template match="tei:note[tei:table or tei:figure]" mode="xhtml">
  <xsl:for-each-group select="node()" group-adjacent="if
(self::tei:table or self::tei:figure) then 'block' else 'inline'">
    <xsl:choose>
      <xsl:when test="current-grouping-key() eq 'block'">
        <xsl:apply-templates select="current-group()" mode="#current"/>
      </xsl:when>
      <xsl:when test="current-grouping-key() eq 'inline'">
        <xhtml:p>
          <xsl:apply-templates select="current-group()" mode="#current"/>
       </xhtml:p>
      </xsl:when>
      <xsl:otherwise>
        <xsl:message terminate="yes">Grouping error</xsl:message>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:for-each-group>
</xsl:template>


Martynas

On Thu, May 22, 2014 at 9:55 PM, Graydon graydon@xxxxxxxxx
<xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:
> On Thu, May 22, 2014 at 07:19:02PM -0000, Martynas JuseviD
ius
martynas@xxxxxxxxxxxx scripsit:
>> I have TEI markup where nodes (text nodes and some elements) are
>> interspersed with table and figure elements, like this:
>>
>>   <note>
>>     text text <ref type="whatever">text</ref>
>>     <table>...</table>
>>     text text
>>     <figure>...</figure>
>>     text text
>>     <table>...</table>
>>     <table>...</table>
>>     text text
>>   </note>
>>
>> There can be nodes before, between, and after tables.
>>
>> I want to produce a corresponding XHTML while also wrapping all the
>> nodes between tables into <p>, so they're on the same block-level (for
>> simplicity, lets say <xhtml:img> is also block-level):
>
> This is a classic use case for XSLT 2.0's for-each-group instruction.
>
> Are you using 2.0?
>
> If so, an approach like
>
> <xsl:for-each-group select="note/node()" group-adjacent="if
> (self::table) then 'table' else 'interstitial'">
>
>     <xsl:choose>
>         <xsl:when test="current-grouping-key() eq 'table'">
>             <!-- do what you do to tables -->
>         </xsl:when>
>         <xsl:when test="current-grouping-key() eq 'interstial'>
>             <!-- wrap everything else -->
>         <xsl:otherwise>
>             <!-- you should never get here; die loudly -->
>         </xsl:otherwise>
>     </xsl:choose>
>
> </xsl:for-each-group>
>
> ought to work.  (The pattern also extends.)
>
> If you have to individual wrap adjacent tables you may want a different
> grouping attribute, and you might want to select
> note/node()[normalize-space()] instead, to avoid white-space only text
> nodes.
>
> -- Graydon

Current Thread