首页 > 技术文章 > c#利用HTTP发送SOAP请求,并解析包含命名空间前缀的xml数据

PeterCola 2020-03-26 23:24 原文

------------恢复内容开始------------

1.soap简介

soap是用于应用程序间的数据通讯服务,具有跨语言和跨平台的特点,是w3c的推荐标准之一,相比http,具有一定的安全性特点;

可以理解为是基于xml(可扩展标记语言)的http,soap=http+xml;

soap请求实例:

通过这个 http://www.thuwater.com/dataservice/datafetch.asmx;

调用地址进行一些服务方法的获取。

以GetPlaceList方法为例,参照soap协议内容进行服务请求;

 以下是 SOAP 1.1 请求和响应示例。所显示的占位符需替换为实际值。

 1 POST /dataservice/datafetch.asmx HTTP/1.1
 2 Host: 47.105.193.134
 3 Content-Type: text/xml; charset=utf-8
 4 Content-Length: length
 5 SOAPAction: "http://tempuri.org/GetPlaceList"
 6 
 7 <?xml version="1.0" encoding="utf-8"?>
 8 <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
 9   <soap:Body>
10     <GetPlaceList xmlns="http://tempuri.org/">
11       <userName>string</userName>
12       <passwd>string</passwd>
13     </GetPlaceList>
14   </soap:Body>
15 </soap:Envelope>
16 HTTP/1.1 200 OK
17 Content-Type: text/xml; charset=utf-8
18 Content-Length: length
19 
20 <?xml version="1.0" encoding="utf-8"?>
21 <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
22   <soap:Body>
23     <GetPlaceListResponse xmlns="http://tempuri.org/">
24       <GetPlaceListResult>string</GetPlaceListResult>
25     </GetPlaceListResponse>
26   </soap:Body>
27 </soap:Envelope>

以下是 SOAP 1.2 请求和响应示例。所显示的占位符需替换为实际值。相比于SOAP1.1,请求中没有SOAPAction: "http://tempuri.org/GetPlaceList";

 1 POST /dataservice/datafetch.asmx HTTP/1.1
 2 Host: 47.105.193.134
 3 Content-Type: application/soap+xml; charset=utf-8
 4 Content-Length: length
 5 
 6 <?xml version="1.0" encoding="utf-8"?>
 7 <soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
 8   <soap12:Body>
 9     <GetPlaceList xmlns="http://tempuri.org/">
10       <userName>string</userName>
11       <passwd>string</passwd>
12     </GetPlaceList>
13   </soap12:Body>
14 </soap12:Envelope>
15 HTTP/1.1 200 OK
16 Content-Type: application/soap+xml; charset=utf-8
17 Content-Length: length
18 
19 <?xml version="1.0" encoding="utf-8"?>
20 <soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
21   <soap12:Body>
22     <GetPlaceListResponse xmlns="http://tempuri.org/">
23       <GetPlaceListResult>string</GetPlaceListResult>
24     </GetPlaceListResponse>
25   </soap12:Body>
26 </soap12:Envelope>

利用soap进行数请求方法如下;

 1  public static string GetSOAPSourc()
 2             {
 3                   string result = "";
 4                   string responseString = "";
 5                   string requestBody =
 6                         @"<?xml version=""1.0"" encoding=""utf - 8""?>
 7                           <soap12:Envelope xmlns:xsi =""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd =""http://www.w3.org/2001/XMLSchema"" xmlns:soap12 =""http://www.w3.org/2003/05/soap-envelope"" >
 8                           <soap12:Body>
 9                           <GetPlaceList xmlns =""http://tempuri.org/"">
10                           <userName>name</userName>
11                           <passwd>passwd</passwd >
12                            </GetPlaceList>
13                            </soap12:Body>
14                            </soap12:Envelope>";
15                   byte[] postBytes = Encoding.UTF8.GetBytes(requestBody);
16                   HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://www.thuwater.com/dataservice/datafetch.asmx");
17                   req.Method = "POST";
18                   req.ContentType = "text/xml;charset=utf-8";
19                   req.ContentLength = postBytes.Length;
20                   using (Stream reqStream = req.GetRequestStream())
21                   {
22                         reqStream.Write(postBytes, 0, postBytes.Length);
23                   }
24                   using (HttpWebResponse myResponse = (HttpWebResponse)req.GetResponse())
25                   {
26                         StreamReader sr = new StreamReader(myResponse.GetResponseStream(), Encoding.UTF8);
27                         responseString = sr.ReadToEnd();
28                         try
29                         {
30                               XmlDocument doc = new XmlDocument();//新建对象
31                               doc.LoadXml(responseString);//符合xml格式的字符串
32                               dynamic obj = Newtonsoft.Json.JsonConvert.DeserializeObject(doc.InnerText);
33                               string[] equipIds = new string[0];
34                               var equipIdList=equipIds.ToList();
35                               for (int i = 0; i < obj.Value.Count; i++) {
36                                     equipIdList.Add(Convert.ToString(obj.Value[i].EquipID));
37                               }
38                               Console.WriteLine();
39                            
40                         }
41                         catch (Exception e) 
42                         {
43 
44                               return null;
45                         }
46                      
47                   }
48                   return result;
49 
50             }

说明:soap请求中,Content-Type 和ContentLength是必须的;请求的url地址就是获取方法说明的地址;如果利用soap1.2,可以省略请求头部的SOAPAction参数;返回的数据内容,即是前面示例中的相应内容;

2.带有命名空间的xml元素标签解析

命名空间就是为了区分相同元素标签而添加的标识,一般是数据来源或者标准;

 1 <root>
3 <h:table xmlns:h="http://www.w3.org/TR/html4/"> 4 <h:tr> 5 <h:td>Apples</h:td> 6 <h:td>Bananas</h:td> 7 </h:tr> 8 </h:table> 9 10 <f:table xmlns:f="http://www.w3cschool.cc/furniture"> 11 <f:name>African Coffee Table</f:name> 12 <f:width>80</f:width> 13 <f:length>120</f:length> 14 </f:table> 15 16 </root>

还有以下默认的命名空间:

1 <table xmlns="http://www.w3.org/TR/html4/">
2 <tr>
3 <td>Apples</td>
4 <td>Bananas</td>
5 </tr>
6 </table>

 

获取的数据为xml字符串,需要转为xml对象,需要进行解析;

 1  public static void test() {
 2                   //具有命名空间前缀的数据
 3                   string testStr =
 4                         @"<?xml version=""1.0"" encoding=""utf - 8""?>
 5                         <soap12:Envelope xmlns:xsi =""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd =""http://www.w3.org/2001/XMLSchema"" xmlns:soap12 =""http://www.w3.org/2003/05/soap-envelope"" >
 6                          <soap12:Body>
 7                           <GetPlaceList xmlns =""http://tempuri.org/"">
 8                           <userName>string</userName>
 9                          </GetPlaceList>
10                          </soap12:Body>
11                          </soap12:Envelope>";
12                   //普通xml数据
13                   string testStr1 =
14                         @"<?xml version=""1.0"" encoding=""utf - 8""?>
15                          <Envelope>
16                          <Body>
17                          <GetPlaceList>
18                         <userName>data20190070</userName>
19                          <passwd>data20190070@0108</passwd >
20                        </GetPlaceList>
21                         </Body>
22                         </Envelope>";
23 
24                    XmlDocument doc = new XmlDocument();//新建对象
25                   doc.LoadXml(testStr);//符合xml格式的字符串
26                   XmlNamespaceManager nsp = new XmlNamespaceManager(doc.NameTable);//添加默认命名空间名称
27                   nsp.AddNamespace("soap12", "http://www.w3.org/2003/05/soap-envelope");//添加用到的命名空间
28                   nsp.AddNamespace(string.Empty, "http://tempuri.org/");//默认的可以用string.Empty添加
29                   XmlNode root = doc.DocumentElement;//找到根节点,这root就是soap12:Envelope节点了,下面的请求路径不用再添加soap12:Envelope
30                   string nodeString = "soap12:Body/GetPlaceList";//读取节点路径;这里GetPlaceList节点读取不到,是有问题,还在探索中。。。
31                   XmlNodeList nodeList = root.SelectNodes(nodeString, nsp);//读取节点(从root开始读,不是从doc;如果从doc,要加上soap12:Envelope/),如果是有命名空间前缀的,需要添加命名空间
32 
33 
34 
35                   XmlDocument doc1 = new XmlDocument();//新建对象
36                   doc1.LoadXml(testStr1);//符合xml格式的字符串
37                   string nodeString1 = "soap12:Envelope/soap12:Body/GetPlaceList";//读取节点路径;这里GetPlaceList节点读取不到,是有问题,还在探索中。。。
38                   XmlNodeList nodeList1 = doc1.SelectNodes(nodeString1);//读取节点,如果是有命名空间前缀的,需要添加命名空间;这里直接从doc开始读
39 
40                   Console.WriteLine();
41                  
42             }

及时整理;慢慢积累;
























------------恢复内容结束------------

推荐阅读