问题:
我有一个 XML 格式的项目列表,我想显示一个包含其名称和属性的表。这相当简单,除了某些项的属性是其他项的总和。在下面的示例中,我想显示食物名称和总卡路里。有些物品具有"卡路里"属性;其他人有一个成分列表,总卡路里应该是该列表中每个项目的卡路里总和。
我对一种不适用于含有其他骨料食物的聚合食物的解决方案感到满意。我仅限于 xsl 1.0。
<?xml version="1.0" encoding="ISO-8859-1"?>
<FoodList>
<SimpleFood name="Banana" calories="50"/>
<SimpleFood name="IceCream" calories="100"/>
<AggregateFood name="BananaSplit">
<IngredientList>
<Ingredient typeRef="Banana"/>
<Ingredient typeRef="IceCream"/>
<Ingredient typeRef="IceCream"/>
</IngredientList>
</AggregateFood>
</FoodList>
以下是基本样式表:
<?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>
<xsl:variable name="foods" select="FoodList/*"/>
<xsl:for-each select="$foods">
<tr>
<td>
<xsl:value-of select="@name"/>
</td>
<td>
<xsl:choose>
<xsl:when test="local-name()='SimpleFood'">
<xsl:value-of select="@calories"/>
</xsl:when>
<xsl:when test="local-name()='AggregateFood'">
<!-- -->
<!-- YOUR AWESOME CODE GOES HERE! -->
<!-- -->
</xsl:when>
</xsl:choose>
</td>
</tr>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
以下是我想看到的输出:
<?xml version="1.0" encoding="UTF-8"?>
<html>
<body>
<tr>
<td>Banana</td>
<td>50</td>
</tr>
<tr>
<td>IceCream</td>
<td>100</td>
</tr>
<tr>
<td>BananaSplit</td>
<td>250</td>
</tr>
</body>
</html>
尝试:
<xsl:value-of select="sum($foods/*[@name=current()/IngredientList/Ingredient/@typeRef]/@calories)"/>
这不仅不起作用(返回 0 卡路里),而且在成分列表中找到与成分匹配的每个元素的想法是有缺陷的,因为它会单独计算重复的冰淇淋成分并返回 150 卡路里而不是正确的 250(如果有人能给我看这个的工作版本,那就太酷了, 出于个人好奇心)。
另一个尝试:
<xsl:variable name="ingredients">
<xsl:for-each select="IngredientList/Ingredient">
<xsl:element name="Ingredient">
<xsl:attribute name="calories">
<xsl:value-of select="$foods/x:*[@name=current()/@typeRef]"/>
</xsl:attribute>
</xsl:element>
</xsl:for-each>
</xsl:variable>
<xsl:value-of select="sum($ingredients/@calories)"/>
复制元素也是如此:
<xsl:variable name="ingredients">
<xsl:for-each select="IngredientList/Ingredient">
<xsl:copy-of select="$foods/x:*[@name=current()/@typeRef]"/>
</xsl:for-each>
</xsl:variable>
<xsl:value-of select="sum($ingredients/@calories)"/>
以上工作都:(我想将它们作为建议发布,以让球滚动;也许你可以找到我的一个简单的错误。
我已经格式化了示例代码,以便您可以通过在线 xsl 转换器(例如此处找到的转换器):http://www.freeformatter.com/xsl-transformer.html。我可能不会"接受"答案,除非我可以使用这样的工具获得所需的输出。
谢谢!
使用模板,一个键和我写的exsl:node-set
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common" exclude-result-prefixes="exsl">
<xsl:key name="by-name" match="SimpleFood" use="@name"/>
<xsl:template match="/">
<html>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="FoodList">
<table>
<thead>
<tr>
<th>Name</th>
<th>Calories</th>
</tr>
</thead>
<tbody>
<xsl:apply-templates/>
</tbody>
</table>
</xsl:template>
<xsl:template match="SimpleFood">
<tr>
<td><xsl:value-of select="@name"/></td>
<td><xsl:value-of select="@calories"/></td>
</tr>
</xsl:template>
<xsl:template match="AggregateFood">
<tr>
<td><xsl:value-of select="@name"/></td>
<td>
<xsl:variable name="ing-cals">
<xsl:for-each select="IngredientList/Ingredient">
<cal><xsl:value-of select="key('by-name', @typeRef)/@calories"/></cal>
</xsl:for-each>
</xsl:variable>
<xsl:value-of select="sum(exsl:node-set($ing-cals)/cal)"/>
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
哪些输出
<html>
<body>
<table>
<thead>
<tr>
<th>Name</th>
<th>Calories</th>
</tr>
</thead>
<tbody>
<tr>
<td>Banana</td>
<td>50</td>
</tr>
<tr>
<td>IceCream</td>
<td>100</td>
</tr>
<tr>
<td>BananaSplit</td>
<td>250</td>
</tr>
</tbody>
</table>
</body>
</html>