xml – XSLT iterating over nodes by length

Question:

There is a list of names:

<books>
    <book name="12345symbols"></book>
    <book name="123456789symbols"></book>
    <book name="12345symbols"></book>
    <book name="12345symbols"></book>
    <book name="12345symbols"></book>
    <book name="123456789symbols"></book>
    <book name="123456789symbols"></book>
    <book name="12345symbols"></book>
    <book name="12345symbols"></book>
    <book name="123456789symbols"></book>
    <book name="12345symbols"></book>
</books>

you need to create a table with two columns:

<table>
    <tr>
        <td class="left">12345symbols</td>
        <td class="right"></td>
    </tr>
    <tr>
        <td colspan="2">123456789symbols</td>
    </tr>
    <tr>
        <td class="left">12345symbols</td>
        <td class="right">12345symbols</td>
    </tr>
    <tr>
        <td class="left">12345symbols</td>
        <td class="right"></td>
    </tr>
    <tr>
        <td colspan="2">123456789symbols</td>
    </tr>
    <tr>
        <td colspan="2">123456789symbols</td>
    </tr>
    <tr>
        <td class="left">12345symbols</td>
        <td class="right">12345symbols</td>
    </tr>
    <tr>
        <td colspan="2">123456789symbols</td>
    </tr>
    <tr>
        <td class="left">12345symbols</td>
        <td class="right"></td>
    </tr>   
</table>

Names with less than or equal to 12 characters each go in one cell, two cells per line. If the name contains more than 12 characters, then we stretch the cell by two and do everything in one line.

For the third day I have been struggling with this problem, maybe someone can suggest something.
If something is not clear I will be glad to explain.

Answer:

If there are only 3 options, then the easiest way is to insert if-s

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
  <!-- xml -> html -->
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="books">
    <table>
      <xsl:apply-templates select="book[1]" />
    </table>
  </xsl:template>

  <xsl:template match="book">
    <xsl:choose>
      <xsl:when test="string-length(@name) &lt;= 12">
        <xsl:choose>
          <xsl:when test="string-length(following-sibling::book[1]/@name) &lt;= 12">

            <!-- два значения -->
            <tr>
              <td class="left">
                <xsl:value-of select="@name"/>
              </td>
              <td class="right">
                <xsl:value-of select="following-sibling::book[1]/@name"/>
              </td>
            </tr>
            <xsl:apply-templates select="following-sibling::book[2]" />

          </xsl:when>
          <xsl:otherwise>

            <!-- одно + пусто -->
            <tr>
              <td class="left">
                <xsl:value-of select="@name"/>
              </td>
              <td class="right"></td>
            </tr>
            <xsl:apply-templates select="following-sibling::book[1]" />

          </xsl:otherwise>
        </xsl:choose>
      </xsl:when>
      <xsl:otherwise>

        <!-- одно на две ячейки -->
        <tr>
          <td colspan="2">
            <xsl:value-of select="@name"/>
          </td>
        </tr>
        <xsl:apply-templates select="following-sibling::book[1]" />

      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

If there is more, then take out apply-templates for choose and add separate conditions for skipping nodes.

Scroll to Top