Приращение переменной в XSLT - PullRequest
4 голосов
/ 26 мая 2010

у меня есть xml-файл типа

<node>
 <elm val="data1"/>
 <elm val="data2"/>
 <elm val="data3"/>
 <elm val="data4"/>
 <elm val="data5"/>
 <elm val="data6"/>
 <elm val="data7"/>
</node>

мне нужно написать xslt для этого xml-файла для отображения в таблице как

  1 dat1
  2 dat2
  3 dat3
  4 dat4
  5 dat5
  6 dat6
  7 dat7

пожалуйста, помогите мне сделать это

Ответы [ 5 ]

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

Это неправильно :

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="elm">
     <xsl:value-of select="concat(position(), ' ', @val)"/>
 </xsl:template>
</xsl:stylesheet>

При работе со многими процессорами XSLT это приведет к следующему (нежелательному) выводу :

 2 data1
 4 data2
 6 data3
 8 data4
 10 data5
 12 data6
 14 data7

Причина в том, что когда шаблоны применяются к дочерним элементам верхнего элемента, это включает дочерние элементы, которые являются текстовыми узлами только для пробелов - между каждыми двумя последовательными elm элементами.

Итак, решение Одеда неверно .

Вот одно правильное решение (и одно из самых коротких из возможных):

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:strip-space elements="*"/>

 <xsl:template match="elm">
     <xsl:value-of select="concat(position(), ' ', @val, '&#xA;')"/>
 </xsl:template>
</xsl:stylesheet>

Это преобразование дает правильный результат :

1 data1
2 data2
3 data3
4 data4
5 data5
6 data6
7 data7

Примечание :

  1. Использование <xsl:strip-space elements="*"/>, чтобы заставить процессор XSLT отбрасывать любые текстовые узлы только для пробелов.

  2. Использование функции XPath concat() для склеивания позиции, данных и символа NL.

2 голосов
/ 26 мая 2010
<xsl:tempate match="node">
  <table>
    <xsl:call-template select="elm"/>
  </table>
</xsl:template>

<xsl:template match="elm">
  <tr>
    <td>
      <xsl:value-of select="count(preceding-sibling::elm) + 1"/>
    </td>
    <td>
      <xsl:value-of select="@val"/>
    </td>
  </tr>
</xsl:template>

В качестве альтернативы, если требуется точный вывод, используйте следующий шаблон для elm.

<xsl:template match="elm">
  <xsl:param name="pos" select="count(preceding-sibling::elm) + 1"/>
  <tr>
    <td>
      <xsl:value-of select="$pos"/>
    </td>
    <td>
      <xsl:text>dat</xsl:text>
      <xsl:value-of select="$pos"/>
    </td>
  </tr>
</xsl:template>

Или в случае вывода текста:

<xsl:tempate match="node">
  <xsl:foreach select="elm">
     <xsl:value-of select="count(preceding-sibling::elm) + 1"/>
     <xsl:text> dat</xsl:text>
     <xsl:value-of select="count(preceding-sibling::elm) + 1"/>
     <xsl:text  disable-output-escaping="yes">&amp;#xA;</xsl:text>
  </xsl:foreach>
</xsl:template>
1 голос
/ 26 мая 2010

Вы можете использовать функцию position()

<xsl:template match="elm">
   <xsl:value-of select="concat(position(), ' ', @val)" />
</xsl:template>

Примечание: формат таблицы в вашем примере не соответствует значению атрибута val, но я предположил, что вы хотите, чтобы оба были одинаковыми (вывод первой строки должен быть 1 data1 вместо 1 dat1 .

Как отметил @Dimitre Novatchev в своем ответе, это предполагает, что ваш исходный документ не имеет узлов только для пробелов. В своем ответе он имеет дело с этим, удалив все узлы только для пробелов из входного документа (используя директиву <xsl:strip-space elements="*"/>) и добавив символ новой строки (&#xA;) в конце конкатенации.

0 голосов
/ 26 мая 2010

XSLT «переменные» являются неизменными переменными.После того, как вы их установите, вы не сможете произвольно изменить их.

Единственный способ взломать это - использовать функцию position () и другие функции «+1», но вы не получаете гибкостьtrue variable.

Существует множество статей о неизменности XSLT-переменных.

Цитирование статьи на тему "http://www.xml.com/pub/a/2001/02/07/trxml9.html"

XSLT-переменных на самом деле имеет многобольше общего с константами во многих языках программирования и используются для аналогичных целей.

Счетчики в XSLT невозможны, поскольку XSLT не является процедурным языком, он декларативен. Для downvoter: укажите причинуЕсли это не так, то, пожалуйста, докажите обратное.

0 голосов
/ 26 мая 2010
<xsl:template match="node">
   <table>
      <xsl:apply-templates select="elm"/>
   </table>
</xsl:template>

<xsl:template match="elm">
   <tr>
      <td><xsl:value-of select="position()"/></td>
      <td>dat<xsl:value-of select="position()"/></td>
   </tr>
</xsl:template>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...