XSLT模板重写通过xsl:import和xsl:apply-imports实现,导入样式表的模板优先级高于被导入的样式表,从而允许覆盖或扩展基础模板;xsl:apply-imports可在重写模板中调用原模板逻辑,实现增量定制;结合导入优先级、模式匹配、特异性和文档顺序,可构建模块化、可维护的分层样式表结构,平衡重用与定制需求。
XSLT实现模板重写,核心机制在于
xsl:import
xsl:apply-imports
要实现XSLT模板的重写,我们通常会用到两个关键指令:
xsl:import
xsl:apply-imports
首先,
xsl:import
例如,我们有一个基础样式表
base.xsl
<!-- base.xsl --> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="item"> <div class="base-item"> <xsl:value-of select="."/> </div> </xsl:template> <xsl:template match="root"> <div class="base-root"> <xsl:apply-templates/> </div> </xsl:template> </xsl:stylesheet>
现在,我们想在另一个样式表
override.xsl
item
<!-- override.xsl --> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 导入 base.xsl,使其模板规则成为当前样式表的“基础” --> <xsl:import href="base.xsl"/> <!-- 重写 item 模板 --> <xsl:template match="item"> <div class="overridden-item"> <!-- 这里是关键:xsl:apply-imports 会调用被导入样式表中匹配当前节点的模板 --> <!-- 也就是说,它会执行 base.xsl 中对 item 的处理逻辑 --> <xsl:apply-imports/> <p>This item was customized!</p> </div> </xsl:template> <!-- 如果你想完全替换,可以不使用 xsl:apply-imports --> <!-- <xsl:template match="item"> <span class="completely-new-item"> <xsl:value-of select="concat('NEW: ', .)"/> </span> </xsl:template> --> <!-- root 模板没有被重写,它会使用 base.xsl 中的定义 --> <xsl:template match="root"> <section class="custom-section"> <h3>Custom Header</h3> <xsl:apply-templates/> <footer>Custom Footer</footer> </section> </xsl:template> </xsl:stylesheet>
对应的XML输入可能是:
<!-- input.xml --> <root> <item>Apple</item> <item>Banana</item> </root>
当你用
override.xsl
input.xml
root
override.xsl
xsl:apply-templates
item
item
override.xsl
xsl:apply-imports
base.xsl
item
override.xsl
base.xsl
xsl:import
xsl:import
具体来说,当一个样式表通过
xsl:import
除了导入优先级,XSLT处理器还会考虑其他两个重要因素:
mode
xsl:apply-templates
xsl:call-template
mode
match
match="element"
match="root/element"
match="element[@id='foo']"
match="element"
当XSLT处理器遇到一个XML节点,并且有多个模板都能匹配它时,它会按照以下顺序来决定哪个模板被应用:
xsl:priority
xsl:priority
所以,通过
xsl:import
xsl:apply-imports
xsl:apply-imports
想象一下,你有一个基础模板,它负责生成一个HTML元素的骨架。现在,你希望在不改变骨架的前提下,往里面添加一些特定的内容,或者在骨架生成前后执行一些额外的逻辑。这时候,
xsl:apply-imports
当你在一个重写模板内部使用
xsl:apply-imports
xsl:apply-imports
举个例子,假设
base.xsl
product
<!-- base.xsl --> <xsl:template match="product"> <div class="product-card"> <h3><xsl:value-of select="name"/></h3> </div> </xsl:template>
现在,在
override.xsl
div.product-card
<!-- override.xsl --> <xsl:import href="base.xsl"/> <xsl:template match="product"> <xsl:apply-imports/> <!-- 这会先执行 base.xsl 中 product 模板的内容 --> <p>Price: <xsl:value-of select="price"/></p> <p><xsl:value-of select="description"/></p> </xsl:template>
如果
input.xml
<products> <product> <name>Laptop</name> <price>$1200</price> <description>Powerful and portable.</description> </product> </products>
最终输出会是:
<div class="product-card"> <h3>Laptop</h3> </div> <p>Price: $1200</p> <p>Powerful and portable.</p>
这里你会发现,
xsl:apply-imports
base.xsl
override.xsl
product
override.xsl
base.xsl
在大型或复杂的XSLT项目中,平衡模板的重用性和定制化需求,确实是一个需要深思熟虑的设计挑战。如果过度追求重用,可能会导致模板过于通用,难以满足特定场景的细微差别;反之,过度定制又容易造成代码冗余,难以维护。我个人的经验是,这需要一套清晰的模块化策略,并且要善用XSLT提供的各种工具。
这里有几个关键的策略和思考点:
建立清晰的基础层和扩展层:
xsl:import
利用 xsl:import
main.xsl
customer_a.xsl
customer_a.xsl
base.xsl
main.xsl
customer_a.xsl
customer_a.xsl
base.xsl
善用 xsl:apply-imports
xsl:apply-imports
合理使用模式(xsl:mode
xsl:mode
match
mode
xsl:apply-templates select="..." mode="myMode"
命名模板(xsl:call-template
xsl:param
清晰的文档和命名规范:
平衡重用和定制,本质上是在寻找一个“恰到好处”的抽象层次。这往往需要一些经验,甚至在项目迭代过程中进行调整。关键在于,当你发现代码开始重复时,考虑提取通用逻辑;当你发现通用逻辑难以满足特定需求时,考虑如何通过
xsl:import
xsl:apply-imports
以上就是XSLT如何实现模板重写?的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 //m.sbmmt.com/ All Rights Reserved | php.cn | 湘ICP备2023035733号