我有文件grandchild.xml,它的结果用granchild.xsl处理后必须转发到child.xsl,然后必须最终由parent.xsl处理输出。
我尝试向xml-stylesheet
结果文档添加一个元素,期望它被引用的 XSL 样式表处理,但没有发生任何事情。
完成这项任务的正确声明是什么?我在互联网上搜索了很多,没有结果。
以下是浏览器中的多遍转换示例:
让我们有这个源 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 转换:
<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>
和
<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。
这是将这两者粘合在一起的转换:
<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>
说明:
主要样式表模块(XML 文档 PI 中引用的那个)导入包含单独转换的两个样式表模块。
第一次转换的结果被捕获在 variavle 中$vrtfPass1
。
在 XSLT 1.0 中,此类变量属于臭名昭著的“RTF”(结果树片段)类型,不能直接操作(只能string()
在 RTF 上使用复制和函数)。在这里,我们使用xxx:node-set()
扩展功能的可移植变体,它可以在 IE 和其他四种主要浏览器中运行。这个可移植的扩展首先由@DavidCarlisle 提出,原文可以在他的博客中找到。
然后将模式“pass2”中的模板应用于节点集,我们在上面的步骤中将 RTF 变量转换为该节点集。第二个导入的样式表模块中的所有模板都处于“pass2”模式,因此它们被选中执行。
最终结果产生。
除非有人知道得更好,否则我相信在浏览器上递归处理 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
.