每个父级在多个子节点上进行XSLT排序

时间:2012-09-14 10:18:17

标签: xml xslt sorting xpath

我有以下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>

每个元素都有多个价格标签,我想为每个元素选择MAX价格,并将其用于与其他元素进行比较。

我的xslt是:

<?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>

它不起作用。它产生:

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

虽然它应该产生:

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

请告诉我。我必须使用XSLT1,所以我真的不能这样做:

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

...

2 个答案:

答案 0 :(得分:2)

我不确定这是否是一种特别优雅的方式,但你可以迭代价格元素而不是条目元素

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

然后,你需要一个 xsl:if 条件来检查每个 price 元素,该元素没有更高的元素

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

这是完整的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>

如果应用于您的XML,则输出以下内容

<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>

答案 1 :(得分:0)

请参阅我对 this question 的回答。

在那里使用“最小”,否则解决方案基本上就是需要的。