zoukankan      html  css  js  c++  java
  • xml解析

      最近的一个项目,调用第三方的接口来获取数据并呈现,第三方接口收发的数据采用xml格式,返回的xml有点让人蛋疼,可读性差,语义破碎。这使得本人这边的项目使用起来有点费劲,之前项目组一个成员,根据接收的报文示例,采用绝对定位的方式读取其中的数据,非常不健壮,只要报文中元素标签的位置发生变化,获取的结果就不对了。之前项目为了赶进度,就在原来的代码基础上加了点封装,基本满足生产环境的要求。但是仅仅两个方法就一百多行代码,显然还有待优化。故利用假期闲暇时段做了点优化,代码量减少了一半,看着舒服多了。

      具体问题如下:

    返回的报文有两种类型:

      (1)用户基本信息:

      

    <?xml version="1.0" ?>
    <response>
    <meta>
    <reqserialno>GJ07L20151223150941707527</reqserialno>
    <channeltype>016</channeltype>
    </meta>
    <data>
    <list>
    <info>
    <orderby />
    <pages>1</pages>
    <page>1</page>
    <total>1</total>
    </info>
    <cols>
    <custacno />
    <custname />
    <paperkind />
    <paperid />
    <corpacno />
    <accubankid />
    <bankname />
    <corpname />
    <cardflag />
    <monthinco />
    <averinco />
    <isspeperc />
    <custperc />
    <corpperc />
    <isalloperc />
    <alloperc />
    <alloamt />
    <accuamt />
    <sumamt />
    <bal />
    <custacstat />
    <custtrusstat />
    <operdate />
    <bankid />
    <operid />
    <agentcorpno />
    <drawcardflag />
    <cardstat />
    <lastsavemonth />
    <channeltype />
    <custid />
    <accucardno />
    <orderno />
    <custdept />
    <natisign2 />
    <bindbanktype />
    <bankcardno />
    </cols>
    <rows>
    <row id="1">
    <c>0961838227</c>
    <c>韩**</c>
    <c>A</c>
    <c>420803198204045129</c>
    <c>1201043768</c>
    <c>010206</c>
    <c>建行干将支行(大厅)</c>
    <c>**市住房公积金管理中心</c>
    <c>1</c>
    <c>8450</c>
    <c>8450</c>
    <c />
    <c>12</c>
    <c>12</c>
    <c>1</c>
    <c>18</c>
    <c>1521</c>
    <c>2028</c>
    <c>3549</c>
    <c>9702.23</c>
    <c>200</c>
    <c>230</c>
    <c>20120926</c>
    <c>010203</c>
    <c>010203000</c>
    <c />
    <c>1</c>
    <c>001</c>
    <c>201511</c>
    <c>002</c>
    <c>A4208031982040451290</c>
    <c>09618382271</c>
    <c />
    <c />
    <c>156</c>
    <c>014</c>
    <c>6214619999025685774</c>
    </row>
    </rows>
    </list>
    </data>
    </response>

      (2) 用户记录信息: 

    <?xml version="1.0" ?>
    <response>
    <meta>
    <reqserialno>GJ08L12015122315121134560494</reqserialno>
    <channeltype>016</channeltype>
    </meta>
    <data>
    <list>
    <info>
    <orderby />
    <pages>6</pages>
    <page>1</page>
    <total>53</total>
    </info>
    <cols>
    <acbooknum />
    <corpacno />
    <custacno />
    <custname />
    <busidetailtype />
    <acculistid />
    <amt />
    <inte />
    <bal />
    <fixedsavebal />
    <demandsavebal />
    <note />
    <acdate />
    <bankid />
    <acid />
    <cancelacbooknum />
    <savemonth />
    <flag />
    <bankname />
    <r />
    </cols>
    <rows>
    <row id="1">
    <c>2000000</c>
    <c>1201043768</c>
    <c>0961838227</c>
    <c>韩**</c>
    <c>103</c>
    <c>12010437682038</c>
    <c>6183</c>
    <c>0</c>
    <c>6183</c>
    <c>0</c>
    <c>6183</c>
    <c>201207201209</c>
    <c>20120927</c>
    <c>010206</c>
    <c>010206017</c>
    <c />
    <c />
    <c>收入</c>
    <c>建行干将支行(大厅)</c>
    <c>1</c>
    </row>
    <row id="2">
    <c>2000001</c>
    <c>1201043768</c>
    <c>0961838227</c>
    <c>韩**</c>
    <c>101</c>
    <c>12010437682040</c>
    <c>2061</c>
    <c>0</c>
    <c>8244</c>
    <c>0</c>
    <c>8244</c>
    <c />
    <c>20121010</c>
    <c>010203</c>
    <c>010203000</c>
    <c />
    <c>201210</c>
    <c>收入</c>
    <c>建行干将支行(大厅)</c>
    <c>2</c>
    </row>
    <row id="3">
    <c>2000002</c>
    <c>1201043768</c>
    <c>0961838227</c>
    <c>韩**</c>
    <c>101</c>
    <c>12010437682042</c>
    <c>2061</c>
    <c>0</c>
    <c>10305</c>
    <c>0</c>
    <c>10305</c>
    <c />
    <c>20121112</c>
    <c>010203</c>
    <c>010203000</c>
    <c />
    <c>201211</c>
    <c>收入</c>
    <c>建行干将支行(大厅)</c>
    <c>3</c>
    </row>
    <row id="4">
    <c>2000003</c>
    <c>1201043768</c>
    <c>0961838227</c>
    <c>韩**</c>
    <c>101</c>
    <c>12010437682045</c>
    <c>2061</c>
    <c>0</c>
    <c>12366</c>
    <c>0</c>
    <c>12366</c>
    <c />
    <c>20121210</c>
    <c>010203</c>
    <c>010203000</c>
    <c />
    <c>201212</c>
    <c>收入</c>
    <c>建行干将支行(大厅)</c>
    <c>4</c>
    </row>
    <row id="5">
    <c>2000004</c>
    <c>1201043768</c>
    <c>0961838227</c>
    <c>韩**</c>
    <c>101</c>
    <c>12010437682046</c>
    <c>2061</c>
    <c>0</c>
    <c>14427</c>
    <c>0</c>
    <c>14427</c>
    <c />
    <c>20130110</c>
    <c>010203</c>
    <c>010203000</c>
    <c />
    <c>201301</c>
    <c>收入</c>
    <c>建行干将支行(大厅)</c>
    <c>5</c>
    </row>
    <row id="6">
    <c>2000005</c>
    <c>1201043768</c>
    <c>0961838227</c>
    <c>韩**</c>
    <c>101</c>
    <c>12010437682047</c>
    <c>2061</c>
    <c>0</c>
    <c>16488</c>
    <c>0</c>
    <c>16488</c>
    <c />
    <c>20130207</c>
    <c>010203</c>
    <c>010203000</c>
    <c />
    <c>201302</c>
    <c>收入</c>
    <c>建行干将支行(大厅)</c>
    <c>6</c>
    </row>
    <row id="7">
    <c>2000006</c>
    <c>1201043768</c>
    <c>0961838227</c>
    <c>韩**</c>
    <c>101</c>
    <c>12010437682048</c>
    <c>2061</c>
    <c>0</c>
    <c>18549</c>
    <c>0</c>
    <c>18549</c>
    <c />
    <c>20130311</c>
    <c>010203</c>
    <c>010203000</c>
    <c />
    <c>201303</c>
    <c>收入</c>
    <c>建行干将支行(大厅)</c>
    <c>7</c>
    </row>
    <row id="8">
    <c>2000007</c>
    <c>1201043768</c>
    <c>0961838227</c>
    <c>韩**</c>
    <c>101</c>
    <c>12010437682050</c>
    <c>2061</c>
    <c>0</c>
    <c>20610</c>
    <c>0</c>
    <c>20610</c>
    <c />
    <c>20130410</c>
    <c>010203</c>
    <c>010203000</c>
    <c />
    <c>201304</c>
    <c>收入</c>
    <c>建行干将支行(大厅)</c>
    <c>8</c>
    </row>
    <row id="9">
    <c>2000008</c>
    <c>1201043768</c>
    <c>0961838227</c>
    <c>韩**</c>
    <c>101</c>
    <c>12010437682051</c>
    <c>2061</c>
    <c>0</c>
    <c>22671</c>
    <c>0</c>
    <c>22671</c>
    <c />
    <c>20130510</c>
    <c>010203</c>
    <c>010203000</c>
    <c />
    <c>201305</c>
    <c>收入</c>
    <c>建行干将支行(大厅)</c>
    <c>9</c>
    </row>
    <row id="10">
    <c>2000009</c>
    <c>1201043768</c>
    <c>0961838227</c>
    <c>韩**</c>
    <c>106</c>
    <c>09618382272000</c>
    <c>9900</c>
    <c>0</c>
    <c>12771</c>
    <c>0</c>
    <c>12771</c>
    <c />
    <c>20130513</c>
    <c>010110</c>
    <c>010110002</c>
    <c />
    <c />
    <c>支出</c>
    <c>建行干将支行(大厅)</c>
    <c>10</c>
    </row>
    </rows>
    </list>
    </data>
    </response>

     

      项目的要求是基本信息用一页显示,记录信息用列表显示,且记录信息可能有多条,需要进行分页处理。基本信息的字段名称是cols元素的子元素,以其对应的名称做为标签名,基本信息的值在row元素内,标签名都是c,且数量和顺序和cols的子元素一一对应。记录信息的字段名称是cols的子元素,每次返回的记录有10条,在rows元素内,每条记录对应其一个子元素row,另外,每次报文中会返回3个重要参数:当前页码,总页数,记录总数,值分别在info元素的子元素<page></page>,<pages></pages>,<total></total>中。

    我针对以上两种xml的解析方法:

     1 public class XmlConvertorByXPath
     2     {
     3         public static Hashtable Convertor1(string xml, string path1, string path2)
     4         {
     5             System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();
     6             xmlDoc.LoadXml(xml);
     7             if (xmlDoc.SelectSingleNode(path1) == null) return null;
     8             var nodeList1 = xmlDoc.SelectSingleNode(path1).ChildNodes;
     9             var nodeList2 = xmlDoc.SelectSingleNode(path2).ChildNodes;
    10             Hashtable hash = new Hashtable();
    11             if (nodeList1.Count != nodeList2.Count)
    12             {
    13                 return null;
    14             }
    15             else
    16             {
    17                 for (int i = 0; i < nodeList1.Count; i++)
    18                 {
    19                     var key = nodeList1[i].Name;
    20                     var value = !string.IsNullOrEmpty(nodeList2[i].InnerText) ? nodeList2[i].InnerText : "";
    21                     hash.Add(key, value);
    22                 }
    23                 return hash;
    24             }
    25         }
    26         public static List<Hashtable> Convertor2(string xml, string path1, string path2,string path3)
    27         {
    28             System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();
    29             xmlDoc.LoadXml(xml);            
    30             if (xmlDoc.SelectSingleNode(path1) == null) return null;
    31             XmlNodeList xmlNodeList = xmlDoc.SelectNodes(path2);
    32             if (0 == xmlNodeList.Count) return null;
    33             var nodeList1 = xmlDoc.SelectSingleNode(path1).ChildNodes;
    34             var nodeList2 = xmlDoc.SelectSingleNode(path3).ChildNodes;
    35             List<Hashtable> hashList = new List<Hashtable>();
    36             for (int i = 0; i < xmlNodeList.Count; i++)
    37             {
    38                 Hashtable hash = new Hashtable();
    39                 var nodes2 = xmlNodeList[i].ChildNodes;
    40                 if (nodes2.Count != nodeList1.Count)
    41                     continue;
    42                 for (int j = 0; j < nodes2.Count; j++)
    43                 {
    44                     var key = nodeList1[j].Name;
    45                     var value = !string.IsNullOrEmpty(nodes2[j].InnerText) ? nodes2[j].InnerText : "";
    46                     hash.Add(key, value);
    47                 }
    48                 for (int k = 0; k < nodeList2.Count; k++) {
    49                     var key = nodeList2[k].Name;
    50                     var value = !string.IsNullOrEmpty(nodeList2[k].InnerText) ? nodeList2[k].InnerText : "";
    51                     hash.Add(key,value);
    52                 }
    53                 hashList.Add(hash);
    54             }
    55             return hashList;
    56         }
    57     }

      目的很简单,就是将xml数据转换为可以按键取值的形式,当然前提是返回的字段名称不重复,且有一定的语义。希望对遇到类似问题的朋友有所帮助。

  • 相关阅读:
    webstrom破解的问题
    redis高级应用(1)
    linux之软链接、硬链接
    爬虫之scrapy、scrapy-redis
    爬虫之xpath、selenuim
    爬虫之Beautifulsoup模块
    爬虫之Reuqests模块使用
    测试项目配置
    Cleary基础
    Redis基础
  • 原文地址:https://www.cnblogs.com/Lightmen/p/5097462.html
Copyright © 2011-2022 走看看