xsl:key 和 key() 是 XSLT 中基于预建索引的高效查找机制;需在顶层声明键规则,用 key() 按值快速检索节点集,支持主从关联、分组及跨文档引用,但键值区分大小写且 use 不支持变量。

xsl:key 和 key() 是 XSLT 中实现高效查找的核心机制,本质是“预建索引 + 快速检索”,不是实时遍历。用对了,性能提升明显,尤其处理大文档或重复查找时。
定义索引:用 xsl:key 声明键规则
必须放在顶层(即 或 内,不能在模板里),声明“按什么字段、在哪些节点上建立索引”。
语法:
说明:
-
name:键名,后续
key()函数靠它调用,必须唯一且合法 QName -
match:匹配哪些节点参与索引(这里是所有
元素) -
use:提取索引值的表达式(这里取
@isbn属性值;支持任意 XPath 表达式,如concat(@category, '-', @year))
注意:use 表达式结果会被自动字符串化,多个节点若计算出相同字符串,就归入同一个键值桶中(支持一对多)。
执行查找:用 key() 函数按值取节点集
key($key-name, $lookup-value, $node-set?)
最常用两参数形式:key('book-by-isbn', '978-0-13-468599-1')
说明:
- 第一个参数是
xsl:key的name(字符串字面量或变量) - 第二个参数是你要查的值(字符串;会自动转为字符串,所以
key('k', 123)等价于key('k', '123')) - 第三个参数可选,指定搜索范围(默认是当前上下文节点的整个文档;设为
$some-node则只查该子树)
返回值:匹配的节点集合(顺序与源文档中出现顺序一致,未排序)。
典型高效用法场景
避免嵌套循环,把“找关联数据”变成 O(1) 查表操作:
-
主从关联(如订单+订单项):用订单号建索引,每个订单模板里直接
key('items-by-order-id', @id)拿对应项 -
去重/分组(Muenchian 方法):配合
generate-id()实现 XSLT 1.0 分组(key('by-cat', @category)[1]找每组首个) -
跨文档引用(需配合 document()):先用
document('lookup.xml')加载外部数据,再对它定义xsl:key,然后key('ext-k', $val, document('lookup.xml'))
常见坑和注意点
-
xsl:key只对当前正在处理的文档生效(即key()默认查的是主输入文档);查其他文档要显式传第三个参数 - 键值区分大小写,且前后空格不自动 trim(
' ABC '≠'ABC'),建议normalize-space(@id)或translate()预处理 - 不能在
xsl:key的use中用变量(XSLT 1.0/2.0 均不支持动态键值);如需多条件,拼接字符串或用多个 key - 调试时可用
验证是否命中Found:
基本上就这些。用熟了,你会发现很多看似要双重 for-each 的地方,一个 key 就搞定。










