导入公共XSL后如何重写模板实现XML文档差异化转换
问题原因说明
- 尝试1失效原因:XSLT模板默认匹配的是输入XML文档的原始节点,而非转换过程中生成的输出节点。你输入的XML中没有
h1元素,h1是公共模板的输出内容,因此匹配//h1的模板永远不会触发。 - 尝试2未生效大概率是语法问题:你贴的代码中
<xsl:import href="common.xsl /缺少闭合引号,正确语法应为<xsl:import href="common.xsl" />。XSLT中xsl:import的规则默认是「导入方(专用样式表)的模板优先级高于被导入的公共样式表」,同匹配规则的模板本应覆盖公共逻辑,若语法修复后仍不生效,可给专用模板添加priority属性强制提高优先级。
可行方案(均无需修改公共样式表和其他专用样式表)
方案1:直接覆盖公共模板(适合完全重写对应节点的转换逻辑)
如果你不需要保留公共模板的输出,直接重写匹配规则即可,可加优先级避免冲突:
<xsl:import href="common.xsl" /> <!-- priority值越高优先级越高,确保覆盖公共模板的同匹配规则 --> <xsl:template match="//data" priority="10"> <p>My name is <xsl:value-of select="name" />!</p> <!-- 如果需要保留公共模板的部分输出,可添加<xsl:apply-imports />调用公共模板逻辑 --> </xsl:template>
如果需要在公共输出的基础上新增内容,也可以结合<xsl:apply-imports>使用,比如先输出自定义内容再输出公共的年龄字段,无需重写全部逻辑。
方案2:多阶段转换(适合仅修改公共模板的部分输出内容)
如果你不想完全重写公共模板,只想修改公共输出中的部分元素(比如把公共输出的h1改成p),可以用两阶段转换实现:
<xsl:import href="common.xsl" /> <xsl:template match="/"> <!-- 第一阶段:执行公共转换逻辑,将结果存为临时节点树 --> <xsl:variable name="tempResult"> <xsl:apply-templates /> </xsl:variable> <!-- 第二阶段:对临时节点树做二次转换,修改指定内容 --> <xsl:apply-templates select="$tempResult" mode="modify" /> </xsl:template> <!-- 二次转换的默认规则:原样复制所有不需要修改的节点 --> <xsl:template match="@*|node()" mode="modify"> <xsl:copy> <xsl:apply-templates select="@*|node()" mode="modify" /> </xsl:copy> </xsl:template> <!-- 二次转换的自定义规则:修改你要调整的h1元素 --> <xsl:template match="h1" mode="modify"> <p>My name is <xsl:value-of select="." />!</p> </xsl:template>
这个方案完全不需要调整公共样式表,只在当前专用样式表中添加二次转换逻辑即可实现局部修改。
内容的提问来源于stack exchange,提问作者devforweb_17
相关产品推荐
相关产品推荐

