0

0

XSLT如何调用模板?

畫卷琴夢

畫卷琴夢

发布时间:2025-09-10 11:54:01

|

819人浏览过

|

来源于php中文网

原创

XSLT调用模板主要有xsl:apply-templates和xsl:call-template两种方式:前者基于匹配规则自动处理节点,实现数据驱动的递归遍历;后者通过名称直接调用模板,支持参数传递,适用于过程式复用。两者结合可高效构建结构清晰、可维护的转换逻辑。

xslt如何调用模板?

XSLT调用模板主要通过两种核心机制实现:

xsl:apply-templates
xsl:call-template
。前者是基于当前上下文和匹配规则进行处理的,更侧重于数据驱动和递归遍历;后者则是直接按名称调用一个特定的、已定义的模板,更偏向于过程式调用和代码复用

解决方案

在XSLT中,模板调用是其转换逻辑的基石,可以说,没有模板调用,XSLT就失去了灵魂。我们通常有两种主要方式来“激活”这些模板:

1.

xsl:apply-templates
:上下文驱动的魔法

这是XSLT最强大也最常用的模板调用方式。它不是直接指定一个模板的名称,而是告诉XSLT处理器:“去处理当前节点集中的所有子节点(或者你通过

select
属性指定的节点),并为每个节点找到最匹配的模板来执行。”

它的工作机制有点像一个智能的调度员:

  • 当你写下
    时,它会处理当前节点的所有子元素和文本节点。
  • 当你写下
    时,它会处理由XPath表达式选择出来的节点。
  • 对于每一个被选中的节点,XSLT处理器会遍历所有可用的
    规则,找出最“精确”匹配当前节点的那个模板并执行它。这其中涉及到优先级规则,例如一个更具体的XPath匹配会优先于一个更通用的匹配。

我个人觉得,

xsl:apply-templates
的精髓在于它的“拉取(pull)”模型和递归特性。你不需要预先知道所有子节点的具体类型,只需定义好各种节点类型的处理规则,然后让XSLT引擎自己去“拉取”数据并应用相应的规则。这使得处理未知或复杂层级结构的数据变得异常高效和优雅。

示例:

DESTOON B2B网站管理系统
DESTOON B2B网站管理系统

DESTOON B2B网站管理系统是一套完善的B2B(电子商务)行业门户解决方案。系统基于PHP+MySQL开发,采用B/S架构,模板与程序分离,源码开放。模型化的开发思路,可扩展或删除任何功能;创新的缓存技术与数据库设计,可负载千万级别数据容量及访问。

下载

  
    
      

书籍列表

作者:

价格:

2.

xsl:call-template
:按名调用的精确制导

xsl:apply-templates
的“智能调度”不同,
xsl:call-template
是一种非常直接、命令式的调用。你必须明确指定要调用的模板的
name
属性。这种方式通常用于:

  • 当你需要复用一段不依赖特定上下文的通用逻辑时,比如格式化日期、计算某个值。
  • 当你需要从一个模板内部调用另一个模板,并且这个被调用的模板可能没有
    match
    属性(因为它不直接匹配任何输入XML节点,而是作为一个可调用的函数存在)。
  • 当你想传递参数给被调用的模板时。

我通常把

xsl:call-template
看作是传统编程语言中的函数调用。它提供了一种模块化的方式,让我们可以将复杂的转换逻辑分解成更小、更易于管理和复用的单元。

示例:


  
    
       
      

这里是主内容。

我的网站

XSLT中
apply-templates
call-template
有什么区别

这个问题是XSLT初学者经常会遇到的一个“哲学”问题,理解它们之间的差异对于写出高效且可维护的XSLT至关重要。

核心区别在于它们的触发机制上下文处理方式

  • xsl:apply-templates
    (拉取/数据驱动)

    • 触发机制: 它是基于匹配的。你指定一个节点集(通过
      select
      属性或默认当前子节点),XSLT处理器会为这些节点自动寻找并执行最匹配的
      模板。
    • 上下文: 当一个模板被
      apply-templates
      调用时,它的上下文节点会切换到当前正在处理的那个节点。这意味着在被调用的模板内部,你可以直接使用
      .
      来引用该节点,或者使用XPath来导航其子节点或属性。
    • 用途: 主要用于处理XML文档的层次结构和递归遍历。它允许你以一种声明式的方式定义“当遇到这种类型的节点时,就这么处理它”,而无需显式地知道其父节点或子节点的具体情况。这在处理结构相似但内容不同的XML时非常强大。
    • 参数: 也可以通过
      xsl:with-param
      传递参数,但通常不如
      call-template
      那么频繁。
    • 特点: 隐式、自动化、递归、上下文敏感。
  • xsl:call-template
    (推送/过程驱动)

    • 触发机制: 它是基于名称的。你必须明确指定要调用的模板的
      name
      属性。被调用的模板可以是
      ,也可以是带有
      match
      属性但你希望按名称而不是匹配来调用的模板(虽然不常见,但语法上允许)。
    • 上下文: 当一个模板被
      call-template
      调用时,上下文节点通常不会改变,它仍然保留在调用
      call-template
      的那个模板的上下文。当然,你可以通过
      xsl:param
      传递新的上下文节点,但这需要显式操作。
    • 用途: 主要用于实现可重用的“函数”或“子程序”。当你有一段通用的转换逻辑,不依赖于特定的XML节点上下文,并且希望在多个地方调用它时,
      call-template
      是理想选择。例如,格式化日期、生成通用HTML头部或尾部、执行复杂计算等。
    • 参数: 非常适合传递参数,
      xsl:with-param
      是其常用伴侣。
    • 特点: 显式、手动、非递归(除非模板内部再次
      apply-templates
      call-template
      )、上下文相对独立。

我个人经验总结: 如果你的目标是遍历和转换XML文档的结构,让XSLT引擎自己决定如何处理每个节点,那么

xsl:apply-templates
是你的首选。它体现了XSLT的声明式编程思想。如果你的目标是封装一段可重用的、不强依赖于当前XML上下文的逻辑,并且希望像调用函数一样精确控制,那么
xsl:call-template
会更合适。在实际项目中,两者经常会结合使用,
apply-templates
负责结构遍历,
call-template
负责局部功能实现。

如何处理XSLT模板的参数传递?

在XSLT中,参数传递是实现模板复用性和灵活性的关键。无论是

xsl:apply-templates
还是
xsl:call-template
,都可以通过
xsl:with-param
元素来传递参数。

1. 定义参数:

xsl:param

首先,在你要接收参数的模板内部,你需要使用

xsl:param
元素来声明这些参数。
xsl:param
必须是
xsl:template
的直接子元素。

  • name
    属性是必须的,用于指定参数的名称。
  • 你可以选择提供一个默认值,通过
    select
    属性或在
    xsl:param
    标签内部放置内容。如果调用时没有提供该参数,或者提供的值为空,就会使用这个默认值。

示例:


   
   

  
    
      
    
    
      
    
  

2. 传递参数:

xsl:with-param

当你调用模板时(无论是通过

xsl:apply-templates
还是
xsl:call-template
),你可以在其内部使用
xsl:with-param
元素来传递参数。

  • name
    属性是必须的,必须与接收模板中
    xsl:param
    name
    属性匹配。
  • select
    属性用于指定参数的值,可以是一个XPath表达式。
  • 你也可以在
    xsl:with-param
    标签内部放置内容来作为参数的值。

示例 (结合

xsl:call-template
):


  
    
    
      
        
        
      
    

    
    
      
        
      
    

    
    
        
        
    
  

示例 (结合

xsl:apply-templates
):

虽然

apply-templates
通常不直接依赖参数,但在某些高级场景下,你可能希望在处理子节点时,传递一些父节点的信息或全局状态。


  
     
  



   
  

-

需要注意的几点:

  • 参数的作用域仅限于接收它的那个模板。
  • 如果一个参数没有被定义(即没有对应的
    xsl:param
    ),但你尝试通过
    xsl:with-param
    传递它,那么这个参数会被忽略。
  • 参数名是大小写敏感的。
  • xsl:param
    也可以在全局定义(作为
    xsl:stylesheet
    的子元素),这些全局参数可以在任何模板中被访问。全局参数通常用于配置整个转换行为。

我发现,合理使用参数可以极大地提高XSLT代码的模块化和可维护性,避免了重复代码,并使得模板能够处理更广泛的输入场景。

在复杂XSLT转换中,如何有效组织和管理模板?

随着XSLT项目的规模增长,模板数量会迅速增加,如果管理不当,很容易变得混乱和难以维护。有效的组织和管理策略至关重要。我个人在处理大型XSLT项目时,通常会从以下几个方面入手:

1. 模块化:拆分XSLT文件

这是最基本也是最重要的策略。不要把所有模板都塞到一个巨大的XSLT文件中。根据功能或XML结构,将相关的模板分组到单独的

.xsl
文件中。

  • xsl:include
    :简单的文件合并

    • xsl:include
      的作用非常直接:它会将指定XSLT文件的内容原封不动地插入到当前位置。就像C语言的
      #include
      一样,它只是一个文本替换。
    • 被包含的模板和变量与主样式表处于同一优先级和作用域。
    • 通常用于将一些辅助性、非核心的模板(例如,一些通用函数、常量定义)引入到主样式表中。
    • 限制: 如果被包含的文件中包含与主样式表同名的模板或变量,可能会导致冲突或覆盖,因为它没有优先级机制。
  • xsl:import
    :带优先级的模块导入

    • xsl:import
      xsl:include
      更强大,它引入的模板和变量具有较低的导入优先级。这意味着,如果主样式表(或更高优先级的导入)中定义了同名的模板或匹配规则,主样式表的规则会覆盖或优先于导入的规则。
    • 这使得
      xsl:import
      成为构建可扩展、可重写样式表的理想选择。你可以定义一个基础样式表,然后通过导入来扩展它,并在需要时覆盖特定的行为。
    • xsl:import
      元素必须是
      xsl:stylesheet
      的直接子元素,并且必须出现在所有其他顶级元素(如
      xsl:template
      xsl:variable
      等)之前。
    • 用途: 适用于构建库文件、框架或实现样式表继承和覆盖的场景。

我个人建议:

  • 对于通用工具函数、不涉及优先级冲突的辅助模板,使用
    xsl:include
  • 对于核心业务逻辑、需要分层或重写规则的模块,使用
    xsl:import
  • 尽量避免循环导入/包含。

2. 命名规范:清晰且一致

为模板、参数和变量使用一套清晰、一致的命名规范,这对于团队协作和长期维护至关重要。

  • 模板名称: 应该清晰地描述模板的功能,例如
    formatDate
    renderProductCard
    generateHeader
  • 参数/变量: 使用驼峰命名法或下划线命名法,例如
    currentPrice
    isDiscounted

3. 默认模板与模式匹配:利用XSLT的声明性

不要过度使用

xsl:call-template
来模拟过程式编程。XSLT的强大之处在于其基于模式匹配的转换。

  • 充分利用
    xsl:template match="...
    的强大功能,让XSLT处理器自动匹配和应用模板。
  • 理解并利用XSLT的内置模板规则(例如,默认会复制文本节点,并递归处理子节点)。有时,一个节点你不需要显式处理,让内置规则去处理反而更简洁。
  • 使用
    mode
    属性可以为同一个节点定义不同的处理模式,这在需要对相同XML数据进行不同形式的转换时非常有用。

4. 错误处理与调试

在复杂转换中,错误是不可避免的。

  • xsl:message
    在转换过程中输出调试信息,这比你想象的有用。
  • XSLT处理器日志: 熟悉你使用的XSLT处理器(如Saxon、libxslt等)的错误报告和日志功能。
  • 逐步调试工具: 许多IDE(如Oxygen XML Editor、Visual Studio Code的XSLT插件)提供了XSLT的调试功能,可以单步执行、查看变量值和上下文。

5. 注释:适度但有价值

清晰的注释可以帮助你和团队成员理解复杂逻辑。

  • 解释模板的目的、参数的含义、复杂XPath表达式的逻辑。
  • 避免为显而易见的代码添加注释。

通过这些策略的组合使用,即使面对极其复杂的XML转换需求,我也能保持XSLT代码的清晰、可维护和可扩展性。关键在于将大问题拆解成小问题,并充分利用XSLT语言本身的特性来解决它们。

相关专题

更多
C语言变量命名
C语言变量命名

c语言变量名规则是:1、变量名以英文字母开头;2、变量名中的字母是区分大小写的;3、变量名不能是关键字;4、变量名中不能包含空格、标点符号和类型说明符。php中文网还提供c语言变量的相关下载、相关课程等内容,供大家免费下载使用。

389

2023.06.20

c语言入门自学零基础
c语言入门自学零基础

C语言是当代人学习及生活中的必备基础知识,应用十分广泛,本专题为大家c语言入门自学零基础的相关文章,以及相关课程,感兴趣的朋友千万不要错过了。

613

2023.07.25

c语言运算符的优先级顺序
c语言运算符的优先级顺序

c语言运算符的优先级顺序是括号运算符 > 一元运算符 > 算术运算符 > 移位运算符 > 关系运算符 > 位运算符 > 逻辑运算符 > 赋值运算符 > 逗号运算符。本专题为大家提供c语言运算符相关的各种文章、以及下载和课程。

353

2023.08.02

c语言数据结构
c语言数据结构

数据结构是指将数据按照一定的方式组织和存储的方法。它是计算机科学中的重要概念,用来描述和解决实际问题中的数据组织和处理问题。数据结构可以分为线性结构和非线性结构。线性结构包括数组、链表、堆栈和队列等,而非线性结构包括树和图等。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

256

2023.08.09

c语言random函数用法
c语言random函数用法

c语言random函数用法:1、random.random,随机生成(0,1)之间的浮点数;2、random.randint,随机生成在范围之内的整数,两个参数分别表示上限和下限;3、random.randrange,在指定范围内,按指定基数递增的集合中获得一个随机数;4、random.choice,从序列中随机抽选一个数;5、random.shuffle,随机排序。

597

2023.09.05

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

524

2023.09.20

c语言get函数的用法
c语言get函数的用法

get函数是一个用于从输入流中获取字符的函数。可以从键盘、文件或其他输入设备中读取字符,并将其存储在指定的变量中。本文介绍了get函数的用法以及一些相关的注意事项。希望这篇文章能够帮助你更好地理解和使用get函数 。

639

2023.09.20

c数组初始化的方法
c数组初始化的方法

c语言数组初始化的方法有直接赋值法、不完全初始化法、省略数组长度法和二维数组初始化法。详细介绍:1、直接赋值法,这种方法可以直接将数组的值进行初始化;2、不完全初始化法,。这种方法可以在一定程度上节省内存空间;3、省略数组长度法,这种方法可以让编译器自动计算数组的长度;4、二维数组初始化法等等。

599

2023.09.22

高德地图升级方法汇总
高德地图升级方法汇总

本专题整合了高德地图升级相关教程,阅读专题下面的文章了解更多详细内容。

43

2026.01.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
XSLT参考手册
XSLT参考手册

共0课时 | 0人学习

XSLT 教程
XSLT 教程

共20课时 | 8.5万人学习

XPath 教程
XPath 教程

共9课时 | 3.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号