使递归地由“父”XSLT文档处理XSLT结果文档

时间:2012-08-14 16:15:23

标签: xml xslt

我有文件grandchild.xml,使用granchild.xsl处理后的结果必须转发到child.xsl,然后必须最终处理并由parent.xsl输出。

我尝试在结果文档中添加xml-stylesheet元素,期望使用引用的XSL样式表对其进行处理,但没有任何反应。

完成此任务的正确声明是什么?我在互联网上搜索了很多,没有结果。

2 个答案:

答案 0 :(得分:2)

以下是浏览器中多次转换的示例

让我们拥有此源XML文档

<?xml-stylesheet title="XSL_formatting"
  type="text/xsl" href="MultiPassBrowser.xsl"?>
<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>

让我们进行这两个XSLT转换

MultiPassBrowser1.xsl

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <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="num/text()">
  <xsl:value-of select=". *2"/>
 </xsl:template>
</xsl:stylesheet>

MultiPassBrowser2.xsl

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

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

 <xsl:template match="num" mode="pass2">
  <p><xsl:value-of select=". +1"/></p>
 </xsl:template>
</xsl:stylesheet>

第一个转换“按原样”复制XML文档,但每个num元素的字符串值乘以2。

第二个转换“按原样”复制XML文档,但每个num元素的字符串值递增。

如果第二个变换应用于第一个变换的结果,则从初始num元素获得的最终值必须为3,5,7,...,21。

以下是将这两者粘合在一起的转变

MultiPassBrowser.xsl

<xsl:stylesheet version="1.0" 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common"
 xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
 exclude-result-prefixes="ext msxsl">
 <xsl:import href="file:///C:/Temp/delete/MultiPassBrowser1.xsl"/>
 <xsl:import href="file:///C:/Temp/delete/MultiPassBrowser2.xsl"/>
 <xsl:output method="html"/>
 <xsl:strip-space elements="*"/>

 <msxsl:script language="JScript" implements-prefix="ext">
     this['node-set'] =  function (x) {
      return x;
      }
 </msxsl:script>

 <xsl:template match="/">
  <html>
      <xsl:variable name="vrtfPass1">
        <xsl:apply-templates select="/*"/>
      </xsl:variable>

      <xsl:apply-templates select="ext:node-set($vrtfPass1)/*/*"
                           mode="pass2"/>
  </html>
 </xsl:template>
</xsl:stylesheet>

当使用IE,Firefox,Safari和Opera打开XML文件时,结果是正确的,预期的

<html>
   <p>3</p>
   <p>5</p>
   <p>7</p>
   <p>9</p>
   <p>11</p>
   <p>13</p>
   <p>15</p>
   <p>17</p>
   <p>19</p>
   <p>21</p>
</html>

<强>解释

  1. 主样式表模块(XML文档PI中引用的模块)导入包含单独转换的两个样式表模块。

  2. 第一次转换的结果在变量$vrtfPass1中捕获。

  3. 在XSLT 1.0中,此变量属于臭名昭着的“RTF”(结果树片段)类型,无法直接操作(只能复制,string()功能可用于RTF)。这里我们使用xxx:node-set()扩展功能的可移植变体,它在IE和其他四个主要浏览器中都有效。 此便携式扩展程序最初由@DavidCarlisle提出,原始版本可在his blog 中找到。

  4. 模式“pass2”中的模板然后应用于节点集,我们在上面的步骤中转换了RTF变量。第二个导入的样式表模块中的所有模板都处于“pass2”模式,因此它们被选中执行。

  5. 产生最终结果。

答案 1 :(得分:0)

除非有人知道更好,否则我认为无法在浏览器上递归处理XSLT输出。

为了证明这一点,我刚刚尝试了以下IE8,FF14和Chrome ......

<强> level1.xml

<?xml version="1.0" encoding="utf-8" ?> 
<?xml-stylesheet title="XSL_formatting" type="text/xsl" href="level1.xsl"?>
<data>
  <id>Level 1 data</id>
</data>

<强> level1.xsl

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:template match="/">
     <?xml-stylesheet title="XSL_formatting" type="text/xsl" href="level2.xsl"?>
     <data2>
       <id2>Level 2: <xsl:value-of select="/data/id"/></id2>
     </data2>
   </xsl:template>   
</xsl:stylesheet>

<强> level2.xsl

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:template match="/">
     <html>
       <body>
         <b>Level 3:</b> <xsl:value-of select="/data2/id2"/>
       </body>
     </html>
   </xsl:template>   
</xsl:stylesheet>

所有3个浏览器的结果只是显示Level 2: Level 1 Data