Search code examples
xsltxslt-grouping

Grouping in XSLT


Have the source XML:

<root>
      <element Key="card1_id">123</element>
      <element Key="card1_balance">500</element>
      <element Key="card2_id">456</element>
      <element Key="card2_balance">800</element>
      .............................................
      <element Key="card(n)_id">999</element>
      <element Key="card(n)_balance">8000</element>
</root>

Where n - the number of cards

With XSLT i need to get a HTML:

<b>Card 1:</b>   
  ID: 123 <br/> 
  Balance: 500 <br/>  

<b>Card 2:</b>   
  ID: 456<br/>  
  Balance: 800<br/> 
 ..................
<b>Card n:</b>   
  ID: 999<br/>  
  Balance: 8000<br/>

How to organize such grouping?


Solution

  • Use Muechian grouping with XSLT 1.0:

    <xsl:stylesheet
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      version="1.0">
    
      <xsl:key name="k1" match="element" use="translate(@Key, translate(@Key, '0123456789', ''), '')"/>
    
      <xsl:output method="html" indent="yes"/>
    
      <xsl:template match="root">
        <div>
          <xsl:apply-templates select="element[generate-id() = generate-id(key('k1', translate(@Key, translate(@Key, '0123456789', ''), ''))[1])]" mode="group"/>
        </div>
      </xsl:template>
    
      <xsl:template match="element" mode="group">
        <b>Card <xsl:value-of select="translate(@Key, translate(@Key, '0123456789', ''), '')"/>:</b>
        <xsl:apply-templates select="key('k1', translate(@Key, translate(@Key, '0123456789', ''), ''))"/>
      </xsl:template>
    
      <xsl:template match="element">
        <xsl:value-of select="concat(substring-after(., '_'), ': ', .)"/>
        <br/>
      </xsl:template>
    
    </xsl:stylesheet>
    

    With that stylesheet Saxon 6.5.5 transforms

    <root>
          <element Key="card1_id">123</element>
          <element Key="card1_balance">500</element>
          <element Key="card2_id">456</element>
          <element Key="card2_balance">800</element>
          .............................................
          <element Key="card3_id">999</element>
          <element Key="card3_balance">8000</element>
    </root>
    

    into

    <div><b>Card 1:</b>: 123<br>: 500<br><b>Card 2:</b>: 456<br>: 800<br><b>Card 3:</b>: 999<br>: 8000<br></div>