如何在XSLT 3.0中遍历JSON数组并解决转换报错问题
解决XSLT遍历JSON转换时的序列与重复键错误
问题场景
需要用XSLT将输入JSON转换为指定结构的输出JSON,尝试<xsl:for-each>时出现错误:JSON output method cannot handle sequences of two or more items;改用嵌套map后又出现:Duplicate key in constructed map: {resourceType}.
输入JSON
{ "members": [ { "name": "Molecule Man", "age": "29", "secretIdentity": "Dan Jukes" }, { "name": "Iron Man", "age": "30", "secretIdentity": "Martin" } ] }
期望输出JSON
[ { "resourceType": "Test", "type": { "name": "Member" }, "displayName": "Molecule Man", "attributes": { "test": [ { "value": "29" } ], "testing": [ { "value": "Dan Jukes" } ] } }, { "resourceType": "Test", "type": { "name": "Member" }, "displayName": "Iron Man", "attributes": { "test": [ { "value": "30" } ], "testing": [ { "value": "Martin" } ] } } ]
错误原因分析
- 序列输出错误:JSON输出方法要求顶层必须是单个JSON值(对象或数组),原代码用
<xsl:for-each>直接输出多个独立map,形成了map序列,不符合要求。 - 重复键错误:原代码在
<xsl:map-entry key="'type'">内部直接嵌套<xsl:map-entry>,没有将内层键包裹在独立的<xsl:map>中,导致外层map同时包含resourceType和name键,触发重复键报错。
修正后的XSLT代码
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="#all"> <xsl:param name="nodes" as="map(*)*"/> <xsl:template name="init"> <!-- 将遍历后的map序列包裹为数组,满足JSON输出要求 --> <xsl:sequence select="array { $nodes?members?* ! map { 'resourceType' : 'Test', 'type' : map { 'name' : 'Member' }, 'displayName' : ?name, 'attributes' : map { 'test' : array { map { 'value' : ?age } }, 'testing' : array { map { 'value' : ?secretIdentity } } } } }"/> </xsl:template> <xsl:output method="json" indent="yes"/> </xsl:stylesheet>
代码说明
- 用数组构造语法
array { ... }将所有转换后的map包裹成一个顶层数组,解决序列输出不符合JSON规范的问题。 - 使用XPath 3.0的
!操作符遍历members数组元素,每个元素直接转换为目标map,替代<xsl:for-each>避免序列输出问题。 - 所有嵌套结构(
type、attributes)都明确用map { ... }构造,确保键的归属正确,避免重复键错误。 - 保留原代码的
$nodes参数,适配原有输入方式;若输入是JSON字符串,可添加json-to-xml($input) => xml-to-json(map { 'mode' : 'map' })步骤完成解析。
内容的提问来源于stack exchange,提问作者Ram Prasad
相关产品推荐
相关产品推荐

