请求编写XSLT解析含多层嵌套数组的JSON转XML文件
XSLT解析多层嵌套数组XML解决方案(支持1.0-3.0)
问题背景
需编写兼容XSLT 1.0至3.0的解析器,处理由JSON转换而来的含多层嵌套数组的XML文件,当前实现仅能获取数组首个元素,无法遍历后续元素,需生成指定格式的两个输出Payload。
源XML示例
<!-- JSON转XML后的典型嵌套数组结构 --> <root> <data> <array1> <item> <id>1</id> <name>Item 1</name> <subarray> <subitem> <sid>1-1</sid> <sname>Subitem 1-1</sname> </subitem> <subitem> <sid>1-2</sid> <sname>Subitem 1-2</sname> </subitem> </subarray> </item> <item> <id>2</id> <name>Item 2</name> <subarray> <subitem> <sid>2-1</sid> <sname>Subitem 2-1</sname> </subitem> </subarray> </item> </array1> </data> </root>
期望输出Payload示例
输出Payload 1(扁平化结构)
[ {"id": "1", "name": "Item 1", "sid": "1-1", "sname": "Subitem 1-1"}, {"id": "1", "name": "Item 1", "sid": "1-2", "sname": "Subitem 1-2"}, {"id": "2", "name": "Item 2", "sid": "2-1", "sname": "Subitem 2-1"} ]
输出Payload 2(保留嵌套结构)
[ { "id": "1", "name": "Item 1", "subitems": [ {"sid": "1-1", "sname": "Subitem 1-1"}, {"sid": "1-2", "sname": "Subitem 1-2"} ] }, { "id": "2", "name": "Item 2", "subitems": [ {"sid": "2-1", "sname": "Subitem 2-1"} ] } ]
解决方案
核心问题分析
之前仅能获取首个元素,通常是因为未对数组节点(如<item>、<subitem>)做遍历处理,或错误使用了[1]这类索引限制了节点选择范围。
1. 兼容XSLT 1.0的实现
使用xsl:for-each或xsl:apply-templates遍历数组节点,手动拼接输出内容:
生成Payload 1的XSLT代码
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text" encoding="UTF-8"/> <xsl:template match="/"> <xsl:text>[</xsl:text> <xsl:apply-templates select="/root/data/array1/item/subarray/subitem"/> <xsl:text>]</xsl:text> </xsl:template> <xsl:template match="subitem"> <xsl:text>{"id": "</xsl:text> <xsl:value-of select="../../id"/> <xsl:text>", "name": "</xsl:text> <xsl:value-of select="../../name"/> <xsl:text>", "sid": "</xsl:text> <xsl:value-of select="sid"/> <xsl:text>", "sname": "</xsl:text> <xsl:value-of select="sname"/> <xsl:text>}</xsl:text> <xsl:if test="position() != last()">,</xsl:if> </xsl:template> </xsl:stylesheet>
生成Payload 2的XSLT代码
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text" encoding="UTF-8"/> <xsl:template match="/"> <xsl:text>[</xsl:text> <xsl:apply-templates select="/root/data/array1/item"/> <xsl:text>]</xsl:text> </xsl:template> <xsl:template match="item"> <xsl:text>{"id": "</xsl:text> <xsl:value-of select="id"/> <xsl:text>", "name": "</xsl:text> <xsl:value-of select="name"/> <xsl:text>", "subitems": [</xsl:text> <xsl:apply-templates select="subarray/subitem"/> <xsl:text>]</xsl:text> <xsl:if test="position() != last()">,</xsl:if> </xsl:template> <xsl:template match="subitem"> <xsl:text>{"sid": "</xsl:text> <xsl:value-of select="sid"/> <xsl:text>", "sname": "</xsl:text> <xsl:value-of select="sname"/> <xsl:text>}</xsl:text> <xsl:if test="position() != last()">,</xsl:if> </xsl:template> </xsl:stylesheet>
2. XSLT 3.0简化实现
利用XSLT 3.0原生的JSON输出、map和array功能,无需手动拼接字符串:
生成Payload 1的XSLT代码
<xsl:stylesheet version="3.0" 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"> <xsl:output method="json" encoding="UTF-8"/> <xsl:template match="/"> <xsl:sequence select="array{ for $item in /root/data/array1/item, $subitem in $item/subarray/subitem return map{ 'id': string($item/id), 'name': string($item/name), 'sid': string($subitem/sid), 'sname': string($subitem/sname) } }"/> </xsl:template> </xsl:stylesheet>
生成Payload 2的XSLT代码
<xsl:stylesheet version="3.0" 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"> <xsl:output method="json" encoding="UTF-8"/> <xsl:template match="/"> <xsl:sequence select="array{ for $item in /root/data/array1/item return map{ 'id': string($item/id), 'name': string($item/name), 'subitems': array{ for $subitem in $item/subarray/subitem return map{ 'sid': string($subitem/sid), 'sname': string($subitem/sname) } } } }"/> </xsl:template> </xsl:stylesheet>
关键说明
- 需根据实际XML结构调整XPath节点路径,确保选中所有数组元素节点,避免使用
[1]索引限制遍历范围。 - XSLT 3.0的
json输出方法可直接生成标准JSON,减少手动拼接的出错概率。 - 若源XML中数组节点命名不同(如
<element>而非<item>),替换对应节点名即可适配。
内容的提问来源于stack exchange,提问作者mangola2023
相关产品推荐
相关产品推荐

