Flag
Flag

Reputation: 577

XSLT 2.0 - Merging adjacent OL elements

I'm trying to merge adjacent <ol>|<ul> elements that appear inside <li> elements without success.

Therefore turning:

 <ol>
 <li>Text node <p>Child node</p>
  <ol>
   <li>1</li>
  </ol>  
  <ol>
   <li>2</li>
   <li>3</li>
   <li>4</li>
  </ol>
  <p>Some text</p>
  <ol>
   <li>1</li>
  </ol>
 </li>
</ol>

Into

<ol>
 <li>Text node <p>Child node</p>
  <ol>
   <li>1</li>
   <li>2</li>
   <li>3</li>
   <li>4</li>
  </ol>
  <p>Some text</p>
  <ol>
   <li>1</li>
  </ol>
 </li>
</ol>

Right now, I've come up with this:

  <xsl:template match="li[ol]" priority="5">   
    <xsl:copy copy-namespaces="no">          
      <ol>
        <xsl:for-each-group select="node()" group-adjacent="boolean(self::ol)">
          <xsl:choose>            
            <xsl:when test="current-grouping-key() and current-group()[self::*]">
              <xsl:apply-templates select="current-group()/node()"/>            
            </xsl:when>
            <xsl:otherwise>              
              <xsl:apply-templates select="current-group()"/>              
            </xsl:otherwise>
          </xsl:choose>
        </xsl:for-each-group>   
      </ol>
    </xsl:copy>
  </xsl:template>

Which gives me:

  <ol>
    <li>
      <ol>Text node <p>Child node</p>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <p>Some text</p>
        <li>1</li>
      </ol>
    </li>
  </ol>

So I'm struggling to not move the parent <li>'s text into the merged <ol>, how do I fix this?

Upvotes: 0

Views: 127

Answers (1)

Martin Honnen
Martin Honnen

Reputation: 167716

Using

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">

    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

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

    <xsl:template match="li[ol]">
        <xsl:copy>
            <xsl:for-each-group select="node()"
                group-adjacent="boolean(self::ol | self::text()[not(normalize-space())])">
                <xsl:choose>
                    <xsl:when test="current-grouping-key()">
                        <ol>
                            <xsl:copy-of select="current-group()/node()"/>
                        </ol>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:apply-templates select="current-group()"/>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each-group>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

you can transform

<ol>
    <li>Text node <p>Child node</p>
        <ol>
            <li>1</li>
        </ol>  
        <ol>
            <li>2</li>
            <li>3</li>
            <li>4</li>
        </ol>
        <p>Some text</p>
        <ol>
            <li>1</li>
        </ol>
    </li>
</ol>

into

<ol>
   <li>Text node <p>Child node</p>
      <ol>
         <li>1</li>
         <li>2</li>
         <li>3</li>
         <li>4</li>
      </ol>
      <p>Some text</p>
      <ol>
         <li>1</li>
      </ol>
   </li>
</ol>

Upvotes: 1

Related Questions