如何在Firefox中执行多轮XSL转换?
解决Firefox中XSLT 1.0使用exsl:node-set时的解析错误问题
我太懂你这种明明按文档操作却碰上火狐报错的憋屈了——说好支持exsl:node-set,结果一用就弹出“加载样式表出错:发生未知错误”,确实让人头大。结合XSLT 1.0的特性和Firefox的实现细节,给你几个排查和解决的方向:
1. 检查命名空间的完整声明
这是最容易踩的坑!很多人漏写了扩展元素前缀的声明,导致Firefox识别不了exsl:node-set。你必须在<xsl:stylesheet>根元素里同时添加两个关键部分:
- exsl命名空间的URL
- 声明exsl是扩展元素前缀
正确的示例写法:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common" extension-element-prefixes="exsl"> <!-- 你的转换逻辑 --> </xsl:stylesheet>
注意:命名空间URL必须完全一致,不能写错字符;extension-element-prefixes属性是告诉XSLT处理器,exsl:前缀的元素属于扩展功能,需要特殊处理。
2. 确认变量是“结果树片段(RTF)”
exsl:node-set的作用是把XSLT 1.0里的**结果树片段(RTF)**转换成可遍历的节点集。如果你的变量本身就是节点集(比如直接从源XML中选取的节点),强行转换反而会出错。
举个正确使用的例子:
<!-- 定义一个存储RTF的变量 --> <xsl:variable name="temp-xml"> <root> <item>转换后的内容</item> </root> </xsl:variable> <!-- 用exsl:node-set转换后再处理 --> <xsl:apply-templates select="exsl:node-set($temp-xml)/root/item"/>
同时要确保RTF里的XML是完全合法的:没有未闭合的标签、特殊字符(比如&、<)已经转义,Firefox对XML的合法性校验非常严格,一点小问题都会触发未知错误。
3. 兼容Firefox的实现细节
有些Firefox版本对exsl:node-set的参数要求更严格,你可以试试兼容微软的msxsl:node-set写法(Firefox也支持这个扩展),增加代码的鲁棒性:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common" xmlns:msxsl="urn:schemas-microsoft-com:xslt" extension-element-prefixes="exsl msxsl"> <xsl:variable name="temp-xml"> <!-- 中间结果 --> </xsl:variable> <!-- 优先用exsl,不行就用msxsl --> <xsl:choose> <xsl:when test="function-available('exsl:node-set')"> <xsl:apply-templates select="exsl:node-set($temp-xml)/node()"/> </xsl:when> <xsl:when test="function-available('msxsl:node-set')"> <xsl:apply-templates select="msxsl:node-set($temp-xml)/node()"/> </xsl:when> </xsl:choose> </xsl:stylesheet>
4. 多轮转换的备选方案
如果exsl:node-set始终无法正常工作,你可以考虑用JavaScript配合XSLTProcessor实现多轮转换:
- 第一次转换完成后,把中间结果以XML字符串的形式输出
- 用JavaScript解析这个字符串为DOM对象
- 加载第二个XSLT样式表,用XSLTProcessor处理中间DOM对象
这种方式虽然需要前端代码配合,但能绕开纯XSLT方案里的扩展函数限制。
内容的提问来源于stack exchange,提问作者user3532811




