如何使用 xslt 将嵌套的 Json 对象转换为 xml

Posted

技术标签:

【中文标题】如何使用 xslt 将嵌套的 Json 对象转换为 xml【英文标题】:How to Convert nested Json object into xml using xslt 【发布时间】:2021-04-08 10:38:27 【问题描述】:
<root><dataResponse>"status":"C","responseCode":200,"description":"Success","resultsInformation":["sourceSystemAppID":"8257000008880","sourceSystemCustomerID":"82570000021453","sourceSystemName":"FINCOR","customerType":"AI","recordType":"INPUT","name":"TAMIZHARASI  M  ","employerName":"","dateOfBirth":"08-10-1977","panNo":"","voterID":"GSDF2613891","passportNo":"","drivingLicense":"","aadhaarNumber":"","gstNumber":"","registrationORCINNo":"","rationCard":"","nregaCard":"","nationalIdNo":"","tanNo":"","gender":"F","addressInformation":["addressType":"ressAddr","address":"49/2 NEW KRISHNAPURAM UYYAKONDAVARI VIRUDHACHALAM  ","city":"VIRUDHACHALAM","state":"TAMILNADU","pincode":"607802","addressType":"permAddr","address":"49/2 NEW KRISHNAPURAM UYYAKONDAVARI VIRUDHACHALAM   ","city":"VIRUDHACHALAM","state":"TAMILNADU","pincode":"607802","addressType":"permAddr","address":"49/2 NEW KRISHNAPURAM UYYAKONDAVARI VIRUDHACHALAM   ","city":"VIRUDHACHALAM","state":"TAMILNADU","pincode":"607802"],"emailInformation":["emailType":"ressEmail","emailID":""],"contactInformation":["phoneType":"offPhone","phone":"","phoneType":"mobile","phone":"9659306719","phoneType":"ressPhone","phone":""],"ckycNumber":"","chassisNumber":"","engineNumber":"","vehicleRegistrationNo":"","remarks":"","sourceSystemAppID":"0000","sourceSystemCustomerID":"82570000021453","sourceSystemName":"FINCOR","customerType":"AI","recordType":"ONLINE","name":"TAMIZHARASI  M  ","employerName":"","dateOfBirth":"08-10-1977","panNo":"","voterID":"FEF2613891","passportNo":"","drivingLicense":"","aadhaarNumber":"","gstNumber":"","registrationORCINNo":"","rationCard":"","nregaCard":"","nationalIdNo":"","tanNo":"","gender":"F","addressInformation":["addressType":"ressAddr","address":"49/2 NEW KRISHNAPURAM UYYAKONDAVARI VIRUDHACHALAM  ","city":"","state":"TAMILNADU","pincode":"607802","addressType":"offAddr","address":"49/2 NEW KRISHNAPURAM UYYAKONDAVARI VIRUDHACHALAM  ","city":"VIRUDHACHALAM","state":"TAMILNADU","pincode":"607802","addressType":"offAddr","address":"49/2 NEW KRISHNAPURAM UYYAKONDAVARI VIRUDHACHALAM  ","city":"VIRUDHACHALAM","state":"TAMILNADU","pincode":"607802"],"emailInformation":["emailType":"others","emailID":""],"contactInformation":["phoneType":"offPhone","phone":"","phoneType":"ressPhone","phone":"","phoneType":"mobile","phone":"999999999"],"ckycNumber":"","chassisNumber":"","engineNumber":"","vehicleRegistrationNo":"","remarks":"","sourceSystemAppID":"3181919","sourceSystemCustomerID":"1","sourceSystemName":"FINCOR","customerType":"AI","recordType":"ONLINE","name":"TAMIZHARASI  M  ","employerName":"","dateOfBirth":"08-10-1977","panNo":"","voterID":"GFG2613891","passportNo":"","drivingLicense":"","aadhaarNumber":"","gstNumber":"","registrationORCINNo":"","rationCard":"","nregaCard":"","nationalIdNo":"","tanNo":"","gender":"F","addressInformation":["addressType":"ressAddr","address":"49/2 NEW KRISHNAPURAM UYYAKONDAVARI VIRUDHACHALAM  ","city":"VIRUDHACHALAM","state":"TAMILNADU","pincode":"607802","addressType":"offAddr","address":"49/2 NEW KRISHNAPURAM UYYAKONDAVARI VIRUDHACHALAM  ","city":"VIRUDHACHALAM","state":"TAMILNADU","pincode":"607802","addressType":"offAddr","address":"49/2 NEW KRISHNAPURAM UYYAKONDAVARI VIRUDHACHALAM  ","city":"VIRUDHACHALAM","state":"TAMILNADU","pincode":"607802"],"emailInformation":["emailType":"ressEmail","emailID":""],"contactInformation":["phoneType":"offPhone","phone":"","phoneType":"ressPhone","phone":"","phoneType":"mobile","phone":"999999999"],"ckycNumber":"","chassisNumber":"","engineNumber":"","vehicleRegistrationNo":"","remarks":"","sourceSystemAppID":"3181919","sourceSystemCustomerID":"358166","sourceSystemName":"FINCOR","customerType":"AI","recordType":"ONLINE","name":"TAMIZHARASI  M  ","employerName":"","dateOfBirth":"08-10-1977","panNo":"","voterID":"EYT2613891","passportNo":"","drivingLicense":"","aadhaarNumber":"","gstNumber":"","registrationORCINNo":"","rationCard":"","nregaCard":"","nationalIdNo":"","tanNo":"","gender":"F","addressInformation":["addressType":"ressAddr","address":"49/2 NEW KRISHNAPURAM UYYAKONDAVARI VIRUDHACHALAM  ","city":"VIRUDHACHALAM","state":"TAMILNADU","pincode":"607802","addressType":"offAddr","address":"49/2 NEW KRISHNAPURAM UYYAKONDAVARI VIRUDHACHALAM  ","city":"VIRUDHACHALAM","state":"TAMILNADU","pincode":"607802","addressType":"offAddr","address":"49/2 NEW KRISHNAPURAM UYYAKONDAVARI VIRUDHACHALAM  ","city":"VIRUDHACHALAM","state":"TAMILNADU","pincode":"607802"],"emailInformation":["emailType":"ressEmail","emailID":""],"contactInformation":["phoneType":"offPhone","phone":"","phoneType":"ressPhone","phone":"","phoneType":"mobile","phone":"999999999"],"ckycNumber":"","chassisNumber":"","engineNumber":"","vehicleRegistrationNo":"","remarks":"","sourceSystemAppID":"570000021422","sourceSystemCustomerID":"82570000021422","sourceSystemName":"BRNET","customerType":"AI","recordType":"ONLINE","name":"TAMIZHARASI  M","employerName":"","dateOfBirth":"10-08-1977","panNo":"","voterID":"TYR2613891","passportNo":"","drivingLicense":"","aadhaarNumber":"","gstNumber":"","registrationORCINNo":"","rationCard":"","nregaCard":"","nationalIdNo":"","tanNo":"","gender":"F","addressInformation":["addressType":"others","address":"pirni","city":"verna","state":"goa","pincode":"403722"],"emailInformation":["emailType":"others","emailID":"shashank.k@gmail.com"],"contactInformation":["phoneType":"mobile","phone":"999999999"],"ckycNumber":"","chassisNumber":"","engineNumber":"","vehicleRegistrationNo":"","remarks":"","sourceSystemAppID":"570000021453","sourceSystemCustomerID":"82570000021452","sourceSystemName":"BRMF","customerType":"AI","recordType":"ONLINE","name":"TAMIZHARASI  M","employerName":"","dateOfBirth":"10-08-1977","panNo":"","voterID":"SGSG2613891","passportNo":"","drivingLicense":"","aadhaarNumber":"","gstNumber":"","registrationORCINNo":"","rationCard":"","nregaCard":"","nationalIdNo":"","tanNo":"","gender":"F","addressInformation":["addressType":"others","address":"pirni","city":"verna","state":"goa","pincode":"403722"],"emailInformation":["emailType":"others","emailID":"DFSDFDSF.k@gmail.com"],"contactInformation":["phoneType":"mobile","phone":"999999999"],"ckycNumber":"","chassisNumber":"","engineNumber":"","vehicleRegistrationNo":"","remarks":"","sourceSystemAppID":"570000021453","sourceSystemCustomerID":"82570000021453","sourceSystemName":"BRMF","customerType":"AI","recordType":"ONLINE","name":"TAMIZHARASI  M","employerName":"","dateOfBirth":"10-08-1977","panNo":"","voterID":"TYR2613891","passportNo":"","drivingLicense":"","aadhaarNumber":"","gstNumber":"","registrationORCINNo":"","rationCard":"","nregaCard":"","nationalIdNo":"","tanNo":"","gender":"F","addressInformation":["addressType":"others","address":"pirni","city":"verna","state":"goa","pincode":"403722"],"emailInformation":["emailType":"others","emailID":"DSDSAD.k@gmail.com"],"contactInformation":["phoneType":"mobile","phone":"9999999999"],"ckycNumber":"","chassisNumber":"","engineNumber":"","vehicleRegistrationNo":"","remarks":"","sourceSystemAppID":"82570000021453","sourceSystemCustomerID":"82570000021453","sourceSystemName":"BRMF","customerType":"AI","recordType":"ONLINE","name":"TAMIZHARASI  M","employerName":"","dateOfBirth":"10-08-1977","panNo":"","voterID":"Gtyv2613891","passportNo":"","drivingLicense":"","aadhaarNumber":"","gstNumber":"","registrationORCINNo":"","rationCard":"","nregaCard":"","nationalIdNo":"","tanNo":"","gender":"F","addressInformation":["addressType":"others","address":"pirni","city":"verna","state":"goa","pincode":"403722"],"emailInformation":["emailType":"others","emailID":"shashank.k@gmail.com"],"contactInformation":["phoneType":"mobile","phone":"9999999999"],"ckycNumber":"","chassisNumber":"","engineNumber":"","vehicleRegistrationNo":"","remarks":"","sourceSystemAppID":"82570000021453","sourceSystemCustomerID":"82570000021856","sourceSystemName":"BRMF","customerType":"AI","recordType":"ONLINE","name":"TAMIZHARASI  M","employerName":"","dateOfBirth":"10-08-1977","panNo":"","voterID":"YRV2613891","passportNo":"","drivingLicense":"","aadhaarNumber":"","gstNumber":"","registrationORCINNo":"","rationCard":"","nregaCard":"","nationalIdNo":"","tanNo":"","gender":"F","addressInformation":[],"emailInformation":[],"contactInformation":["phoneType":"mobile","phone":"999999999"],"ckycNumber":"","chassisNumber":"","engineNumber":"","vehicleRegistrationNo":"","remarks":"","sourceSystemAppID":"8257000008881","sourceSystemCustomerID":"82570000021454","sourceSystemName":"FINCOR","customerType":"AI","recordType":"ONLINE","name":"TAMIZHARASI  M  ","employerName":"","dateOfBirth":"08-10-1977","panNo":"","voterID":"YRV2613891","passportNo":"","drivingLicense":"","aadhaarNumber":"","gstNumber":"","registrationORCINNo":"","rationCard":"","nregaCard":"","nationalIdNo":"","tanNo":"","gender":"F","addressInformation":["addressType":"ressAddr","address":"49/2 NEW KRISHNAPURAM UYYAKONDAVARI VIRUDHACHALAM  ","city":"VIRUDHACHALAM","state":"TAMILNADU","pincode":"607802","addressType":"offAddr","address":"49/2 NEW KRISHNAPURAM UYYAKONDAVARI VIRUDHACHALAM  ","city":"VIRUDHACHALAM","state":"TAMILNADU","pincode":"607802","addressType":"offAddr","address":"49/2 NEW KRISHNAPURAM UYYAKONDAVARI VIRUDHACHALAM  ","city":"VIRUDHACHALAM","state":"TAMILNADU","pincode":"607802"],"emailInformation":["emailType":"ressEmail","emailID":""],"contactInformation":["phoneType":"offPhone","phone":"","phoneType":"ressPhone","phone":"","phoneType":"mobile","phone":"999999999"],"ckycNumber":"","chassisNumber":"","engineNumber":"","vehicleRegistrationNo":"","remarks":""]</dataResponse><message>Request Completed Successfully</message><statusCode>000</statusCode><status>Success</status></root>

这是我的 xml 代码。到目前为止,我已经编写了 xslt 代码

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:cs="urn:cs" xmlns:msxsl="urn:schemas-microsoft-com:xslt" version="1.0" exclude-result-prefixes="msxsl cs">
   <xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
   <msxsl:script language="C#" implements-prefix="cs">
      <msxsl:assembly name="System.Web.Extensions" />
      <msxsl:using namespace="System.Collections.Generic" />
      <msxsl:using namespace="System.Web.Script.Serialization" />
      <![CDATA[public string getXMLFromJson(string jsonString)
      string resp="";
      var serializer = new javascriptSerializer();
      Dictionary<string, object> result = (serializer.DeserializeObject(jsonString) as Dictionary<string, object>);    
      foreach(string key in result.Keys)
        var newKey=key.Replace(" ","_");
        resp+="<"+newKey+">"+result[key]+"</"+newKey+">";
        
            return resp;
    ]]>
   </msxsl:script>
   <xsl:template match="@* | node()">
      <xsl:copy>
         <xsl:apply-templates select="@* | node()" />
      </xsl:copy>
   </xsl:template>
   <xsl:template match="root/dataResponse">
      <xsl:variable name="jstr">
         <xsl:value-of select="." />
      </xsl:variable>
      <dataResponse>
         <xsl:value-of select="cs:getXMLFromJson($jstr)" disable-output-escaping="yes" />
      </dataResponse>
   </xsl:template>
</xsl:stylesheet>

我无法遍历嵌套对象 resultsInformation 并且还想要循环 addressInformation 并将其转换为 xml。我当前的输出如下所示。

    <root>
  <dataResponse><status>C</status><responseCode>200</responseCode><description>Success</description><resultsInformation>System.Object[]</resultsInformation></dataResponse>
  <message>Request Completed Successfully</message>
  <statusCode>000</statusCode>
  <status>Success</status>
</root>

【问题讨论】:

我什至不知道您可以在 xslt 中注入 C# 代码...您可以发布代码以使 franken-xslt 运行吗? 我可以建议你“提取”C#代码,至少是为了调试它......最后你知道输入是什么(json)和输出应该是什么(一个 xml 片段)。 xslt 只是额外的包袱,它会使所有的调试变得更加复杂。 如果你可以使用 json.net 就很容易了:***.com/questions/18503845/… 【参考方案1】:

如果你可以使用 Json.Net,它就变成了单线:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:cs="urn:cs" xmlns:msxsl="urn:schemas-microsoft-com:xslt" version="1.0" exclude-result-prefixes="msxsl cs">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
    <xsl:strip-space elements="*"/>
    <msxsl:script language="C#" implements-prefix="cs">
        <msxsl:assembly name="System.Xml.Linq" />
        <msxsl:using namespace="Newtonsoft.Json" />
        <msxsl:assembly name="Newtonsoft.Json" />
        <msxsl:using namespace="System.Xml.Linq" />
        <![CDATA[
        public static XPathNavigator getXMLFromJson(string jsonString)
        
            var xml = JsonConvert.DeserializeXmlNode(jsonString, "dataResponse");
            return xml.CreateNavigator();
        
        ]]>
    </msxsl:script>
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()" />
        </xsl:copy>
    </xsl:template>
    <xsl:template match="root/dataResponse">
        <xsl:copy-of select="cs:getXMLFromJson(.)" />
    </xsl:template>
</xsl:stylesheet>

请注意,我添加了一个

<xsl:strip-space elements="*"/>

正确格式化生成的 xml。

如果没有 Json.Net,它会复杂得多(我不确定是否涵盖了所有极端情况):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:cs="urn:cs" xmlns:msxsl="urn:schemas-microsoft-com:xslt" version="1.0" exclude-result-prefixes="msxsl cs">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
    <xsl:strip-space elements="*"/>
    <msxsl:script language="C#" implements-prefix="cs">
        <msxsl:assembly name="System.Core" />
        <msxsl:assembly name="System.Xml.Linq" />
        <msxsl:assembly name="System.Web.Extensions" />
        <msxsl:using namespace="System.Collections.Generic" />
        <msxsl:using namespace="System.Linq" />
        <msxsl:using namespace="System.Xml.Linq" />
        <msxsl:using namespace="System.Web.Script.Serialization" />
        <![CDATA[
            public static XPathNavigator XmlFromJson(string root, string json)
            
                var jss = new JavaScriptSerializer();
                var xml = ToXElement(root, (IDictionary<string, object>)jss.DeserializeObject(json));
                return xml.CreateNavigator();
            

            public static XElement ToXElement(string name, IDictionary<string, object> coll)
            
                if (coll == null)
                
                    return new XElement(name, null);
                

                return new XElement(
                    name,
                    coll.Select(x =>
                        x.Value is IDictionary<string, object> ? new[]  ToXElement(x.Key, (IDictionary<string, object>)x.Value)  :
                        x.Value is object[]? ToXElement(x.Key, (object[])x.Value) :
                        new[]  new XElement(x.Key, x.Value) 
                    ).SelectMany(x => x)
                    .ToArray());
            

            public static XElement[] ToXElement(string name, object[] coll)
            
                if (coll == null)
                
                    return new[]  new XElement(name, null) ;
                

                return Array.ConvertAll(coll, x =>
                    x is IDictionary<string, object> ? ToXElement(name, (IDictionary<string, object>)x) :
                    x is object[]? new XElement(name, ToXElement(name, (object[])x)) :
                    new XElement(name, x)
                );
            
        ]]>
    </msxsl:script>
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()" />
        </xsl:copy>
    </xsl:template>
    <xsl:template match="root/dataResponse">
        <xsl:copy-of select='cs:XmlFromJson("dataResponse", .)' />
    </xsl:template>
</xsl:stylesheet>

【讨论】:

我无法使用 Newtonsoft.Json 反序列化 更新的代码对我有用。我会检查它的多个场景。

以上是关于如何使用 xslt 将嵌套的 Json 对象转换为 xml的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 XSLT 将单个子 xml 元素转换为 Json 数组

将嵌套的 JSON 解析为 CSV

如何使用 xlsx npm 库将嵌套的 json 对象转换为 excel 表?

如何停止 xslt3.0 的 xml-to-json() 函数将数字转换为指数表示法

如何将嵌套的 JSON 对象转换为数组 Spring Boot?

XSLT 3.0 - 无法在 XSLT 3.0 xml-to-json() 中获取对象数组