Как сделать второе преобразование на выходе шаблона XSLT - PullRequest
15 голосов
/ 03 октября 2011

У меня есть только базовые навыки XSLT, поэтому извиняюсь, если это является базовым или невозможным.

У меня есть шаблон paginator, который используется везде на сайте, который я просматриваю.Есть ошибка, когда одному конкретному поиску нужно добавить параметр categoryId, добавленный к href ссылок на страницы. Я не могу изменить таблицу стилей paginator , иначе я бы просто добавил к ней параметр.Я хотел бы применить шаблон как есть, а затем выполнить второе преобразование на основе его выходных данных.Это возможно?Как обычно другие расширяют шаблоны библиотек?

До сих пор я думал о создании рекурсивной копии выходных данных и применении шаблона к hrefs по мере их обработки.Синтаксис этого несколько ускользает от меня, тем более что я даже не уверен, что это возможно.


Редактировать - Между ответом Дабблера и комментарием Майкла Кея мы туда попали.Вот мой полный тест.

 <xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common">
    <!-- note we require the extensions for this transform -->

    <!--We call the template to be extended here and store the result in a variable-->
    <xsl:variable name="output1">
            <xsl:call-template name="pass1"/>
    </xsl:variable>

    <!--The template to be extended-->
    <xsl:template name="pass1">
            <a href="url?param1=junk">foo</a>
    </xsl:template>

    <!--the second pass. we lock this down to a mode so we can control when it is applied-->
    <xsl:template match="a" mode="pass2">
            <xsl:variable name="href" select="concat(@href, '&amp;', 'catid', '=', 'stuff')"/>
            <a href="{$href}"><xsl:value-of select="."/></a>
    </xsl:template>

    <xsl:template match="/">
            <html><head></head><body>
                    <!--the node-set extension function turns the first pass back into a node set-->
                    <xsl:apply-templates select="ext:node-set($output1)" mode="pass2"/>
            </body></html>
    </xsl:template>

</xsl:stylesheet>

Ответы [ 2 ]

17 голосов
/ 04 октября 2011

Вот полный пример того, как многопроходная обработка может быть выполнена с XSLT 1.0 :

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

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

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

 <xsl:template match="/">
  <xsl:variable name="vrtfPass1Result">
   <xsl:apply-templates/>
  </xsl:variable>

  <xsl:apply-templates mode="mPass2"
      select="ext:node-set($vrtfPass1Result)/*"/>
 </xsl:template>

 <xsl:template match="num/text()">
  <xsl:value-of select="2*."/>
 </xsl:template>

 <xsl:template match="/*" mode="mPass2">
  <xsl:copy>
    <xsl:copy-of select="@*"/>
    <xsl:apply-templates mode="mPass2"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="num/text()" mode="mPass2">
  <xsl:value-of select="3 + ."/>
 </xsl:template>
</xsl:stylesheet>

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

<nums>
  <num>01</num>
  <num>02</num>
  <num>03</num>
  <num>04</num>
  <num>05</num>
  <num>06</num>
  <num>07</num>
  <num>08</num>
  <num>09</num>
  <num>10</num>
</nums>

желаемый результат (каждый num умножается на 2 и на следующем проходе 3 добавляется к каждому num), получается :

<nums>
   <num>5</num>
   <num>7</num>
   <num>9</num>
   <num>11</num>
   <num>13</num>
   <num>15</num>
   <num>17</num>
   <num>19</num>
   <num>21</num>
   <num>23</num>
</nums>
8 голосов
/ 03 октября 2011

Это возможно в XSLT 2; Вы можете хранить данные в переменной и вызывать apply-templates для этого.

Базовый пример:

<xsl:variable name="MyVar">
   <xsl:element name="Elem"/> <!-- Or anything that creates some output -->
</xsl:variable>
<xsl:apply-templates select="$MyVar"/>

И где-то в вашей таблице стилей есть шаблон, соответствующий Elem. Вы также можете использовать отдельный режим, чтобы провести четкое различие между двумя фазами (создание переменной и ее обработка), особенно когда обе фазы используют шаблоны, которые соответствуют одним и тем же узлам.

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