Search code examples
xsltxslt-2.0xslt-grouping

XSLT Grouping's : Add parent to set of elements in child elements


Using for-each-group I'm trying to add parent node by the class value of each para element. I tried to apply the grouping but the result is not good, I'm not getting the desired output. I'm confused about using the grouping in this case. Is there any better approach in this case for adding the parent node?

Current XML:

<?xml version="1.0" encoding="utf-8" ?>
<section>
  <h1>Some heading</h1>
  <section>
   <p>normal paragaraph</p>
   <p class="list">list 1</p>
   <p class="list">list 1</p>
  
    <p>normal paragaraph</p>
   <p class="list">list 2</p>
   <p class="list">list 2</p>
  </section>
    <section> ...  </section>
</section>

XSLT used:

   <xsl:template match="section">
      <xsl:for-each-group select="node()" group-by="if (@class='list') then 'list' else 'nolist'">
        <xsl:for-each select="current-grouping-key()">
            <xsl:choose>
              <xsl:when test="current-grouping-key() = 'list'">
              <list>
                  <xsl:apply-templates select="current-group()" />
              </list>                
              </xsl:when>
              <xsl:otherwise>
                  <xsl:apply-templates select="current-group()" />
              </xsl:otherwise>
            </xsl:choose>

        </xsl:for-each>
      </xsl:for-each-group>
  </xsl:template>

Current Output:


<h1>Some heading</h1>
<p>normal paragaraph</p>
<p>normal paragaraph</p>
<list>
   <p class="list">list 1</p>
   <p class="list">list 1</p>
   <p class="list">list 2</p>
   <p class="list">list 2</p>
</list>

<p>normal paragaraph</p>
....

Expected Output:

<section>
  <h1>Some heading</h1>
  <section>
   <p>normal paragaraph</p>
   <list>
      <p class="list">list 1</p>
      <p class="list">list 1</p>
   </list>
    <p>normal paragaraph</p>
   <list>
      <p class="list">list 2</p>
      <p class="list">list 2</p>
   </list>
</section>
<section>...</section>
</section>


Solution

  • <xsl:template match="section">
      <section>
        <h1>Some Heading</h1>
        <section>
            <xsl:for-each-group select="section/p" group-by=".">
                <xsl:choose>
                  <xsl:when test="current-grouping-key() != 'normal paragaraph'">
                    <p>normal paragaraph</p>
                    <list>
                      <xsl:for-each select="current-group()">
                          <p class="list"><xsl:value-of select="current-grouping-key()"/></p>
                      </xsl:for-each>
                    </list>
                  </xsl:when>
                </xsl:choose>
            </xsl:for-each-group>
          </section>
      </section>
    </xsl:template>