浅谈C#生成解析XML

XML这种格式的字符串一般作为服务器之间的数据交互格式,且应用广泛,是一个已经很成熟的技术。先介绍一下XML是怎么生成的(肯定不是拼字符串拼出来的)。

现在给一个服务器应答的XML常用格式,应答XML报文一般比请求XML报文简单很多:

<RETURNS>
	<RETCODE>0</RETCODE>
	<RETMSG>SUCCESS</RETMSG>
</RETURNS>

这是A服务器向B服务器提交一个请求后,B进行相关的数据处理后并返回给A的处理结果,也是一个XML报文,一般上面这种结果表示B处理成功了。我们怎么生成一个这样的报文呢?下面上代码:

//创建xml文档
    XmlDocument doc = new XmlDocument();
    //创建节点,节点名称为RETURNS
    XmlElement Root = doc.CreateElement("RETURNS");
    //将这个节点加入文档中
    doc.AppendChild(Root);
    //创建一个名称为RETCODE的节点
    XmlElement child1 = doc.CreateElement("RETCODE");
    //给该节点赋值0
    child1.InnerText = "0";
    //将该节点加入到RETURNS节点下,RETMSG同理
    Root.AppendChild(child1);
    XmlElement child2 = doc.CreateElement("RETMSG");
    child2.InnerText = "SUCCESS";
    Root.AppendChild(child2);
    //将设计好的XML作为字符串输出
    Console.Write(doc.InnerXml);
    Console.Read();

看看生成的结果:
在这里插入图片描述
当A服务器拿到这样的XML后同样需要进行解析。这里需要搞清楚的是,对A服务器来说,它关心的是什么?它只关心B服务器的返回结果怎么样,成功还是失败。如果成功,那么A可能会做后续的事情,如果失败,B会给出失败原因。但B响应完成后,A服务器后面要做什么就跟B服务器没有任何关系了,而且不论是否成功,这个结果一般都会保存到数据库,作为以后的责任认定的依据(虽然DBA可以直接修改,但处理结果一般是双方服务器都会保存的,所以只要双方服务器处理结果不一致基本确定是数据库直接修改的,这个是职业素养问题了,不过多纠结)。

对于返回值RETCODE一般都约定0为处理成功。当然,你想奇葩点把1当做处理成功都是可以的,反正双方技术人员约定好就行了。接下来看一下C#怎么解析XML:
//需要注意,这个xml字符串一定要有声明头,且节点内不允许有空格,如<RETURNS >这样是不允许的

  string response = "<?xml version=\"1.0\" encoding=\"utf - 8\" ?>
    				   <RETURNS>
    				   		<RETCODE>0</RETCODE>
    				   		<RETMSG>SUCCESS</RETMSG>
    				   	</RETURNS>";
    XmlDocument resDoc = new XmlDocument();
    resDoc.InnerXml = response;
    //得到这个xml根节点下所有子节点,比如这里是有2个,第一个为声明头,第二个是RETURNS,我们需要拿到第二个节点
    XmlNodeList xnl = resDoc.ChildNodes;
    Console.WriteLine("节点数量:"+xnl.Count);
    Console.WriteLine("第一个节点名称为:" + xnl.Item(0).Name);
    Console.WriteLine("第二个节点名称为:" + xnl.Item(1).Name);
    Console.ReadLine();

在这里插入图片描述

//解析节点内容,声明头不用管它,从第二个节点开始解析
XmlNode xn=xnl.Item(1);
XmlNodeList returns=xn.ChildNodes;
XmlNode retCode = returns.Item(0);
Console.WriteLine("{0}节点的内容为:{1}", retCode.Name, retCode.InnerText);
XmlNode retMsg = returns.Item(1);
Console.WriteLine("{0}节点的内容为:{1}", retMsg.Name, retMsg.InnerText);
Console.ReadLine();

在这里插入图片描述
一般的情况下,作为双方服务器数据交互格,格式是不会轻易改变的,如果需要更改格式,双方技术人员肯定会做交流,更改解析格式,所以放心解析就好。而且数据是经过加密传输的,形式上肯定不会这么简单,但核心的思想都是这样。然后解析的结果最终一定会保存到数据库,这里就不再做数据存储了。

现在有一个这样的业务场景,比如客户到淘宝上买了一样东西,OMS对应的商户接收到客户数据,该商户的实物实际在WMS进行存储,并且已经与指定的WMS对接完毕,那么该数据组织好后会由OMS平台向WMS发起请求,请求XML如下:

<?xml version="1.0" encoding="utf - 8" ?>
<REQUEST>
	<ORDERS>
		<ORDER>
			<ORDERHEAD>															//订单头部信息
				<ORDERID>PTB201903291049233</ORDERID>	//OMS订单号
				<STORERID>LDT</STORERID>								//商户商标
				<ADDDATE>2019-03-29 10:51:00</ADDDATE>		//订单生成时间
				<CONSIGNEEID>路人甲</CONSIGNEEID>				//客户姓名
				<MOBILE>13333333333</MOBILE>						//客户电话
				<ADDRESS>天国1路</ADDRESS>							//客户地址
			</ORDERHEAD>
			<ORDERDETAIL>														//订单详细信息
				<ORDER>
    				<ORDERID>PTB201903291049233</ORDERID>	//对应订单的编号
    				<ITEMID>GB2312</ITEMID>									//货品编号
    				<ITEMNAME>振动棒</ITEMNAME>							//货品名称
    				<COUNT>2</COUNT>											//购买的数量
				</ORDER>
				<ORDER>
    				<ORDERID>PTB201903291049233</ORDERID>	//对应订单的编号
    				<ITEMID>UTF8</ITEMID>									//货品编号
    				<ITEMNAME>双头龙</ITEMNAME>							//货品名称
    				<COUNT>1</COUNT>											//购买的数量
				</ORDER>
			</ORDERDETAIL>
		</ORDER>
	</ORDERS>
</REQUEST>

这段XML就相对复杂一些,但解析思想还是这样。事实上,A服务器发起的这一段XML请求一定是经过加密的,B服务器得到的是一串密文。在服务器对接的时候,先有一个用户授权,双方做服务器交互会用一个约定的秘钥进行加解密,主要用于XML防篡改。简单的说就是,一个真正的业务绝对不会有这么简单的XML。我们尝试解析这段XML

string requestXML="<?xml version=\"1.0\" encoding=\"utf - 8\" ?><REQUEST><ORDERS><ORDER><ORDERHEAD><ORDERID>PTB201903291049233</ORDERID><STORERID>LDT</STORERID><ADDDATE>2019-03-29 10:51:00</ADDDATE><CONSIGNEEID>路人甲</CONSIGNEEID><MOBILE>13333333333</MOBILE><ADDRESS>天国1路</ADDRESS></ORDERHEAD><ORDERDETAIL><ORDER><ORDERID>PTB201903291049233</ORDERID><ITEMID>GB2312</ITEMID><ITEMNAME>振动棒</ITEMNAME><COUNT>2</COUNT></ORDER><ORDER><ORDERID>PTB201903291049233</ORDERID><ITEMID>UTF8</ITEMID><ITEMNAME>双头龙</ITEMNAME><COUNT>1</COUNT></ORDER></ORDERDETAIL></ORDER></ORDERS></REQUEST>";
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.InnerXml = requestXML;
XmlNodeList xmlNodeList=xmlDocument.ChildNodes;
//拿到ORDERS节点,这里才是数据真正存在的节点,一个XML实际上不止传一个订单,肯定需要支持多订单解析,读者根据实际XML自行判断该从哪里开始解析
XmlNode requestNode = xmlNodeList.Item(1);
XmlNode ordersNode=requestNode.ChildNodes.Item(0);             //这里拿到ORDERS节点
Console.WriteLine("开始解析{0}节点",ordersNode.Name);
XmlNodeList orderList = ordersNode.ChildNodes;                 //获取ORDERS节点下的所有节点

for(int i=0;i<orderList.Count;i++)
{
	XmlNode order = orderList.Item(i);
    Console.WriteLine("解析ORDERHD");
    XmlNode orderHeadNode = order.ChildNodes.Item(0);
    XmlNodeList orderHeadNodeNext = orderHeadNode.ChildNodes;
    for (int j=0;j<orderHeadNodeNext.Count;j++)
    {
    	Console.WriteLine(orderHeadNodeNext.Item(j).Name + ":" + orderHeadNodeNext.Item(j).InnerText);
    }
    Console.WriteLine();
    Console.WriteLine("解析ORDERDETAIL");
    XmlNode orderDetailNode = order.ChildNodes.Item(1);
    XmlNodeList orderDetailNodeNext = orderDetailNode.ChildNodes;
    for(int m=0;m<orderDetailNodeNext.Count;m++)
    {
    	XmlNode detailNode = orderDetailNodeNext.Item(m);
        XmlNodeList detailOrderList = detailNode.ChildNodes;
        for(int n=0;n<detailOrderList.Count;n++)
        {
        	Console.WriteLine(detailOrderList.Item(n).Name+":"+detailOrderList.Item(n).InnerText);
        }
        Console.WriteLine();
        }
    }
    Console.ReadLine();

在这里插入图片描述
如果放在C#里面解析相对来说还是很麻烦的,解析出来之后还需要用一个结构和xml一致的类去保存这些数据,最终会用一个List容器来承载这些数据,然后再保存到数据库中。其实数据库自身也是支持xml解析的,而且逻辑上比使用C#会简单很多,业务处理也方便很多。看读者跟擅长哪块吧。

这里继续,解析出来了肯定不能直接保存的,基本的数据校验还是要的吧,而且给定的xml不是所有的数据都是需要的,而且有些关键性的数据一定要做相关校验,比如订单号和商户编号,我WMS没有接入这个商户编号也传给我?这就是业务校验。读者依据实际业务做相关更改,数据处理完毕再生成响应报文,告诉对方我的处理结果即可。

有时候请求报文不一定是XML,要求使用JSON进行数据交互也是有可能的,这时候就需要进行格式转换再发起请求,有开发者早已封装好相关的功能,我们只需要调用即可完成格式的转换,工具类名称叫Newtonsoft.Json.dll,该资源已上传,有需要的读者自行下载。将下载的工具类放入自己的项目文件夹中,添加该dll引用即可使用。
下面给出使用方法

string requestXML = "<?xml version=\"1.0\" encoding=\"utf - 8\" ?><REQUEST><ORDERS><ORDER><ORDERHEAD><ORDERID>PTB201903291049233</ORDERID><STORERID>LDT</STORERID><ADDDATE>2019-03-29 10:51:00</ADDDATE><CONSIGNEEID>路人甲</CONSIGNEEID><MOBILE>13333333333</MOBILE><ADDRESS>天国1路</ADDRESS></ORDERHEAD><ORDERDETAIL><ORDER><ORDERID>PTB201903291049233</ORDERID><ITEMID>GB2312</ITEMID><ITEMNAME>振动棒</ITEMNAME><COUNT>2</COUNT></ORDER><ORDER><ORDERID>PTB201903291049233</ORDERID><ITEMID>UTF8</ITEMID><ITEMNAME>双头龙</ITEMNAME><COUNT>1</COUNT></ORDER></ORDERDETAIL></ORDER></ORDERS></REQUEST>";
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.InnerXml = requestXML;
/* 
 * 如果直接传入XmlDocument,最后生成的Json字符串会有Xml声明头,
 * 一般生成的Json字符串应该没有xml声明头的,所以传入的XmlNode要调整一下
 */
string jsonString = JsonConvert.SerializeXmlNode(xmlDocument.ChildNodes.Item(1));
Console.WriteLine(jsonString);
Console.Read();

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值