1

I need to display the maximum quantity of book in each library in Indonesia and the library using XSL 1.0. There can be 2 books with the same quantity which are the maximum. How do I display both of them. I am using xsl apply-template and xsl value-select. I'm new to XML and XSL. Appreciate all help.

XML

</libraries>
  <library>
    <id>1</id>
    <name>DabZ</name>
    <address>
      <street>Green</street>
      <city>Patemon</city>
      <country>Indonesia</country>
    </address>
    <books>
      <book>
        <id>2</id>
        <im_id>00851287</im_id>
        <name>Alice in wonderland</name>
        <price>80.22</price>
        <qty>10</qty>
      </book>
      <book>
        <id>11</id>
        <im_id>50241141</im_id>
        <name>Master your mind</name>
        <price>75.03</price>
        <qty>84</qty>
      </book>
    </books>
  </library>
  <library>
    <id>2</id>
    <name>Skippad</name>
    <address>
      <street>Harper</street>
      <city>Makale</city>
      <country>Indonesia</country>
    </address>
    <books>
      <book>
        <id>2</id>
        <im_id>00851287</im_id>
        <name>Alice in Wonderland</name>
        <price>80.22</price>
        <qty>4</qty>
      </book>
      <book>
        <id>15</id>
        <im_id>67510150</im_id>
        <name>Flu Relief</name>
        <price>92.26</price>
        <qty>361</qty>
      </book>
      <book>
        <id>20</id>
        <im_id>67510140</im_id>
        <name>Stress Relief</name>
        <price>50.00</price>
        <qty>361</qty>
      </book>
    </books>
  </library>
</libraries>

Desired output from xsl

Library 1, Dabz

Largest quantity:

Master your mind, 84

Library 2, Skippad

Largest quantity:

Flu Relief: 361

Stress Relief: 361

My attempted xsl

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:template match="/">
    <html>
      <body>
          <ul>
            <xsl:apply-templates select="//library[address/country='Indonesia']"/> 
          </ul>
      </body>  
    </html>
  </xsl:template>
    
  <xsl:template match="library">
    <h1>Library <xsl:value-of select="id"/>,  <xsl:value-of select="name"/> </h1>
    <xsl:apply-templates select="books"/>           
  </xsl:template>

  <xsl:template match="book">
    <xsl:sort select="qty" data-type="number" order="descending"/>   
    <xsl:sort select="qty"/>
    <xsl:if test="position() = 1"><xsl:value-of select="."/></xsl:if>
  </xsl:template>
  
</xsl:stylesheet>

I received the error message, cannot parse xsl.

anali
  • 57
  • 5
  • Which XSLT 1.0 processor will you be using? This is not a trivial problem, and you could use an extension function, if your processor supports it. – michael.hor257k Oct 23 '20 at 00:53

1 Answers1

1

You can use the following XSLT-1.0 stylesheet. It uses an approach similar to the method described in this SO answer implementing an XSLT-1.0 fn:max() function (like the XPath-2.0 function fn:max()):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="text" />

  <xsl:template match="/">
    <html>
      <body>
          <ul>
            <xsl:apply-templates select="//library[address/country='Indonesia']"/> 
          </ul>
      </body>  
    </html>
  </xsl:template>
    
  <xsl:template match="library">
    <h1><xsl:value-of select="concat('Library ', id, ': ', name, '&#xa;')"/></h1>
    <xsl:apply-templates select="books/book[not(preceding-sibling::book/qty > qty) and not(following-sibling::book/qty > qty)]"/>           
  </xsl:template>

  <xsl:template match="book">
    <xsl:value-of select="concat(name,': ',qty)"/>
    <xsl:text>&#xa;</xsl:text>
  </xsl:template>
  
</xsl:stylesheet>

Its output is:

Library 1: DabZ
Master your mind: 84
Library 2: Skippad
Flu Relief: 361
Stress Relief: 361

If you also want to output the <h1> tags and similar (which your code indicates), you have to change the <xsl:output method="text" /> attribute to html or xml.

zx485
  • 28,498
  • 28
  • 50
  • 59