Andrew Truckle
Andrew Truckle

Reputation: 19197

Detect count of for-each

I have this XSL script:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:msa="http://www.publictalksoftware.co.uk/msa">
  <xsl:output method="html" indent="yes" version="4.01"
    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
    doctype-public="//W3C//DTD XHTML 1.0 Transitional//EN"/>
  <xsl:template match="/">
    <html>
      <head>
        <title>Publishers Report</title>
        <link rel="stylesheet" type="text/css" href="Custom Publisher Report.css"/>
      </head>
      <body>
        <xsl:variable name="PubDB" select="document('MSA_PublisherDatabase.XML')"/>
        <table>
          <thead>
            <th class="cellHeading">Name</th>
            <th class="cellHeading">Bible Reading</th>
          </thead>
          <tbody>
            <xsl:apply-templates select="$PubDB/msa:PublisherDatabase/msa:Publishers/msa:Publisher">
              <xsl:sort select="msa:Name" data-type="text" order="ascending"/>
            </xsl:apply-templates>
          </tbody>
        </table>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="msa:Publisher">
    <xsl:variable name="HistoryDB" select="document('AssignHistory.XML')"/>
    <xsl:variable name ="SearchName" select="msa:Name"/>
    <tr>
      <!--The first cell is the name-->
      <td>
        <xsl:value-of select="msa:Name"/>
      </td>
      <!--The second cell is the most recent Bible Reading date-->
      <!--So we need to locate all "Bible Reading" items for the name in question-->
      <!--We sort the entries in date descending order so that the first entry is the most recent-->
      <td>
        <xsl:for-each select="$HistoryDB/AssignmentHistory/*/StudentItems/Item[Description='Bible Reading' and Name=$SearchName]">
          <xsl:sort select="$HistoryDB/AssignmentHistory/*" order="descending" data-type="text"/>
          <!--We only want the first entry-->
          <xsl:if test="position()=1">
            <xsl:value-of select="name(../..)"/>
          </xsl:if>
        </xsl:for-each>
        <!--If no entries were found then it ned to write out "<xsl:text> </xsl:text>" How?-->
      </td>
    </tr>
  </xsl:template>

</xsl:stylesheet>

How do I detect if no items were found in the for-each? In this instance I want to enter an empty space for the cell.

Update

I have still not resolved this issue.

Upvotes: 0

Views: 59

Answers (1)

Aniket V
Aniket V

Reputation: 3247

One option to check whether the loop will get executed is to find the count(). The number of items qualifying in the for-each XPath can be determined as below

<xsl:variable name="numItems" select="count($HistoryDB/AssignmentHistory/*/StudentItems/Item[Description='Bible Reading' and Name=$SearchName])" />

Then using <xsl:choose>,<xsl:when> and <xsl:otherwise>, the if-else logic can be applied.

<xsl:choose>
    <xsl:when test="$numItems &gt; 0"> <!-- check count > 0 -->
    <!-- Perform for loop -->
    </xsl:when>
    <xsl:otherwise>
        <!-- If no entries are found -->
        <xsl:text>&nbsp;</xsl:text>
    </xsl:otherwise>
</xsl:choose>

So the <td> would look like

<td>
    <xsl:variable name="numItems" select="$HistoryDB/AssignmentHistory/*/StudentItems/Item[Description='Bible Reading' and Name=$SearchName]" />
    <xsl:choose>
        <xsl:when test="$numItems &gt; 0"> <!-- check count > 0 -->
            <xsl:for-each select="$HistoryDB/AssignmentHistory/*/StudentItems/Item[Description='Bible Reading' and Name=$SearchName]">
                <xsl:sort select="$HistoryDB/AssignmentHistory/*" order="descending" data-type="text" />
                <!--We only want the first entry -->
                <xsl:if test="position() = 1">
                    <xsl:value-of select="name(../..)" />
                </xsl:if>
            </xsl:for-each>         
        </xsl:when>
        <xsl:otherwise>
            <!-- If no entries are found, add space -->
            <xsl:text>&nbsp;</xsl:text>
        </xsl:otherwise>
    </xsl:choose>
</td>

Upvotes: 1

Related Questions