Is daisy chaining xslt an accepted practice?

2019-02-09 05:04发布

问题:

I have a situation where I think I need to daisy chain my xslt transformation (i.e. that output of one xslt transform being input into another). The first transform is rather complex with lots of xsl:choice and ancestor xpaths. My thought is to transform the xml into xml that can then be easily transformed to html.

My question is 'Is this standard practice or am I missing something?'

Thanks in advance.

Stephen

回答1:

Performing a chain of transformations is used quite often in XSLT applications, though doing this entirely in XSLT 1.0 requires the use of the vendor-specific xxx:node-set() function. In XSLT 2.0 no such extension is needed as the infamous RTF datatype is eliminated there.

Here is an example (too-simple to be meaningful, but illustrating completely how this is done):

<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:template match="/">
   <xsl:variable name="vrtfPass1">
    <xsl:apply-templates select="/*/*"/>
   </xsl:variable>

   <xsl:variable name="vPass1"
        select="ext:node-set($vrtfPass1)"/>

   <xsl:apply-templates mode="pass2"
        select="$vPass1/*"/>
 </xsl:template>

 <xsl:template match="num[. mod 2 = 1]">
  <xsl:copy-of select="."/>
 </xsl:template>

 <xsl:template match="num" mode="pass2">
  <xsl:copy>
    <xsl:value-of select=". *2"/>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

when this transformation is applied on the following XML document:

<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>

the wanted, correct result is produced:

<num>2</num>
<num>6</num>
<num>10</num>
<num>14</num>
<num>18</num>

Explanation:

  1. In the first step the XML document is transformed and the result is defined as the value of the variable $vrtfPass1. This copies only the num elements that have odd value (not even).

  2. The $vrtfPass1 variable, being of type RTF, is not directly usable for XPath expressions so we convert it to a normal tree, using the EXSLT (implemented by most XSLT 1.0 processors) function ext:node-set and defining another variable -- $vPass1 whose value is this tree.

  3. We now perform the second transformation in our chain of transformations -- on the result of the first transformation, that is kept as the value of the variable $vPass1. Not to mess with the first-pass template, we specify that the new processing should be in a named mode, called "pass2". In this mode the value of any num element is multiplied by two.

XSLT 2.0 solution (no RTFs):

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

 <xsl:template match="/">
  <xsl:variable name="vPass1" >
   <xsl:apply-templates select="/*/*"/>
  </xsl:variable>
   <xsl:apply-templates mode="pass2"
        select="$vPass1/*"/>
 </xsl:template>

 <xsl:template match="num[. mod 2 = 1]">
  <xsl:copy-of select="."/>
 </xsl:template>

 <xsl:template match="num" mode="pass2">
  <xsl:copy>
    <xsl:value-of select=". *2"/>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>


回答2:

If this is your situation (or may become your situation):

  1. Transform initial xml to mediary xml.
  2. Maybe transform mediary xml into final1_html.
  3. Maybe transform mediary xml into final2_html (not at all like final1_html).

or

  1. Transform initial xml into mediary xml. This is reasonably likely to change over time.
  2. Transform mediary xml to final_html. This in not likely to change over time.

Then it makes sense to use a two step transformation.

If this is your situation:

  1. Transform initial xml to mediary xml.
  2. Transform mediary xml to final_html.

Then consider not two stepping. Instead just perform one transformation.



回答3:

I wouldn't think it was standard practice, in particular since you can transform one XML dialect directly to another.

However, if the processing is complex, splitting it to several steps (applying a different transform in each step) can indeed simplify each step and make sense.

It really depends on the particular situation.



标签: xslt