.NET中利用Ebay的XSLT模板转换XML到JSON

从XML转换到JSON的方法有多种, 不过都要依赖第三方的库来实现转化,不过有了eBay提供的xml-2-json.xlst模板,你会发现转换原来很轻松.

xml-2-json.xslt的代码大致如下(稍做了点改动):

<? xml version="1.0" encoding="UTF-8" ?>
< xsl:stylesheet  version ="1.0"  xmlns:xsl ="http://www.w3.org/1999/XSL/Transform"  xmlns:fo ="http://www.w3.org/1999/XSL/Format"  xmlns:ebl ="urn:ebay:apis:eBLBaseComponents"  exclude-result-prefixes ="ebl" >
    
<!-- ====================================================================================
    Original version by : Holten Norris ( holtennorris at yahoo.com )
    Current version maintained  by: Alan Lewis (alanlewis at gmail.com)
    Thanks to Venu Reddy from eBay XSLT team for help with the array detection code
    Protected by CDDL open source license.  
    Transforms XML into JavaScript objects, using a JSON format.
    ===================================================================================== 
-->
    
< xsl:output  method ="text"  encoding ="UTF-8" />
    
< xsl:template  match ="*" >
        
< xsl:param  name ="recursionCnt" > 0 </ xsl:param >
        
< xsl:param  name ="isLast" > 1 </ xsl:param >
        
< xsl:param  name ="inArray" > 0 </ xsl:param >
        
< xsl:if  test ="$recursionCnt=0" >
            
< xsl:text > json = { </ xsl:text >
        
</ xsl:if >
        
<!--  test what type of data to output   -->
        
< xsl:variable  name ="elementDataType" >
            
< xsl:value-of  select ="number(text())" />
        
</ xsl:variable >
        
< xsl:variable  name ="elementData" >
            
<!--  TEXT ( use quotes )  -->
            
< xsl:if  test ="string($elementDataType) ='NaN'" >
                
< xsl:if  test ="boolean(text())" >
                "
< xsl:value-of  select ="text()" /> "
                
</ xsl:if >
            
</ xsl:if >
            
<!--  NUMBER (no quotes )  -->
            
< xsl:if  test ="string($elementDataType) !='NaN'" >
                
< xsl:value-of  select ="text()" />
            
</ xsl:if >
            
<!--  NULL  -->
            
< xsl:if  test ="not(*)" >
                
< xsl:if  test ="not(text())" >
                    null
                
</ xsl:if >
            
</ xsl:if >
        
</ xsl:variable >
        
< xsl:variable  name ="hasRepeatElements" >
            
< xsl:for-each  select ="*" >
                
< xsl:if  test ="name() = name(preceding-sibling::*) or name() = name(following-sibling::*)" >
                    true
                
</ xsl:if >
            
</ xsl:for-each >
        
</ xsl:variable >
        
< xsl:if  test ="not(count(@*) &gt; 0)" >
         "
< xsl:value-of  select ="local-name()" /> ":  < xsl:value-of  select ="$elementData" />
        
</ xsl:if >
        
< xsl:if  test ="count(@*) &gt; 0" >
        "
< xsl:value-of  select ="local-name()" /> ": {
        "content": 
< xsl:value-of  select ="$elementData" />
            
< xsl:for-each  select ="@*" >
                
< xsl:if  test ="position()=1" > , </ xsl:if >
                
<!--  test what type of data to output   -->
                
< xsl:variable  name ="dataType" >
                    
< xsl:value-of  select ="number(.)" />
                
</ xsl:variable >
                
< xsl:variable  name ="data" >
                    
<!--  TEXT ( use quotes )  -->
                    
< xsl:if  test ="string($dataType) ='NaN'" >
                "
< xsl:value-of  select ="current()" /> </ xsl:if >
                    
<!--  NUMBER (no quotes )  -->
                    
< xsl:if  test ="string($dataType) !='NaN'" >
                        
< xsl:value-of  select ="current()" />
                    
</ xsl:if >
                
</ xsl:variable >
                
< xsl:value-of  select ="local-name()" /> : < xsl:value-of  select ="$data" />
                
< xsl:if  test ="position() !=last()" > </ xsl:if >
            
</ xsl:for-each >
        }
        
</ xsl:if >
        
< xsl:if  test ="not($hasRepeatElements = '')" >
                    [{
                
</ xsl:if >
        
< xsl:for-each  select ="*" >
            
< xsl:if  test ="position()=1" >
                
< xsl:if  test ="$hasRepeatElements = ''" >
                    
< xsl:text >  {  </ xsl:text >
                
</ xsl:if >
            
</ xsl:if >
            
< xsl:apply-templates  select ="current()" >
                
< xsl:with-param  name ="recursionCnt"  select ="$recursionCnt+1" />
                
< xsl:with-param  name ="isLast"  select ="position()=last()" />
                
< xsl:with-param  name ="inArray"  select ="not($hasRepeatElements = '')" />
            
</ xsl:apply-templates >
            
< xsl:if  test ="position()=last()" >
                
< xsl:if  test ="$hasRepeatElements = ''" >
                    
< xsl:text >  }  </ xsl:text >
                
</ xsl:if >
            
</ xsl:if >
        
</ xsl:for-each >
        
< xsl:if  test ="not($hasRepeatElements = '')" >
                    }]
                
</ xsl:if >
        
< xsl:if  test ="not( $isLast )" >
            
< xsl:if  test ="$inArray = 'true'" >
                
< xsl:text >  }  </ xsl:text >
            
</ xsl:if >
            , 
            
< xsl:if  test ="$inArray = 'true'" >
                
< xsl:text >  {  </ xsl:text >
            
</ xsl:if >
        
</ xsl:if >
        
< xsl:if  test ="$recursionCnt=0" >  };  </ xsl:if >
    
</ xsl:template >
</ xsl:stylesheet >

 从上面的代码可以看出,只要给出相应的XML在应用此XLST样式就可以实现转化了。

不过为了方便,还是封装一层,以便我们能更好地在.NET下完成任务:

首先,是一个通用的转换方法,它可以读出流,然后应用XSLT样式:

 

private   static   string  XML2JSon(Stream rd, int  type) 
        
{
            XmlDocument doc 
= new XmlDocument();
            rd.Position
=0;
            doc.Load(rd);

            XmlElement root 
= doc.DocumentElement;
            XmlNodeList nl;
            
if(type == 0)
                 nl 
= root.SelectNodes("//Table1");
            
else
                 nl 
= root.ChildNodes;
            XmlDocument srcdoc 
= new XmlDocument();
            
string temp =null;
            
foreach(XmlNode xn in nl) 
            
{
                
if(type==0)
                    temp 
+= xn.InnerXml;
                
else
                    temp 
+= xn.OuterXml;
            }

            temp 
= "<result>" + temp + "</result>";
            srcdoc.InnerXml 
= temp;

            XPathNavigator nav 
= srcdoc.CreateNavigator();

            XslTransform xt 
= new XslTransform();

            
string path = ConfigurationSettings.AppSettings["ServerPath"];
            xt.Load(path 
+ "css/xml-2-json.xsl");

            Stream w 
= new MemoryStream();
            XmlTextWriter wr 
= new XmlTextWriter(w,Encoding.GetEncoding("UTF-8"));
            xt.Transform(nav,
null,w,null);
            w.Position 
= 0;
            StreamReader tr 
= new StreamReader(w);
            
string str = tr.ReadToEnd();
            
            w.Close();
            tr.Close();
            
return str;
        }

 

然后定义三个重载方法,来负责转换或序列化对象生成XML:

 转换DataSet

         public   static   string  Convert(DataSet ds) 
        
{
            MemoryStream ms 
= new MemoryStream();
            XmlTextWriter tw 
= new XmlTextWriter(ms,Encoding.UTF8);
            ds.WriteXml(ms);
            
string str = XML2JSon(ms,0);
            ds.Dispose();
            ms.Close();
            
return str;
        }

转换Model

public   static   string  Convert( object  model) 
        {
            XmlSerializer xmls 
=   new  XmlSerializer(model.GetType());
            MemoryStream ms 
=   new  MemoryStream();
            xmls.Serialize(ms,model);
            
string  str  =  XML2JSon(ms, 1 );
            ms.Close();
            
return  str;
        }

直接读XML并转换

public   static   string  Convert( string  XMLFilename) 
        
{
            FileStream fs 
= new FileStream(XMLFilename,FileMode.Open,FileAccess.Read);
            
string str = XML2JSon(fs,1);
            fs.Close();
            
return str;
        }

然后我们就可以使用它了,在ashx或webservice里调用Convert方法并用Response.write方法输出,就可以得到JSON。

例如:

<? xml version="1.0" encoding="utf-8"  ?>  
< root >
    
< styletype  id ="0"  imgsrc ="/fitment/images/loading/loading.gif" > 读取中....... </ styletype >
    
<!-- <styletype id="1" imgsrc="/fitment/images/loading/loadingbar2.gif"><![CDATA[&nbsp;]]></styletype> -->
    
< styletype  id ="1" > <![CDATA[ 读取中....<br><img src='/fitment/images/loading/loadingbar2.gif'/> ]]> </ styletype >
</ root >

输出成

json  =  {  " result " : [{  " styletype " : {  " content " " 读取中....... "  ,id: 0 , imgsrc:  " /fitment/images/loading/loading.gif "  } } , {  " styletype " : {  " content " " 读取中....
"  ,id: 1  } }] }; 

OK,这样我们就可以通过多种方式读出此JSON来处理我们的数据了

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值