I'm transforming an xml document to an html table using xslt, and now what I want to do is to change the background color of the cell containing the lowest "price" value without sorting my list.
我正在使用xslt将xml文档转换为html表,现在我想要做的是更改包含最低“price”值的单元格的背景颜色,而不对列表进行排序。
I'm new on this, so what I'm doing is following the W3C schools examples. The xml file looks like this:
我是新手,所以我正在做的是遵循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>
And what I want to obtain is something similar to this but without ordering the elements in the list by price. So I want to maintain the original order in the XML document.
而我想要获得的是类似于此但没有按价格排序列表中的元素。所以我想在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>
Thanks in advance for your help.
在此先感谢您的帮助。
EDIT: I think I have found a solution for my question:
编辑:我想我找到了一个问题的解决方案:
<?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(. > ../../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>
2 个解决方案
#1
2
You seem to have answered your question already, but I will throw in a couple of other things in here.
你似乎已经回答了你的问题,但我会在这里提出其他几件事。
(1) You can avoid re-calculating the minimum price at each iteration through the <cd/>
elements by adding a variable to the stylesheet or the template to do the calculation once:
(1)通过在样式表或模板中添加一个变量进行一次计算,可以避免通过
<xsl:variable name="least" select="math:min(/catalog/cd/price)"/>
(2) That "$least" variable declaration uses the EXSLT math:min function (namespace is xmlns:math="http://exslt.org/math"), which may be available to your XSLT 1.0 processor. If you have a 2.0 processor, you can use the built-in "min()".
(2)“$ least”变量声明使用EXSLT数学:min函数(命名空间为xmlns:math =“http://exslt.org/math”),它可供您的XSLT 1.0处理器使用。如果您有2.0处理器,则可以使用内置的“min()”。
If nothing else, a min() function is more readable for the next person.
如果没有别的,min()函数对下一个人来说更具可读性。
(3) This is purely stylistic, but you can reduce the branching a bit by using xsl:attribute.
(3)这是纯粹的风格,但你可以通过使用xsl:attribute来减少分支。
<td>
<xsl:if test="price=$lowest">
<xsl:attribute name="bgcolor">#ff00ff</xsl:attribute>
</xsl:if>
<xsl:value-of select="price"/>
</td>
#2
3
And what I want to obtain is something similar to this but without ordering the elements in the list by price.
而我想要获得的是类似于此但没有按价格排序列表中的元素。
The fact that sorting is used for finding the minimum doesn't mean that any elements will be re-ordered. Finding the minimum using <xsl:sort>
is in practice the fastest way to do so in XSLT 1.0 -- and doesn't require any extension functions:
排序用于查找最小值的事实并不意味着任何元素将被重新排序。使用
<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>
When this transformation is applied on the provided XML document:
在提供的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>
the wanted, correct result is produced:
产生了想要的正确结果:
<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>
#1
2
You seem to have answered your question already, but I will throw in a couple of other things in here.
你似乎已经回答了你的问题,但我会在这里提出其他几件事。
(1) You can avoid re-calculating the minimum price at each iteration through the <cd/>
elements by adding a variable to the stylesheet or the template to do the calculation once:
(1)通过在样式表或模板中添加一个变量进行一次计算,可以避免通过
<xsl:variable name="least" select="math:min(/catalog/cd/price)"/>
(2) That "$least" variable declaration uses the EXSLT math:min function (namespace is xmlns:math="http://exslt.org/math"), which may be available to your XSLT 1.0 processor. If you have a 2.0 processor, you can use the built-in "min()".
(2)“$ least”变量声明使用EXSLT数学:min函数(命名空间为xmlns:math =“http://exslt.org/math”),它可供您的XSLT 1.0处理器使用。如果您有2.0处理器,则可以使用内置的“min()”。
If nothing else, a min() function is more readable for the next person.
如果没有别的,min()函数对下一个人来说更具可读性。
(3) This is purely stylistic, but you can reduce the branching a bit by using xsl:attribute.
(3)这是纯粹的风格,但你可以通过使用xsl:attribute来减少分支。
<td>
<xsl:if test="price=$lowest">
<xsl:attribute name="bgcolor">#ff00ff</xsl:attribute>
</xsl:if>
<xsl:value-of select="price"/>
</td>
#2
3
And what I want to obtain is something similar to this but without ordering the elements in the list by price.
而我想要获得的是类似于此但没有按价格排序列表中的元素。
The fact that sorting is used for finding the minimum doesn't mean that any elements will be re-ordered. Finding the minimum using <xsl:sort>
is in practice the fastest way to do so in XSLT 1.0 -- and doesn't require any extension functions:
排序用于查找最小值的事实并不意味着任何元素将被重新排序。使用
<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>
When this transformation is applied on the provided XML document:
在提供的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>
the wanted, correct result is produced:
产生了想要的正确结果:
<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>