В XSLT, как вы можете сортировать, используя косвенный ключ? - PullRequest
2 голосов
/ 20 мая 2010

У меня проблемы с получением 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" к элементам Drink в DrinkSelections, а не к локальному элементу Drink.

Я могу обойти это, используя переменную, как в операторе xsl:value-of. Но поскольку xsl:sort должен быть первым оператором после оператора xsl:for-each, я не могу вставить оператор xsl:variable до xsl:sort.

Есть ли способ явно указать, что значение атрибута должно быть взято из "локального" элемента?

1 Ответ

2 голосов
/ 20 мая 2010

Вам не хватает функции 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-коду (применяются очень редкие исключения).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...