XSLT调用模板主要有xsl:apply-templates和xsl:call-template两种方式:前者基于匹配规则自动处理节点,实现数据驱动的递归遍历;后者通过名称直接调用模板,支持参数传递,适用于过程式复用。两者结合可高效构建结构清晰、可维护的转换逻辑。
XSLT调用模板主要通过两种核心机制实现:
和
。前者是基于当前上下文和匹配规则进行处理的,更侧重于数据驱动和递归遍历;后者则是直接按名称调用一个特定的、已定义的模板,更偏向于过程式调用和
代码复用
。
解决方案
在XSLT中,模板调用是其转换逻辑的基石,可以说,没有模板调用,XSLT就失去了灵魂。我们通常有两种主要方式来“激活”这些模板:
1.:上下文驱动的魔法
这是XSLT最强大也最常用的模板调用方式。它不是直接指定一个模板的名称,而是告诉XSLT
处理器
:“去处理当前节点集中的所有子节点(或者你通过
属性指定的节点),并为每个节点找到最匹配的模板来执行。”
它的工作机制有点像一个智能的调度员:
当你写下
时,它会处理当前节点的所有子元素和文本节点。
当你写下
时,它会处理由XPath表达式选择出来的节点。
对于每一个被选中的节点,XSLT处理器会遍历所有可用的
规则,找出最“精确”匹配当前节点的那个模板并执行它。这其中涉及到优先级规则,例如一个更具体的XPath匹配会优先于一个更通用的匹配。
我个人觉得,
的精髓在于它的“拉取(pull)”模型和递归特性。你不需要预先知道所有子节点的具体类型,只需定义好各种节点类型的处理规则,然后让XSLT引擎自己去“拉取”数据并应用相应的规则。这使得处理未知或复杂层级结构的数据变得异常高效和优雅。
示例:
2.:按名调用的精确制导
与
的“智能调度”不同,
是一种非常直接、命令式的调用。你必须明确指定要调用的模板的
属性。这种方式通常用于:
当你需要复用一段不依赖特定上下文的通用逻辑时,比如格式化日期、计算某个值。
当你需要从一个模板内部调用另一个模板,并且这个被调用的模板可能没有
属性(因为它不直接匹配任何输入XML节点,而是作为一个可调用的函数存在)。
当你想传递参数给被调用的模板时。
我通常把
看作是传统
编程语言
中的函数调用。它提供了一种模块化的方式,让我们可以将复杂的转换逻辑分解成更小、更易于管理和复用的单元。
示例:
XSLT中
和
有什么区别?
这个问题是XSLT初学者经常会遇到的一个“哲学”问题,理解它们之间的差异对于写出高效且可维护的XSLT至关重要。
核心区别在于它们的
触发机制
和
上下文处理方式
:
(拉取/数据驱动)
触发机制:
它是
基于匹配
的。你指定一个节点集(通过
属性或默认当前子节点),XSLT处理器会为这些节点自动寻找并执行最匹配的
模板。
上下文:
当一个模板被
调用时,它的
上下文节点会切换到当前正在处理的那个节点
。这意味着在被调用的模板内部,你可以直接使用
来引用该节点,或者使用XPath来导航其子节点或属性。
用途:
主要用于处理XML文档的层次结构和递归遍历。它允许你以一种声明式的方式定义“当遇到这种类型的节点时,就这么处理它”,而无需显式地知道其父节点或子节点的具体情况。这在处理结构相似但内容不同的XML时非常强大。
参数:
也可以通过
传递参数,但通常不如
那么频繁。
特点:
隐式、自动化、递归、上下文敏感。
(推送/过程驱动)
触发机制:
它是
基于名称
的。你必须明确指定要调用的模板的
属性。被调用的模板可以是
,也可以是带有
属性但你希望按名称而不是匹配来调用的模板(虽然不常见,但语法上允许)。
上下文:
当一个模板被
调用时,
上下文节点通常不会改变
,它仍然保留在调用
的那个模板的上下文。当然,你可以通过
传递新的上下文节点,但这需要显式操作。
用途:
主要用于实现可重用的“函数”或“子程序”。当你有一段通用的转换逻辑,不依赖于特定的XML节点上下文,并且希望在多个地方调用它时,
是理想选择。例如,格式化日期、生成通用HTML头部或尾部、执行复杂计算等。
参数:
非常适合传递参数,
是其常用伴侣。
特点:
显式、手动、非递归(除非模板内部再次
或
)、上下文相对独立。
我个人经验总结:
如果你的目标是遍历和转换XML文档的结构,让XSLT引擎自己决定如何处理每个节点,那么
是你的首选。它体现了XSLT的声明式编程思想。如果你的目标是封装一段可重用的、不强依赖于当前XML上下文的逻辑,并且希望像调用函数一样精确控制,那么
会更合适。在实际项目中,两者经常会结合使用,
负责结构遍历,
负责局部功能实现。
如何处理XSLT模板的参数传递?
在XSLT中,参数传递是实现模板复用性和灵活性的关键。无论是
还是
,都可以通过
元素来传递参数。
1. 定义参数:
首先,在你要接收参数的模板内部,你需要使用
元素来声明这些参数。
必须是
的直接子元素。
属性是必须的,用于指定参数的名称。
你可以选择提供一个默认值,通过
属性或在
标签内部放置内容。如果调用时没有提供该参数,或者提供的值为空,就会使用这个默认值。
示例:
2. 传递参数:
当你调用模板时(无论是通过
还是
),你可以在其内部使用
元素来传递参数。
使用HTML,CSS,JavaScript开发Android应用程序 英文文字pdf版附源文件
如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Android友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Android应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更
下载
属性是必须的,必须与接收模板中
的
属性匹配。
属性用于指定参数的值,可以是一个XPath表达式。
你也可以在
标签内部放置内容来作为参数的值。
示例 (结合):
示例 (结合):
虽然
通常不直接依赖参数,但在某些高级场景下,你可能希望在处理子节点时,传递一些父节点的信息或全局状态。
需要注意的几点:
参数的
作用域
仅限于接收它的那个模板。
如果一个参数没有被定义(即没有对应的
),但你尝试通过
传递它,那么这个参数会被忽略。
参数名是大小写敏感的。
也可以在全局定义(作为
的子元素),这些全局参数可以在任何模板中被访问。全局参数通常用于配置整个转换行为。
我发现,合理使用参数可以极大地提高XSLT代码的模块化和可维护性,避免了重复代码,并使得模板能够处理更广泛的输入场景。
在复杂XSLT转换中,如何有效组织和管理模板?
随着XSLT项目的规模增长,模板数量会迅速增加,如果管理不当,很容易变得混乱和难以维护。有效的组织和管理策略至关重要。我个人在处理大型XSLT项目时,通常会从以下几个方面入手:
1. 模块化:拆分XSLT文件
这是最基本也是最重要的策略。不要把所有模板都塞到一个巨大的XSLT文件中。根据功能或XML结构,将相关的模板分组到单独的
文件中。
:简单的文件合并
的作用非常直接:它会将指定XSLT文件的内容
原封不动地
插入到当前位置。就像C语言的
一样,它只是一个文本替换。
被包含的模板和变量与主样式表处于同一优先级和作用域。
通常用于将一些辅助性、非核心的模板(例如,一些通用函数、常量定义)引入到主样式表中。
限制:
如果被包含的文件中包含与主样式表同名的模板或变量,可能会导致冲突或覆盖,因为它没有优先级机制。
:带优先级的模块导入
比
更强大,它引入的模板和变量具有
较低的导入优先级
。这意味着,如果主样式表(或更高优先级的导入)中定义了同名的模板或匹配规则,主样式表的规则会覆盖或优先于导入的规则。
这使得
成为构建可扩展、可重写样式表的理想选择。你可以定义一个基础样式表,然后通过导入来扩展它,并在需要时覆盖特定的行为。
元素必须是
的直接子元素,并且必须出现在所有其他顶级元素(如
、
等)之前。
用途:
适用于构建库文件、框架或实现样式表继承和覆盖的场景。
我个人建议:
对于通用工具函数、不涉及优先级冲突的辅助模板,使用
。
对于核心业务逻辑、需要分层或重写规则的模块,使用
。
尽量避免循环导入/包含。
2. 命名规范:清晰且一致
为模板、参数和变量使用一套清晰、一致的命名规范,这对于团队协作和长期维护至关重要。
模板名称:
应该清晰地描述模板的功能,例如
、
、
。
参数/变量:
使用驼峰命名法或下划线命名法,例如
、
。
3. 默认模板与模式匹配:利用XSLT的声明性
不要过度使用
来模拟过程式编程。XSLT的强大之处在于其基于模式匹配的转换。
充分利用
的强大功能,让XSLT处理器自动匹配和应用模板。
理解并利用XSLT的
内置模板规则
(例如,默认会复制文本节点,并递归处理子节点)。有时,一个节点你不需要显式处理,让内置规则去处理反而更简洁。
使用
属性可以为同一个节点定义不同的处理模式,这在需要对相同XML数据进行不同形式的转换时非常有用。
4. 错误处理与调试
在复杂转换中,错误是不可避免的。
:
在转换过程中输出调试信息,这比你想象的有用。
XSLT处理器日志:
熟悉你使用的XSLT处理器(如Saxon、libxslt等)的错误报告和日志功能。
逐步调试工具:
许多IDE(如Oxygen XML Editor、Visual Studio Code的XSLT插件)提供了XSLT的调试功能,可以单步执行、查看变量值和上下文。
5. 注释:适度但有价值
清晰的注释可以帮助你和团队成员理解复杂逻辑。
解释模板的目的、参数的含义、复杂XPath表达式的逻辑。
避免为显而易见的代码添加注释。
通过这些策略的组合使用,即使面对极其复杂的XML转换需求,我也能保持XSLT代码的清晰、可维护和可扩展性。关键在于将大问题拆解成小问题,并充分利用XSLT语言本身的特性来解决它们。
xsl:apply-templatesxsl:call-templatexsl:apply-templatesselectxsl:apply-templates
书籍列表
作者:
价格:
xsl:call-templatexsl:apply-templatesxsl:call-templatenamematchxsl:call-template
这里是主内容。
我的网站
apply-templatescall-templatexsl:apply-templatesselectapply-templates.xsl:with-paramcall-templatexsl:call-templatenamematchcall-templatecall-templatexsl:paramcall-templatexsl:with-paramapply-templatescall-templatexsl:apply-templatesxsl:call-templateapply-templatescall-templatexsl:apply-templatesxsl:call-templatexsl:with-paramxsl:paramxsl:paramxsl:paramxsl:templatenameselectxsl:param
xsl:with-paramxsl:apply-templatesxsl:call-templatexsl:with-paramnamexsl:paramnameselectxsl:with-paramxsl:call-template
xsl:apply-templatesapply-templates
-
xsl:paramxsl:with-paramxsl:paramxsl:stylesheet.xslxsl:includexsl:include#includexsl:importxsl:importxsl:includexsl:importxsl:importxsl:stylesheetxsl:templatexsl:variablexsl:includexsl:importformatDaterenderProductCardgenerateHeadercurrentPriceisDiscountedxsl:call-templatexsl:template match="...modexsl:message