Подражая позиции (набор узлов) в XSLT 1.0? - PullRequest
2 голосов
/ 22 февраля 2012

XSLT 2.0 предлагает преимущество передачи параметра набора узлов как части функции position ().К сожалению, это не доступно в XSLT 1.0.Есть ли способ имитировать это поведение?

Например, с учетом этого XML:

<wishlists>
  <wishlist name="Games">
    <product name="Crash Bandicoot"/>
    <product name="Super Mario Brothers"/>
    <product name="Sonic the Hedgehog"/>
  </wishlist>
  <wishlist name="Movies">
    <product name="Back to the Future"/>
  </wishlist>
</wishlists>

и этого XSLT 2.0:

<xsl:value-of select="position(/wishlists/wishlist/product)"/>

значение "4"будет возвращен при обработке последнего узла «Назад в будущее».

К сожалению, наиболее близким, по-моему, с XSLT 1.0 является следующее:

<xsl:template match="product">
  <xsl:value-of select="position()"/>
</xsl:template>

ОднакоЯ получил бы значение «1» в том же узле «Назад в будущее», а не значение «4», которое мне действительно нужно.

Ответы [ 2 ]

4 голосов
/ 22 февраля 2012

Вы можете использовать предшествующую ось .

Эта таблица стилей XSLT 1.0:

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

  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="product">
    <product position="{count(preceding::product) + 1}">
      <xsl:apply-templates select="@*"/>
    </product>    
  </xsl:template>

</xsl:stylesheet>

При применении к вашему XML-вводу получается:

<wishlists>
   <wishlist name="Games">
      <product position="1" name="Crash Bandicoot"/>
      <product position="2" name="Super Mario Brothers"/>
      <product position="3" name="Sonic the Hedgehog"/>
   </wishlist>
   <wishlist name="Movies">
      <product position="4" name="Back to the Future"/>
   </wishlist>
</wishlists>
2 голосов
/ 22 февраля 2012

XSLT 2.0 предлагает преимущество передачи параметра набора узлов в качестве части функция position ().

Это утверждение неверно. Функция position() не имеет аргументов - ни в XPath 1.0, ни в XPath 2.0, который использует XSLT 2.0.

То, что вы хотите, это :

count(preceding::product) +1

или, альтернативно, можно использовать инструкцию xsl:number.

Вот демонстрация обоих этих методов :

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

 <xsl:variable name="vLastProd" select=
  "//product[@name='Back to the Future']"/>

 <xsl:template match="/">
     <xsl:value-of select="count($vLastProd/preceding::product) +1"/>
=========
<xsl:text/>
   <xsl:apply-templates select="$vLastProd"/>
 </xsl:template>

 <xsl:template match="product">
   <xsl:number level="any" count="product"/>    
 </xsl:template>
</xsl:stylesheet>

Когда это преобразование применяется к предоставленному документу XML :

<wishlists>
    <wishlist name="Games">
        <product name="Crash Bandicoot"/>
        <product name="Super Mario Brothers"/>
        <product name="Sonic the Hedgehog"/>
    </wishlist>
    <wishlist name="Movies">
        <product name="Back to the Future"/>
    </wishlist>
</wishlists>

требуемый, правильный результат получается с использованием обоих методов - и вывод :

4
=========
4

Примечание : результат xsl:number должен быть зафиксирован внутри тела переменной, если он не будет выводиться напрямую.

...