2

I have the following XML:

<?xml version="1.0" encoding="ISO-8859-1"?>
<entries>
    <entry>
        <title>Entry 1</title>
                <prices>
                <price>10</price>
                <price>50</price>
                </prices>
    </entry>
    <entry>
        <title>Entry 2</title>
                <prices>
                <price>200</price>
                <price>300</price>
                </prices>
    </entry>
    <entry>
        <title>Entry 3</title>
                <prices>
                <price>70</price>
                <price>500</price>
                </prices>
    </entry>
</entries>

Each element has more than one price tag, I want to select the MAX price, per element and use it for comparison with the rest of the elements.

My xslt is:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
  <html>
  <body>
    <table border="1">
      <tr>
        <th>Title</th>
        <th>Highest Price</th>
      </tr>
      <xsl:for-each select="entries/entry">
      <xsl:sort select="prices/price" order="descending" data-type="number"/>
      <tr>
        <td><xsl:value-of select="title"/></td>
        <td><xsl:value-of select="prices/price"/></td>
      </tr>
      </xsl:for-each>
    </table>
  </body>
  </html>
</xsl:template>

</xsl:stylesheet>

It doesn't work. It produces:

Title   Highest Price
Entry 2 200
Entry 3 70
Entry 1 10

While it should produce:

Title   Highest Price
Entry 3 500
Entry 2 300
Entry 1 50

Please advise me. I have to use XSLT1, so I can't really do:

<xsl:sort select="max(prices/price)" order="descending" data-type="number"/>

...

hyankov
  • 4,049
  • 1
  • 29
  • 46
  • 1
    How can you have "30" in the output but it is not even in the source XML. Please edit your source XML so it could fit your expected output. Best regards, Peter – Peter Sep 14 '12 at 10:27

2 Answers2

2

I am not sure if this is a particularly elegant way of doing it, but you could iterate over the price elements rather than the entry elements

<xsl:for-each select="entries/entry/prices/price">
  <xsl:sort select="." order="descending" data-type="number"/>

Then, you would need an xsl:if condition to check for each price element that there is not a higher one for that element

<xsl:if test="not(../price > current())">

Here is the full XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:template match="/">
      <html>
         <body>
            <table border="1">
               <tr>
                  <th>Title</th>
                  <th>Highest Price</th>
               </tr>
               <xsl:for-each select="entries/entry/prices/price">
                  <xsl:sort select="." order="descending" data-type="number"/>
                  <xsl:if test="not(../price > current())">
                     <tr>
                        <td>
                           <xsl:value-of select="../../title"/>
                        </td>
                        <td>
                           <xsl:value-of select="."/>
                        </td>
                     </tr>
                  </xsl:if>
               </xsl:for-each>
            </table>
         </body>
      </html>
   </xsl:template>
</xsl:stylesheet>

WHen applied to your XML, the following is output

<html>
<body>
<table border="1">
<tr>
<th>Title</th>
<th>Highest Price</th>
</tr>
<tr>
<td>Entry 3</td>
<td>500</td>
</tr>
<tr>
<td>Entry 2</td>
<td>300</td>
</tr>
<tr>
<td>Entry 1</td>
<td>50</td>
</tr>
</table>
</body>
</html>
Tim C
  • 70,053
  • 14
  • 74
  • 93
0

See my answer to this question.

"Minimum" is used there, but otherwise the solution is essentially what is needed.

Community
  • 1
  • 1
Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431