Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XSL to show highest number of copies in catalog.xml file

Tags:

xslt

In this the catalog.xml file. I have two books who have the same inventory (i.e. 20). I want to write an XSL file that will display the highest number of copies of a book in a catalog. If there are two or more books of the same inventory then they have to be displayed.

<catalog>
  <Book>
    <sku>12345</sku>
    <title>Beauty Secrets</title>
    <condition>New</condition>
    <current_inventory>20</current_inventory>
    <price>99.99</price>
  </Book>
  <Book>
    <sku>54321</sku>
    <title>Picturescapes</title>
    <current_inventory>20</current_inventory>
    <condition>New</condition>
    <price>50.00</price>
  </Book> 
  <Book>
    <sku>33333</sku>
    <title>Tourist Perspectives</title>
    <condition>New</condition>
    <current_inventory>0</current_inventory>
    <price>75.00</price>
  </Book>
  <Book>
    <sku>10001</sku>
    <title>Fire in the Sky</title>
    <condition>Used</condition>
    <current_inventory>0</current_inventory>
    <price>10.00</price>
  </Book>
</catalog>

Below is my catalog3.xsl file which is able to display only one out of the two books:

<xsl:stylesheet 
  version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
  <xsl:variable name="max"/>

  <xsl:template match="/">
    <html>
      <body>
        <h2>Titles of Books for which Most Copies are Available</h2>
        <table border="2">
          <tr bgcolor="#9acd32">
            <th>Title</th>
            <th>No of Copies</th>
          </tr>
          <xsl:apply-templates/>
        </table>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="catalog">
    <xsl:for-each select="Book">
      <xsl:sort select="current_inventory" data-type="number" order="descending"/>
      <tr>
        <xsl:if test="position()= 1">
          <p><xsl:value-of select="$max = "/></p>
          <td><xsl:value-of select="title"/></td>
          <td><xsl:value-of select="current_inventory"/></td>
        </xsl:if>
      </tr>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

Could anybody correct me to achieve my goal of displaying all the copies having the same maximum inventory in the catalog. Thanks.

like image 646
Sanjay Rao Avatar asked Oct 15 '22 08:10

Sanjay Rao


1 Answers

The maximum current_inventory can be calculated in the following manner:

<xsl:variable name="max">
  <xsl:for-each select="/catalog/Book/current_inventory">
    <xsl:sort data-type="number" order="descending"/>
    <xsl:if test="position()=1"><xsl:value-of select="."/></xsl:if>
  </xsl:for-each>
</xsl:variable>

Adjusting the criteria for the xsl:if to compare the current_inventory of the current node in the for-each to the $max variable achieves the desired result.

You were evaluating position()=1 inside of the for-each, which will only be true for the first item in the sorted collection.

I set it to look for current_inventory that is equal to the $max:

<xsl:if test="current_inventory = $max">

Applying these changes to your stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<!--Determine the maximum current_inventory -->
<xsl:variable name="max">
    <xsl:for-each select="/catalog/Book/current_inventory">
        <xsl:sort data-type="number" order="descending"/>
        <xsl:if test="position()=1"><xsl:value-of select="."/></xsl:if>
    </xsl:for-each>
</xsl:variable>

<xsl:template match="/">
    <html>
        <body>
            <h2>Titles of Books for which Most Copies are Available</h2>
            <table border="2">
                <tr bgcolor="#9acd32">
                    <th>Title</th>
                    <th>No of Copies</th>
                </tr>
                <xsl:apply-templates/>
            </table>
        </body>
    </html>
</xsl:template>
<xsl:template match="catalog">
    <xsl:for-each select="Book">
        <xsl:sort select="current_inventory" data-type="number" order="descending"/>

        <xsl:if test="current_inventory = $max">
                            <tr>
                <td>
                    <xsl:value-of select="title"/>
                </td>
                <td>
                    <xsl:value-of select="current_inventory"/>
                </td>
                            </tr>
        </xsl:if>

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

like image 197
Mads Hansen Avatar answered Oct 18 '22 10:10

Mads Hansen