4

我正在使用 xslt 将 xml 文档转换为 html 表,现在我要做的是更改包含最低“价格”值的单元格的背景颜色,而不对我的列表进行排序。

我对此很陌生,所以我正在做的是遵循 W3C 学校的例子。xml 文件如下所示:

    <?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Edited by XMLSpy® -->
<catalog>
<cd>
    <title>Empire Burlesque</title>
    <artist>Bob Dylan</artist>
    <country>USA</country>
    <company>Columbia</company>
    <price>10.90</price>
    <year>1985</year>
</cd>
<cd>
    <title>Black angel</title>
    <artist>Savage Rose</artist>
    <country>EU</country>
    <company>Mega</company>
    <price>11.90</price>
    <year>1995</year>
</cd>
<cd>
    <title>For the good times</title>
    <artist>Kenny Rogers</artist>
    <country>UK</country>
    <company>Mucik Master</company>
    <price>8.70</price>
    <year>1995</year>
</cd>
</catalog>

我想要获得的是与此类似的东西,但没有按价格对列表中的元素进行排序。所以我想保持XML文档中的原始顺序。

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <!-- Edited by XMLSpy® -->
    <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
     <html>
      <body>
        <h2>My CD Collection</h2>
        <table border="1">
          <tr bgcolor="#9acd32">
          <th>Title</th>
          <th>Artist</th>
          <th>Price</th>
        </tr>
        <xsl:for-each select="catalog/cd">
        <xsl:sort select="price" order="ascending" data-type="number"/>
          <tr>
            <td><xsl:value-of select="title"/></td>
            <td><xsl:value-of select="artist"/></td>
            <xsl:choose>
              <xsl:when test="(position() = 1)">
                <td bgcolor="#ff00ff">
                <xsl:value-of select="price"/></td>
              </xsl:when>
            <xsl:otherwise>
                <td><xsl:value-of select="price"/></td>
            </xsl:otherwise>
            </xsl:choose>
          </tr>
        </xsl:for-each>
        </table>
      </body>
      </html>
    </xsl:template>
    </xsl:stylesheet>

在此先感谢您的帮助。


编辑:我想我已经为我的问题找到了解决方案:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Edited by XMLSpy® -->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
  <html>
  <body>
    <h2>My CD Collection</h2>
    <table border="1">
      <tr bgcolor="#9acd32">
        <th>Title</th>
        <th>Artist</th>
        <th>Price</th>
      </tr>
      <xsl:for-each select="catalog/cd">
       <tr>
        <td><xsl:value-of select="title"/></td>
        <td><xsl:value-of select="artist"/></td>
        <xsl:choose>
          <xsl:when test="price=/catalog/cd/price[not(. &gt; ../../cd/price)][1]">
            <td bgcolor="#ff00ff">
            <xsl:value-of select="price"/></td>
          </xsl:when>
        <xsl:otherwise>
            <td><xsl:value-of select="price"/></td>
        </xsl:otherwise>
        </xsl:choose>
      </tr>

      </xsl:for-each>
    </table>
  </body>
  </html>
</xsl:template>

4

2 回答 2

6

我想要获得的是与此类似的东西,但没有按价格对列表中的元素进行排序。

排序用于查找最小值这一事实并不意味着任何元素都会被重新排序。在 XSLT 1.0 中,找到最低使用<xsl:sort>量实际上是最快的方法——并且不需要任何扩展函数

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

    <xsl:variable name="vLowest">
     <xsl:for-each select="/*/*/price">
      <xsl:sort data-type="number"/>
      <xsl:if test="position()=1"><xsl:value-of select="."/></xsl:if>
     </xsl:for-each>
    </xsl:variable>

 <xsl:template match="/*">
          <html>
          <body>
            <h2>My CD Collection</h2>
            <table border="1">
              <tr bgcolor="#9acd32">
                <th>Title</th>
                <th>Artist</th>
                <th>Price</th>
              </tr>
              <xsl:apply-templates select="cd"/>
            </table>
          </body>
          </html>
 </xsl:template>

 <xsl:template match="cd">
        <tr>
          <td><xsl:value-of select="title"/></td>
          <td><xsl:value-of select="artist"/></td>
          <td>
            <xsl:if test="price=number($vLowest)">
              <xsl:attribute name="bgcolor">#ff00ff</xsl:attribute>
            </xsl:if>
            <xsl:value-of select="price"/>
          </td>
        </tr>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于提供的 XML 文档时:

<catalog>
    <cd>
        <title>Empire Burlesque</title>
        <artist>Bob Dylan</artist>
        <country>USA</country>
        <company>Columbia</company>
        <price>10.90</price>
        <year>1985</year>
    </cd>
    <cd>
        <title>Black angel</title>
        <artist>Savage Rose</artist>
        <country>EU</country>
        <company>Mega</company>
        <price>11.90</price>
        <year>1995</year>
    </cd>
    <cd>
        <title>For the good times</title>
        <artist>Kenny Rogers</artist>
        <country>UK</country>
        <company>Mucik Master</company>
        <price>8.70</price>
        <year>1995</year>
    </cd>
</catalog>

产生了想要的正确结果:

<html>
   <body>
      <h2>My CD Collection</h2>
      <table border="1">
         <tr bgcolor="#9acd32">
            <th>Title</th>
            <th>Artist</th>
            <th>Price</th>
         </tr>
         <tr>
            <td>Empire Burlesque</td>
            <td>Bob Dylan</td>
            <td>10.90</td>
         </tr>
         <tr>
            <td>Black angel</td>
            <td>Savage Rose</td>
            <td>11.90</td>
         </tr>
         <tr>
            <td>For the good times</td>
            <td>Kenny Rogers</td>
            <td bgcolor="#ff00ff">8.70</td>
         </tr>
      </table>
   </body>
</html>
于 2013-04-10T03:07:00.070 回答
2

你似乎已经回答了你的问题,但我会在这里抛出一些其他的东西。

<cd/>(1)您可以通过在样式表或模板中添加一个变量来进行一次计算,从而避免在每次遍历元素时重新计算最低价格:

<xsl:variable name="least" select="math:min(/catalog/cd/price)"/>

(2) "$least" 变量声明使用 EXSLT math:min 函数(命名空间是 xmlns:math="http://exslt.org/math"),您的 XSLT 1.0 处理器可能可以使用该函数。如果您有 2.0 处理器,则可以使用内置的“min()”。

如果不出意外,min() 函数对于下一个人来说更具可读性。

(3) 这纯粹是风格,但您可以使用 xsl:attribute 减少分支。

<td>
    <xsl:if test="price=$lowest">
        <xsl:attribute name="bgcolor">#ff00ff</xsl:attribute>
    </xsl:if>
    <xsl:value-of select="price"/>
</td>
于 2013-04-09T18:25:33.017 回答