求助:使用XSLT 3将外部JSON转换为XML的实现问题
XSLT 3.0 转换JSON数组为指定XML格式失败求助
我已在Stack Overflow查阅过相关帖子,包括《使用XSLT将JSON数组转换为XML》《使用XSLT 3.0函数将JSON转换为XML》,但现有方案与我的需求存在差异,未找到适配的解决办法。
转换调用命令
java -jar SaxonHE/saxon-he-11.4.jar -s:not_used.xml -xsl:rework_map.xsl -o:report-map.xml p1="list.json"
输入JSON文件(list.json)
[ { "tc_id": "A_S_0001", "file_name": "\\scripts\\A_S_0001.cs", "version": "19", "is_automated": true }, { "tc_id": "A_S_0002", "file_name": "\\scripts\\A_S_0002.cs", "version": "25", "is_automated": false } ]
期望输出XML
<list> <test_case> <tc_id>A_S_0001</tc_id> <file_name>\\scripts\\A_S_0001.cs</file_name> <version>19</version> <is_automated>true</is_automated> </test_case> <test_case> <tc_id>A_S_0002</tc_id> <file_name>\\scripts\\A_S_0002.cs</file_name> <version>25</version> <is_automated>false</is_automated> </test_case> </list>
现有无效XSLT代码(rework_map.xsl)
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:math="http://www.w3.org/2005/xpath-functions/math" xmlns:map="http://www.w3.org/2005/xpath-functions/map" xmlns:array="http://www.w3.org/2005/xpath-functions/array" exclude-result-prefixes="xs math map array fn" version="3.0"> <!-- OUTPUT --> <xsl:output method="xml" indent="yes"/> <!-- PARAMETERS --> <xsl:param name="p1"></xsl:param> <!-- list.json --> <!-- VARIABLES --> <xsl:variable name="json-array" select="json-doc($p1)"/> <xsl:template match="/"> <!-- <xsl:call-template name="common.INFO"/> --> <list> <xsl:apply-templates select="$json-array/*"/> </list> </xsl:template> <xsl:template match="fn:map"> <test_case> <xsl:apply-templates/> </test_case> </xsl:template> <xsl:template match="fn:map/fn:*"> <xsl:element name="{@key}"> <xsl:value-of select="."/> </xsl:element> </xsl:template> </xsl:stylesheet>
解决方案
你的代码无法工作的核心原因:json-doc()返回的是XDM数组对象,而非XML节点树,因此基于XML节点匹配的模板(如match="fn:map")无法生效。
提供两种可行修复方案:
方案1:直接处理XDM数组与Map(无需转XML节点)
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:map="http://www.w3.org/2005/xpath-functions/map" exclude-result-prefixes="xs map" version="3.0"> <xsl:output method="xml" indent="yes"/> <xsl:param name="p1"/> <xsl:variable name="json-array" select="json-doc($p1)"/> <xsl:template match="/"> <list> <!-- 遍历数组中的每个测试用例Map --> <xsl:for-each select="$json-array?*"> <test_case> <!-- 遍历Map的所有键,生成对应XML元素 --> <xsl:for-each select="map:keys(.)"> <xsl:element name="{.}"> <xsl:value-of select="map:get(current(), .)"/> </xsl:element> </xsl:for-each> </test_case> </xsl:for-each> </list> </xsl:template> </xsl:stylesheet>
方案2:先将JSON转为XML节点,再用模板匹配
利用json-to-xml()函数将JSON转换为标准XML节点结构,再通过模板匹配处理:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" exclude-result-prefixes="xs fn" version="3.0"> <xsl:output method="xml" indent="yes"/> <xsl:param name="p1"/> <!-- 将JSON转换为XML节点结构 --> <xsl:variable name="json-xml" select="fn:json-to-xml(json-doc($p1))"/> <xsl:template match="/"> <list> <!-- 匹配数组中的每个Map节点 --> <xsl:apply-templates select="$json-xml/*/*"/> </list> </xsl:template> <!-- 每个Map对应一个test_case元素 --> <xsl:template match="fn:map"> <test_case> <xsl:apply-templates select="fn:entry"/> </test_case> </xsl:template> <!-- 每个Map的键值对对应一个XML元素 --> <xsl:template match="fn:entry"> <xsl:element name="{@key}"> <xsl:value-of select="."/> </xsl:element> </xsl:template> </xsl:stylesheet>
两种方案均能生成你期望的XML格式,任选其一即可。
内容的提问来源于stack exchange,提问作者YaP
相关产品推荐
相关产品推荐

