XSLT中的xsl:for-each和xsl:apply-templates有什么区别,应该如何选择使用?

xsl:for-each 是显式循环,xsl:apply-templates 是声明式匹配;前者按 XPath 拉取节点硬循环,后者依模板规则自动分发处理,适用场景分别侧重简单遍历与结构保持、复用及递归转换。

xsl:for-each 是显式循环,xsl:apply-templates 是声明式匹配——前者“我来控制怎么遍历”,后者“你按规则自己找节点处理”。选哪个,关键看你要不要保留XML的结构逻辑和模板复用能力。

作用机制不同

直接切换当前上下文节点,每次迭代都把 select 指定的节点依次设为 context node,里面只能访问该节点及其后代。它不关心节点类型、不触发模板匹配,纯靠 XPath 拉出一组节点硬循环。

不指定具体节点,而是让处理器根据当前节点(或子节点)自动查找所有已定义的

适用场景对比

当你需要:

  • 快速输出同级节点的简单列表(比如所有 的标题)
  • 配合 position()、last() 做序号、分页、奇偶样式等位置敏感操作
  • 在排序后立即渲染( 必须嵌在 for-each 内部)
  • XSLT 1.0 环境下做简单分组前筛选(如 book[position()

用 当你需要:

  • 保持 XML 原始结构语义(比如 下有
    ,要分别用不同模板处理)
  • 复用模板(同一 match 规则可在多处 apply,避免重复写逻辑)
  • 支持默认模板行为(没写 match 的节点也能被合理处理)
  • 做深度嵌套转换(如递归处理树形菜单、嵌套的

一个典型区别示例

假设 XML 里有 两种元素:

– 用 for-each: 只能统一输出,无法区分二者格式;

– 用 apply-templates: 配合两个独立模板:,样式和逻辑完全解耦。

进阶建议

初学者常误以为 for-each 更“直观”,但长期维护中 apply-templates 更健壮:

  • 新增一种节点类型?加个 template 就行,不用改所有 for-each
  • 想跳过某类节点?用 空模板即可,无需在每个循环里加 if
  • XSLT 2.0+ 的 for-each-group、current-group() 等高级功能虽强,仍建议先用 apply-templates 搭骨架,再局部嵌入 for-each 做细节控制

基本上就这些。