Reegan
Reegan

Reputation: 183

Grouping same xml elements using XSLT 2

I have an xml document having same element repeated. I need to bring the adjacent div elements inside another element. Below my xml document contains p and div elements. All the div element should be grouped inside the division. If it is single or with adjacent.

   <doc>
    <section>
        <p class="h1">the fisr A</p>
        <p class="txt">one</p>
        <p>tow</p>
        <div>the sec B</div>
        <div>theree</div>
        <div>theree</div>
        <p class="h2">the sec sec B</p>
        <p class="txt">the next text</p>
        <p class="h3">the fisr C</p>
        <p class="txt">four</p>
        <div>five</div>
        <div>the seccond A</div>
        <p class="txt">the seccond txt</p>
        <p class="h2">the second B</p>
    </section>
    <section>
        <p class="txt">six</p>
        <div>seven</div>
        <p class="txt">eight</p>
        <p class="txt">nine</p>
    </section>
</doc>

I need to bring the adjacent div elements in one parent element division. Below is my output.

   <doc>
    <section>
        <p class="h1">the fisr A</p>
        <p class="txt">one</p>
        <p>tow</p>
        <division>
            <div>the sec B</div>
            <div>theree</div>
            <div>theree</div>
        </division>
        <p class="h2">the sec sec B</p>
        <p class="txt">the next text</p>
        <p class="h3">the fisr C</p>
        <p class="txt">four</p>
        <division>
            <div>five</div>
            <div>the seccond A</div>
        </division>
        <p class="txt">the seccond txt</p>
        <p class="h2">the second B</p>
    </section>
    <section>
        <p class="txt">six</p>
        <division>
            <div>seven</div>
        </division>
        <p class="txt">eight</p>
        <p class="txt">nine</p>
    </section>
</doc>

I have tried the below xslt.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes" method="xml"/>
  <xsl:template match="node() | @*">
    <xsl:copy>
      <xsl:apply-templates select="node() | @*"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="body">
    <xsl:copy>
      <xsl:for-each-group select="div" group-adjacent="div">
        <xsl:choose>
          <xsl:when test="current-grouping-key()">
            <division>
              <xsl:apply-templates select="current-group()"/>
            </division>
          </xsl:when>
          <xsl:otherwise>
            <xsl:apply-templates select="current-group()"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:for-each-group>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

Please someone try to help me.

Upvotes: 1

Views: 178

Answers (1)

Tim C
Tim C

Reputation: 70648

You have a template matching body but there are no body elements in your XML. You probably meant section here.

For the grouping, you should really be selecting all elements, not just div, and then for the group-adjacent you need an expression that returns true if it the element is a div, or false otherwise.

Try this XSLT

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes" method="xml"/>

  <xsl:template match="node() | @*">
    <xsl:copy>
      <xsl:apply-templates select="node() | @*"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="section">
    <xsl:copy>
      <xsl:for-each-group select="*" group-adjacent="boolean(self::div)">
        <xsl:choose>
          <xsl:when test="current-grouping-key()">
            <division>
              <xsl:apply-templates select="current-group()"/>
            </division>
          </xsl:when>
          <xsl:otherwise>
            <xsl:apply-templates select="current-group()"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:for-each-group>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

Upvotes: 2

Related Questions