如何在不改动现有XSLT逻辑前提下处理XML转JSON的空标签输出
XSLT空标签填充实现方案(适配XML转指定JSON格式)
核心要求:
- 不干扰现有XSLT代码的业务逻辑
- 空标签按预期JSON格式输出:空文本节点输出为
"",指定列表节点输出为空数组[] - 仅保留预期JSON中定义的参数
输入XML文件
<?xml version="1.0" encoding="UTF-8"?> <ns0:PO_Record xmlns:ns0="http://Test.com/Order"> <domainId>TEST</domainId> <hubDomainId>TEST</hubDomainId> <isForReference>false</isForReference> <status>Ok</status> <docStatus>Success</docStatus> <editingStatus>confirmed</editingStatus> <vpoNo>10000341</vpoNo> <vpoDate>2021-03-05</vpoDate> <instructions></instructions> <businessRefNo>10000341</businessRefNo> <totalItems>0</totalItems> <totalQty>0</totalQty> <customFields> <customFieldDate1>2042-01-21</customFieldDate1> </customFields> <season> <code>F22</code> </season> <custId> <custCode>TEST</custCode> <refNo>002001</refNo> </custId> <vendorId> <vendorCode>1235</vendorCode> </vendorId> <vpoItemList></vpoItemList> <vpoShipDtlDtoGroupList></vpoShipDtlDtoGroupList> <vpoShipDtlCsGroupList></vpoShipDtlCsGroupList> </ns0:PO_Record>
预期输出JSON格式
{ "domainId": "TEST", "hubDomainId": "TEST", "isForReference": "false", "status": "Ok", "docStatus": "Success", "editingStatus": "confirmed", "vpoNo": "10000341", "vpoDate": "2021-03-05", "instructions": "", "businessRefNo": "10000341", "totalItems": "0", "totalQty": "0", "customFields": { "customFieldDate1": "2042-01-21" }, "season": { "code": "F22" }, "custId": { "custCode": "TEST", "refNo": "002001" }, "vendorId": { "vendorCode": "1235" }, "vpoItemList": [], "vpoShipDtlDtoGroupList": [], "vpoShipDtlCsGroupList": [] }
兼容原有逻辑的XSLT代码
仅新增1个空列表节点匹配模板,原有业务逻辑完全保留:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="#all" xmlns="http://www.w3.org/2005/xpath-functions" expand-text="yes" version="3.0"> <xsl:output method="text"/> <xsl:template match="/"> <xsl:variable name="json-xml"> <xsl:apply-templates/> </xsl:variable> <xsl:value-of select="xml-to-json($json-xml, map { 'indent' : true() })"/> </xsl:template> <!-- 新增模板:匹配空的指定列表节点,生成空数组 --> <xsl:template match="vpoItemList | vpoItemCsList | vpoShipDtlDtoGroupList | vpoShipDtlCsGroupList[not(*)]"> <array key="{local-name()}"/> </xsl:template> <xsl:template match="*[not(*)]"> <string key="{local-name()}">{.}</string> </xsl:template> <xsl:template match="*[(*) and . castable as xs:double]"> <number key="{local-name()}">{.}</number> </xsl:template> <xsl:template match="*[*]"> <xsl:param name="key" as="xs:boolean" select="false()"/> <map> <xsl:if test="$key"> <xsl:attribute name="key" select="local-name()"/> </xsl:if> <xsl:for-each-group select="*" group-by="node-name()"> <xsl:choose> <xsl:when test="current-group()[2] or self::vpoItemList or self::vpoItemCsList or self::vpoShipDtlDtoGroupList or self::vpoShipDtlCsGroupList"> <array key="{local-name()}"> <xsl:choose> <xsl:when test="self::vpoShipDtlDtoGroupList"> <array> <xsl:apply-templates select="current-group()"> <xsl:with-param name="key" select="false()"/> </xsl:apply-templates> </array> </xsl:when> <xsl:when test="self::vpoShipDtlCsGroupList"> <xsl:for-each-group select="current-group()" group-by="itemLotNo"> <array> <xsl:apply-templates select="current-group()"> <xsl:with-param name="key" select="false()"/> </xsl:apply-templates> </array> </xsl:for-each-group> </xsl:when> <xsl:otherwise> <xsl:apply-templates select="current-group()"> <xsl:with-param name="key" select="false()"/> </xsl:apply-templates> </xsl:otherwise> </xsl:choose> </array> </xsl:when> <xsl:otherwise> <xsl:apply-templates select="current-group()"> <xsl:with-param name="key" select="true()"/> </xsl:apply-templates> </xsl:otherwise> </xsl:choose> </xsl:for-each-group> </map> </xsl:template> </xsl:stylesheet>
调整说明
- 新增模板优先级高于原有通用模板,只会匹配指定的空列表节点,不会影响其他节点的转换逻辑
- 空文本节点(如
<instructions></instructions>)由原有模板自动输出为"",符合预期 - 输出字段完全匹配预期JSON范围,无冗余内容
内容的提问来源于stack exchange,提问作者raviteja
相关产品推荐
相关产品推荐

