Условное Авто приращение в xsl - PullRequest
1 голос
/ 21 августа 2009

У меня есть такой XML-код:

<V>
  <W>
    <X>1</X> 
  </W>
  <W>
    <Y>1</Y> 
  </W>
  <W>
    <X>1555</X> 
  </W>
  <W>
    <X>1</X> 
  </W>
</V>

Я хочу сделать что-то вроде этого:

<entity ID="start">
    <f ID="NewField">0001</f>
    <f ID="NewField">0001</f>
    <f ID="NewField">0002</f>
    <f ID="NewField">0003</f>
</entity>

Если поле имеет значение V / W / X, тогда значение NewField должно быть увеличено на 1 столько раз, сколько найдено тега V / W / X. Аналогично для V / W / Y.

XSL, который я использую -

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<entity ID="start">
    <xsl:for-each select="V/W">
        <xsl:if test="X">
            <xsl:variable name="my_var">
                <xsl:value-of select="concat('000',position())"/>
            </xsl:variable>
            <f ID="NewField"><xsl:value-of  select="$my_var"/></f>
        </xsl:if>
        <xsl:if test="Y">
            <xsl:variable name="my_var">
                <xsl:value-of select="concat('000',position())"/>
            </xsl:variable>
            <f ID="NewField"><xsl:value-of  select="$my_var"/></f>
        </xsl:if>
    </xsl:for-each>
</entity>
</xsl:template>
</xsl:stylesheet>

но это дает мне неверный результат, что-то вроде этого:

<entity ID="start">
  <f ID="NewField">0001</f>
  <f ID="NewField">0002</f> 
  <f ID="NewField">0003</f> 
  <f ID="NewField">0004</f> 
</entity>

Ответы [ 3 ]

1 голос
/ 14 февраля 2010

Если вы хотите пронумеровать узлы с помощью XSLT, тогда элемент xsl: number может помочь:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">

  <xsl:output indent="yes"/>

  <xsl:template match="/">
    <entity ID="start">
      <xsl:apply-templates select="descendant::X | descendant::Y"/>
    </entity>
  </xsl:template>

  <xsl:template match="X | Y">
    <f ID="NewField"><xsl:number level="any" format="0000"/></f>
  </xsl:template>

</xsl:stylesheet>
0 голосов
/ 21 августа 2009
<xsl:stylesheet 
  version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
  <xsl:template match="V">
    <entity ID="start">
      <xsl:apply-templates select="W/X|W/Y" />
    </entity>
  </xsl:template>

  <xsl:template match="X|Y">
    <f ID="NewField">
      <xsl:variable name="counter" select="
        count(
          parent::W/preceding-sibling::W/*[name() = name(current())]
        ) + 1
      " />
      <xsl:value-of select="format-number($counter, '0000')" />
    </f>
  </xsl:template>

</xsl:stylesheet>

Это:

parent::W/preceding-sibling::W/*[name() = name(current())]

выбирает все предыдущие элементы с тем же именем, что и текущий элемент. Например, если точка исполнения находится на этом узле:

<X>1555</X> 

Он поднимается на один уровень вверх (parent::W), затем выбирает всех предшествующих <W> братьев и сестер, и из них он выбирает любого потомка (*), который имеет имя X - поскольку X является имя элемента current().

Результирующий набор узлов считается и увеличивается на единицу. format-number() используется для создания хорошего чистого вывода:

<entity ID="start">
  <f ID="NewField">0001</f>
  <f ID="NewField">0001</f>
  <f ID="NewField">0002</f>
  <f ID="NewField">0003</f>
</entity>
0 голосов
/ 21 августа 2009

Я думаю, вы ищете что-то вроде count(preceding::X) выражения. Конечно, вы можете сделать его более сложным, а затем позаботиться о форматировании чисел, но это звучит как отправная точка, которую вы ищете.

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