代码之家  ›  专栏  ›  技术社区  ›  e-holder

在XSLT中,如何使用间接键进行排序?

  •  2
  • e-holder  · 技术社区  · 16 年前

    我很难得到 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>
    

    我想制作一份包含在客户订单中的饮料列表(按名称排序)。下面是我正在处理的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 命令试图将“oid”属性应用于饮料选举中的饮料元素,而不是本地饮料元素。

    我可以用一个变量来解决这个问题,比如 xsl:value-of 语句。但自从 排序:XSL 必须是 xsl:for-each 声明,我不能插入 xsl:variable 语句之前 排序:XSL .

    有没有一种方法可以明确地声明属性值应该从“local”元素中获取?

    1 回复  |  直到 16 年前
        1
  •  2
  •   Tomalak    16 年前

    你错过了 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>
    

    A您可能没有正确使用模板,因为如果使用了模板,您的 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>
    

    请注意,我也为每个删除了。每个 对于每个 避免是朝着更好的XSLT代码迈进的一步(极少数例外适用)。