Jak zrobić drugą transformację na wyjściu szablonu XSLT

Mam tylko podstawowe umiejętności XSLT, więc przepraszam, jeśli jest to albo podstawowe, albo niemożliwe.

Mam szablon paginatora, który jest używany wszędzie na stronie, na którą patrzę. Jest błąd, w którym jedno wyszukiwanie musi mieć parametr categoryId dołączony do href linków do strony. nie mogę zmienić arkusza stylów paginatora {[5] } albo po prostu dodałbym do niego param. To, co chciałbym zrobić, to zastosować szablon, a następnie wykonać drugą transformację w oparciu o jego wynik. Czy to możliwe? Jak inni zwykle robią rozszerzenia szablonów bibliotek?

Do tej pory myślałem o wykonaniu rekurencyjnej kopii wyjścia i zastosowaniu szablonu do hrefs podczas ich przetwarzania. Składnia tego mi trochę umyka, zwłaszcza, że nie jestem nawet pewien, czy to możliwe.


Edit-między odpowiedzią Dabblera a komentarzem Michaela Kay ' a. Oto mój kompletny test.

 <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>
 15
Author: Ollie Edwards, 2011-10-03

2 answers

Jest to możliwe w XSLT 2; możesz przechowywać dane w zmiennej i wywoływać apply-templates na tym.

Przykład podstawowy:

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

I gdzieś w arkuszu stylów masz szablon pasujący do Elem. Można również użyć oddzielnego trybu, aby zachować wyraźne rozróżnienie między dwiema fazami (budowanie zmiennej i przetwarzanie jej), zwłaszcza gdy obie fazy używają szablonów, które pasują do tych samych węzłów.

 8
Author: Dabbler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-09 14:00:42

Oto kompletny przykład przetwarzania wieloprzebiegowego za pomocą 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>

Jeżeli transformacja ta jest zastosowana w następującym dokumencie 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>

Pożądany wynik (każdy num jest mnożony przez 2 i w następnym przebiegu 3 jest dodawany do każdego num) jest wytwarzany :

<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>
 17
Author: Dimitre Novatchev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-04 01:41:42