如何根据XML内容选择导入对应的XSL样式表?
问题分析与解决方案
你遇到的转换失败,核心原因是XSLT的<xsl:import>属于静态编译指令——它必须在样式表的编译阶段就确定要导入的资源,不能放在运行时执行的模板(比如<xsl:template match="/">)或条件判断(<xsl:choose>)内部,运行时的节点值无法影响静态导入的逻辑。
下面是几种可行的替代方案:
方案1:预导入所有样式表,动态调用对应模板(兼容XSLT 1.0)
先静态导入所有可能的设施样式表,再根据XML中的Source值,调用对应样式表中定义的专属主模板。
主样式表代码:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 提前导入所有子样式表 --> <xsl:import href="Stylesheet for Facility A.xml"/> <xsl:import href="Stylesheet for Facility B.xml"/> <xsl:template match="/"> <!-- 根据Source值匹配对应节点,触发模板调用 --> <xsl:apply-templates select="Root/Source"/> </xsl:template> <!-- 匹配Facility A,调用子样式表的主模板 --> <xsl:template match="Source[text()='Facility A']"> <xsl:call-template name="FacilityA-Main"/> </xsl:template> <!-- 匹配Facility B,调用子样式表的主模板 --> <xsl:template match="Source[text()='Facility B']"> <xsl:call-template name="FacilityB-Main"/> </xsl:template> </xsl:stylesheet>
要求每个子样式表(比如Stylesheet for Facility A.xml)必须定义一个唯一名称的主模板,示例:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template name="FacilityA-Main"> <!-- 这里写Facility A的转换逻辑 --> </xsl:template> </xsl:stylesheet>
方案2:使用静态参数指定导入(兼容XSLT 2.0+,需处理器支持)
如果你的XSLT处理器支持静态参数(比如Saxon),可以通过静态参数传递设施名称,直接在编译阶段确定要导入的样式表。
主样式表代码:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 定义静态参数,值来自XML的Source节点 --> <xsl:param name="facility-name" select="/Root/Source/text()" static="yes"/> <!-- 用静态参数拼接样式表路径,实现条件导入 --> <xsl:import href="Stylesheet for {$facility-name}.xml"/> <xsl:template match="/"> <xsl:apply-templates/> </xsl:template> </xsl:stylesheet>
方案3:动态加载样式表文档(兼容XSLT 1.0/2.0)
通过document()函数动态加载对应设施的样式表文档,再调用其中的模板逻辑。
主样式表代码:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <!-- 拼接目标样式表的路径 --> <xsl:variable name="stylesheet-path"> <xsl:text>Stylesheet for </xsl:text> <xsl:value-of select="Root/Source/text()"/> <xsl:text>.xml</xsl:text> </xsl:variable> <!-- 动态加载样式表文档 --> <xsl:variable name="target-stylesheet" select="document($stylesheet-path)"/> <!-- 调用样式表中的主模板 --> <xsl:call-template name="Main" select="$target-stylesheet"/> </xsl:template> </xsl:stylesheet>
同样要求子样式表定义统一名称的主模板(比如Main),确保可以被正确调用。
内容的提问来源于stack exchange,提问作者Dragyn
相关产品推荐
相关产品推荐

