map() 和 array() 是 xpath 3.1/xslt 3.0 的原生数据类型构造器函数,非高阶映射操作;需用 map:merge()、array:for-each() 等命名空间函数实现合并与转换,且必须声明命名空间并设 version="3.1"。

map() 函数在 XSLT 3.0 中不是内置函数
直接说结论:map() 和 array() 是 XPath 3.1 / XSLT 3.0 的**原生数据类型构造器函数**,但它们**不是“遍历处理”意义上的 map(像 JavaScript 的 Array.prototype.map)**。你在 XSLT 里不能用 map($items, function($x) { $x * 2 }) 这种语法——XSLT 没有高阶函数式映射操作符。
真正可用的是:
-
map { "key1": "val1", "key2": 42 }—— 字面量构造 map -
array { 1, 2, 3 }—— 字面量构造 array -
map:merge( (map { "a": 1 }, map { "b": 2 }) )—— 来自map命名空间的实用函数(需声明xmlns:map="http://www.w3.org/2005/xpath-functions/map") -
array:for-each($arr, function($x) { $x + 1 })—— 注意:这是array:for-each,不是map();它返回新 array,行为接近 map,但函数名固定
怎么安全创建和访问 map/array?
XSLT 3.0 支持 map 和 array 类型,但必须确保处理器支持(如 Saxon HE 10+、Saxon PE/EE、BaseX 10+),且启用 XPath 3.1 模式(version="3.1")。
常见写法示例:
<stylesheet version="3.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:map="http://www.w3.org/2005/xpath-functions/map" xmlns:array="http://www.w3.org/2005/xpath-functions/array"><p><template match="/"><!-- 构造一个 map --><variable name="user" as="map(*)" select="map { 'name': 'Alice', 'age': 30, 'active': true() }"></variable></template></p>
<pre class="brush:php;toolbar:false;"><!-- 访问 key -->
<xsl:value-of select="$user?name"/> <!-- → Alice -->
<!-- 构造 array -->
<xsl:variable name="scores" as="array(*)"
select="array { 85, 92, 78 }"/>
<!-- 取第 2 个元素(索引从 1 开始!)-->
<xsl:value-of select="$scores?2"/> <!-- → 92 -->
<!-- 用 array:for-each 实现类似 map 的转换 -->
<xsl:variable name="doubled" as="array(*)"
select="array:for-each($scores, function($x) { $x * 2 })"/>
常见报错和坑点
以下错误几乎都源于类型或命名空间缺失:
-
XPST0003或XPDY0002:未声明xmlns:map/xmlns:array,或 XSLT 版本不是3.1 -
XPTY0004:对非 map 变量使用?key语法(比如变量类型是xs:string却写$x?name) -
FORG0006:用?0或负数索引访问 array(XPath array 索引从 1 开始) - 空 map/array 被误判为
():注意map {} eq ()是false();要用map:size($m) = 0判空
替代方案:什么时候该用 XSLT 3.0 map/array?
它们适合做「结构化中间数据」,而非通用循环工具。真实场景中更常用:
- 把 XML 节点集转成 map 做快速查找(比如 ID → 元素映射)
- 用
array:for-each+array:filter处理分组后的一维结果(比嵌套xsl:for-each更紧凑) - 配合
xsl:iterate实现状态累积(例如计数、拼接字符串) - 避免频繁调用
key()或//—— 预建 map 查表更快
如果你只是想“对每个节点执行一个函数”,老老实实用 xsl:for-each 或 xsl:iterate 更稳;map/array 的价值在于表达「键值关系」和「有序集合语义」,不是语法糖。










