寻求基于XSLT的XML转JSON方案:处理命名空间与单元素数组问题
基于XSLT的Salesforce通知XML转JSON解决方案
需求说明
需将Salesforce出站通知XML转换为指定格式的JSON,核心解决两个问题:
- 移除XML中所有命名空间及元素前缀
- 即便仅存在单个
Notification元素,转换后也必须为JSON数组格式
输入XML
<notifications xmlns="http://soap.sforce.com/2005/09/outbound"> <OrganizationId>123</OrganizationId> <ActionId>123</ActionId> <SessionId xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/> <EnterpriseUrl>qwe</EnterpriseUrl> <PartnerUrl>qwe</PartnerUrl> <Notification> <Id>123</Id> <sObject xsi:type="sf:Opportunity" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sf="urn:sobject.enterprise.soap.sforce.com"> <sf:Id>ao123</sf:Id> <sf:Amount>60000.0</sf:Amount> <sf:CreatedDate>2014-11-26T14:45:52.000Z</sf:CreatedDate> <sf:IsClosed>false</sf:IsClosed> </sObject> </Notification> </notifications>
期望输出JSON
{ "notifications": { "OrganizationId": "123", "ActionId": "123", "SessionId": { "@nil": "true" }, "EnterpriseUrl": "qwe", "PartnerUrl": "qwe", "Notification": [ { "Id": "123", "sObject": { "@type": "sf:Opportunity", "Id": "ao123", "Amount": "60000.0", "CreatedDate": "2014-11-26T14:45:52.000Z", "IsClosed": "false" } } ] } }
XSLT转换方案
以下XSLT可完成所有需求处理:移除命名空间前缀、转换XSI属性格式、强制Notification为数组标识,生成可直接用于JSON序列化的中间XML。
XSLT代码
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sf="urn:sobject.enterprise.soap.sforce.com" xmlns:json="http://james.newtonking.com/projects/json" exclude-result-prefixes="xsi sf"> <!-- 匹配所有元素,移除命名空间前缀 --> <xsl:template match="*"> <xsl:element name="{local-name()}"> <xsl:apply-templates select="@* | node()"/> </xsl:element> </xsl:template> <!-- 转换xsi:nil属性为@nil格式 --> <xsl:template match="@xsi:nil"> <xsl:attribute name="@nil"> <xsl:value-of select="."/> </xsl:attribute> </xsl:template> <!-- 转换xsi:type属性为@type格式 --> <xsl:template match="@xsi:type"> <xsl:attribute name="@type"> <xsl:value-of select="."/> </xsl:attribute> </xsl:template> <!-- 保留非命名空间相关的其他属性 --> <xsl:template match="@*[not(namespace-uri() = namespace-uri(xsi:nil) or namespace-uri() = namespace-uri(sf:Id))]"> <xsl:copy/> </xsl:template> <!-- 强制Notification元素携带数组标识,确保单个元素也被序列化为数组 --> <xsl:template match="*[local-name()='Notification']"> <xsl:element name="{local-name()}"> <xsl:attribute name="json:Array">true</xsl:attribute> <xsl:apply-templates select="@* | node()"/> </xsl:element> </xsl:template> <!-- 复制文本节点 --> <xsl:template match="text()"> <xsl:copy/> </xsl:template> </xsl:stylesheet>
使用步骤
- 用XSLT处理器(如Saxon、.NET的
XslCompiledTransform)将输入XML转换为中间XML,转换后会自动移除命名空间前缀并添加数组标识 - 使用
JsonConvert.SerializeXNode处理中间XML,即可得到符合要求的JSON
转换后的中间XML示例
<notifications> <OrganizationId>123</OrganizationId> <ActionId>123</ActionId> <SessionId @nil="true"/> <EnterpriseUrl>qwe</EnterpriseUrl> <PartnerUrl>qwe</PartnerUrl> <Notification json:Array="true"> <Id>123</Id> <sObject @type="sf:Opportunity"> <Id>ao123</Id> <Amount>60000.0</Amount> <CreatedDate>2014-11-26T14:45:52.000Z</CreatedDate> <IsClosed>false</IsClosed> </sObject> </Notification> </notifications>
内容的提问来源于stack exchange,提问作者techresearch
相关产品推荐
相关产品推荐

