XSLT: сопоставление атрибутов Xpath с атрибутами для каждой области видимости - PullRequest
1 голос
/ 12 января 2010

Я думаю, что моя проблема довольно распространена, поэтому должно быть простое решение. Рассмотрим следующий фрагмент XML:

  <categories>
    <category name="cat1" />
    <category name="cat2" />
    <category name="cat3" />
    <category name="cat4" />
  </categories>
  <data>
    <catval name="cat2">foo</catval>
    <catval name="cat4">bar</catval>
    <catval name="cat3">boo</catval>
  </data>

Мне нужно вывести значения catval в порядке, определенном в элементе категорий (включая категории, у которых нет данных). Обратите внимание, что в реальном входном XML есть несколько элементов data повсюду, и вывод является более сложным, поэтому создание шаблона для категорий не представляется возможным. Я использую конструкцию, подобную следующей:

<xsl:template match="data">
    <xsl:variable name="currentdata" select="." />
    <xsl:for-each select="../categories/category">
      <xsl:value-of select="@name" />: 
      <xsl:value-of 
        select="$currentdata/catval[@name=@name]" /> <!-- ??? -->
    </xsl:for-each>
</xsl:template>

Я не знаю, является ли это лучшим подходом для решения моей проблемы, но даже если это не так: как сопоставить атрибут name в $ currentdata / catval с атрибут name элемента category в контексте цикла for-each?

Ответы [ 3 ]

3 голосов
/ 12 января 2010

Простой, элегантный и эффективный:

<xsl:key name="catvalByName" match="catval" use="@name" />

<xsl:template match="category">
  <xsl:value-of select="@name" />
  <xsl:text>: </xsl:text>
  <xsl:value-of select="key('catvalByName', @name)" />
  <xsl:text>&#10;</xsl:text>
</xsl:template>

Будет выводить:

cat1: 
cat2: foo
cat3: boo
cat4: bar

при таком вызове, например:

<xsl:template match="categories">
  <xsl:apply-templates select="category" />
</xsl:template>
1 голос
/ 12 января 2010

Используйте переменную для сохранения значения атрибута из области действия <xsl:for-each>:

<xsl:template match="data">
  <xsl:variable name="currentdata" select="." />
  <xsl:for-each select="../categories/category">
    <xsl:variable name="name" select="@name"/>
    <xsl:value-of select="$name" />: 
    <xsl:value-of 
      select="$currentdata/catval[@name=$name]" /> <!-- ??? -->
  </xsl:for-each>
</xsl:template>
0 голосов
/ 12 января 2010

Я бы пошел другим путем:

<xsl:template match="categories">
   <xsl:for-each select="category">
     <xsl:variable name="name" select="@name"/>
     <xsl:apply-template select="/data/catval[@name=$name]/>
   </xsl:for-each>
</xsl:template>

<xsl:template match="catval">
  <!-- Your output logic here -->
</xsl:template>

Итак, попав в шаблон «catval», вы уверены, что заказ уже выполнен, и вам просто нужно сосредоточиться на форматировании вывода.

...