我无法让xsl:sort
了解我引用的属性的范围。这是一个XML示例文档来说明:
<Root>
<DrinkSelections>
<Drink id=1000 name="Coffee"/>
<Drink id=1001 name="Water"/>
<Drink id=1002 name="Tea"/>
<Drink id=1003 name="Almost But Not Quite Entirely Unlike Tea"/>
</DrinkSelections>
<CustomerOrder>
<Drinks>
<Drink oid="1001"/>
<Drink oid="1002"/>
<Drink oid="1003"/>
</Drinks>
</CustomerOrder
</Root>
我想生成CustomerOrder中包含的饮料列表(按名称排序)。这是我正在摆弄的XSLT代码:
<xsl:for-each select="/Root/CustomerOrder/Drinks/Drink">
<xsl:sort select="/Root/DrinkSelections/Drink[@id = @oid]/@name"/>
<xsl:variable name=var_oid select="@oid"/>
<xsl:value-of select="/Root/DrinkSelections/Drink[@id = $var_oid]/@name"/>
</xsl:for-each>
显然,xsl:sort
命令试图将“oid”属性应用于DrinkSelections中的Drink元素,而不是本地Drink元素。
我可以使用变量解决这个问题,就像在xsl:value-of
语句中一样。但由于xsl:sort
必须是xsl:for-each
语句之后的第一个语句,因此我无法在xsl:variable
之前插入xsl:sort
语句。
有没有办法明确说明属性值应该来自“local”元素?
答案 0 :(得分:2)
您缺少current()
功能。
<xsl:for-each select="/Root/CustomerOrder/Drinks/Drink">
<xsl:sort select="/Root/DrinkSelections/Drink[@id = current()/@oid]/@name"/>
<xsl:value-of select="/Root/DrinkSelections/Drink[@id = current()/@oid]/@name"/>
</xsl:for-each>
但更突出的是,为了便于阅读和,你缺少XSL密钥:
<xsl:key name="kDrinkById" match="DrinkSelections/Drink" use="@id" />
<!-- ... later ... -->
<xsl:for-each select="/Root/CustomerOrder/Drinks/Drink">
<xsl:sort select="key('kDrinkById', @oid)/@name"/>
<xsl:value-of select="key('kDrinkById', @oid)/@name"/>
</xsl:for-each>
您可能没有正确使用模板,因为如果您这样做,您的xsl:for-each
选择表达式将不会从根目录开始。
<xsl:template match="Root">
<xsl:apply-templates select="CustomerOrder/Drinks" />
</xsl:template>
<xsl:template match="CustomerOrder/Drinks">
<xsl:apply-templates select="Drink">
<xsl:sort select="key('kDrinkById', @oid)/@name"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="CustomerOrder/Drinks/Drink">
<xsl:value-of select="key('kDrinkById', @oid)/@name"/>
</xsl:template>
请注意,我也删除了for-each。避免每个xsl:for-each
都是迈向更好的XSLT代码的一步(非常罕见的例外情况适用)。