导入含同名模板的多XSL样式表冲突解决求助(XSLT3.0)
解决方案
针对XSLT 3.0和Saxon PE的特性,提供三种可行的隔离方案:
方案1:使用XSLT 3.0原生xsl:package封装隔离
通过将两个冲突样式表封装为独立命名空间的包,明确区分调用的模板:
为两个样式表创建包装包
package-ab.xsl(封装A→B转换):<xsl:package name="http://your-domain.com/ab-convert" package-version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0"> <xsl:use-package name="http://www.w3.org/xslt30/standard" package-version="3.0"/> <xsl:import href="convert_from_a_to_b.xsl"/> <!-- 暴露需要调用的模板,设置为公开可见 --> <xsl:expose component="template" names="template-1234 baseContent" visibility="public"/> </xsl:package>package-bc.xsl(封装B→C转换):<xsl:package name="http://your-domain.com/bc-convert" package-version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0"> <xsl:use-package name="http://www.w3.org/xslt30/standard" package-version="3.0"/> <xsl:import href="convert_from_b_to_c.xsl"/> <xsl:expose component="template" names="template-1234 baseContent" visibility="public"/> </xsl:package>
主样式表中引用包并指定调用
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ab="http://your-domain.com/ab-convert" xmlns:bc="http://your-domain.com/bc-convert" version="3.0"> <xsl:use-package name="http://your-domain.com/ab-convert" package-version="1.0" as="ab"/> <xsl:use-package name="http://your-domain.com/bc-convert" package-version="1.0" as="bc"/> <xsl:template match="//root"> <new_root_element> <xsl:apply-templates select="./*"/> </new_root_element> </xsl:template> <xsl:template match="content_to_convert"> <content> <xsl:variable name="convertedContent"> <!-- 使用ab包中的模板处理原始内容 --> <xsl:apply-templates select="./*" mode="ab-mode"/> </xsl:variable> <!-- 使用bc包中的模板处理转换后的内容 --> <xsl:apply-templates select="$convertedContent" mode="bc-mode"/> </content> </xsl:template> <!-- 绑定模式到ab包 --> <xsl:template match="*" mode="ab-mode"> <xsl:next-match package="ab"/> </xsl:template> <!-- 绑定模式到bc包 --> <xsl:template match="*" mode="bc-mode"> <xsl:next-match package="bc"/> </xsl:template> <!-- 通用身份模板 --> <xsl:template match="@* | node()" mode="#all"> <xsl:copy> <xsl:apply-templates select="@* | node()" mode="#current"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
方案2:使用Saxon扩展package属性直接指定
Saxon PE支持在xsl:apply-templates或xsl:call-template中通过package属性指定要调用的样式表包,无需额外封装:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0"> <!-- 将两个样式表导入为命名包 --> <xsl:import href="convert_from_a_to_b.xsl" package="ab"/> <xsl:import href="convert_from_b_to_c.xsl" package="bc"/> <xsl:template match="//root"> <new_root_element> <xsl:apply-templates select="./*"/> </new_root_element> </xsl:template> <xsl:template match="content_to_convert"> <content> <xsl:variable name="convertedContent"> <!-- 明确调用ab包中的模板 --> <xsl:apply-templates select="./*" package="ab"/> </xsl:variable> <!-- 明确调用bc包中的模板 --> <xsl:apply-templates select="$convertedContent" package="bc"/> </content> </xsl:template> <xsl:template match="@* | node()" mode="#all"> <xsl:copy> <xsl:apply-templates select="@* | node()" mode="#current"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
方案3:分阶段转换(最直观的隔离方式)
将转换拆分为两个独立步骤,完全隔离两个样式表:
- 第一步用
convert_from_a_to_b.xsl生成中间文档。 - 第二步用
convert_from_b_to_c.xsl将中间文档转换为最终输出。
在Oxygen中可通过创建多步骤转换场景实现,或在主样式表中用xsl:transform函数链式调用:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0"> <xsl:template match="/"> <!-- 第一步:执行A→B转换 --> <xsl:variable name="step1-output"> <xsl:transform href="convert_from_a_to_b.xsl" select="/"/> </xsl:variable> <!-- 第二步:执行B→C转换 --> <xsl:transform href="convert_from_b_to_c.xsl" select="$step1-output"/> </xsl:template> </xsl:stylesheet>
内容的提问来源于stack exchange,提问作者hepabolu
相关产品推荐
相关产品推荐

