如何从 C# 中的 SOAP 响应中提取数据
How to extract data from SOAP response in C#
我有以下 SOAP 响应。使用我的代码我只能提取一个元素。
然后它抛出空引用异常错误。
如何在 C# 函数中将 Item->key 和 Item->value 提取到我的字典中?
以下是我用来从中提取数据的函数的一部分。
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP- ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:Magento" xmlns:ns2="http://xml.apache.org/xml-soap" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns1:callResponse>
<callReturn SOAP-ENC:arrayType="ns2:Map[2]" xsi:type="SOAP-ENC:Array">
<item xsi:type="ns2:Map">
<item>
<key xsi:type="xsd:string">state</key>
<value xsi:type="xsd:string">processing</value>
</item>
<item>
<key xsi:type="xsd:string">status</key>
<value xsi:type="xsd:string">processing</value>
</item>
<item>
<key xsi:type="xsd:string">protect_code</key>
<value xsi:type="xsd:string">ba8dd7</value>
</item>
<item>
<key xsi:type="xsd:string">shipping_firstname</key>
<value xsi:type="xsd:string">Roshan</value>
</item>
<item>
<key xsi:type="xsd:string">billing_name</key>
<value xsi:type="xsd:string">Roshan India</value>
</item>
<item>
<key xsi:type="xsd:string">shipping_name</key>
<value xsi:type="xsd:string">Roshan India</value>
</item>
<item>
<key xsi:type="xsd:string">order_id</key>
<value xsi:type="xsd:string">2</value>
</item>
</item>
</callReturn>
</ns1:callResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
代码,
try
{
XmlDocument xdoc = new XmlDocument();//xml doc used for xml parsing
xdoc.LoadXml(content); // --------> THIS IS WHERE I PASS SOAP RESPONSE
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xdoc.NameTable);
nsmgr.AddNamespace("SOAP-ENV:encodingStyle", "http://schemas.xmlsoap.org/soap/encoding/");
XmlNodeList xNodelst = xdoc.DocumentElement.SelectNodes("//item");
int nodes = xNodelst.Count;
dynamic item;
Dictionary<string, string> items = new Dictionary<string, string>();
foreach (XmlNode xn in xNodelst)
{
XmlNode itemnode = xn["item"];
if (itemnode != null) {
string key = itemnode["key"].InnerText;
string value = itemnode["value"].InnerText;
items.Add(key, value);
}
}
var ss = items;
return "";
}
catch (Exception e) {
return e.Message;
}
xml有两层标签项。因此,您必须确保分别对待项目标签的每个级别。我使用 xml linq 获取数据并将结果放入字典。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XElement root = doc.Root;
XNamespace ns = root.GetDefaultNamespace();
XElement firstItem = doc.Descendants(ns + "item").FirstOrDefault();
Dictionary<string, string> dictItems = firstItem.Descendants(ns + "item")
.GroupBy(x => (string)x.Element("key"), y => (string)y.Element("value"))
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
}
}
}
我终于成功完成了这项工作。我在名称空间管理器变量中添加了所有名称空间。并使用 xPath 在 XML 中导航,如下所示,
XmlNodeList xNodelst = xdoc.DocumentElement.SelectNodes("//item[@xsi:type]",nsmgr);
这帮助我解决了我的问题。如果有人遇到类似问题,我会在这里发布。
干杯!
string soapString = @"<soapenv:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:urn=""urn:Magento""><soapenv:Header/><soapenv:Body><urn:call soapenv:encodingStyle=""http://schemas.xmlsoap.org/soap/encoding/""><sessionId xsi:type=""xsd:string"">"+ssid +@"</sessionId><resourcePath xsi:type=""xsd:string"">sales_order.list</resourcePath><args xsi:type=""xsd:anyType""></args></urn:call></soapenv:Body></soapenv:Envelope>";
HttpResponseMessage response = await PostXmlRequest("http://localhost/M1/api.php", soapString);
string content = await response.Content.ReadAsStringAsync();
XmlDocument xdoc = new XmlDocument();//xml doc used for xml parsing
xdoc.LoadXml(content);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xdoc.NameTable);
nsmgr.AddNamespace("ns1", "urn:Magento");
nsmgr.AddNamespace("ns2", "http://xml.apache.org/xml-soap");
nsmgr.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
nsmgr.AddNamespace("xsd", "http://www.w3.org/2001/XMLSchema");
nsmgr.AddNamespace("SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/");
nsmgr.AddNamespace("encodingStyle", "http://schemas.xmlsoap.org/soap/encoding/");
XmlNodeList xNodelst = xdoc.DocumentElement.SelectNodes("//item[@xsi:type]",nsmgr);
int nodes = xNodelst.Count;
Dictionary<int, IDictionary> items = new Dictionary<int, IDictionary>();
int n = 0;
foreach (XmlNode xn in xNodelst)
{
XmlNode itemnode = xn;
Dictionary<string, string> itemData = new Dictionary<string, string>();
foreach (XmlNode xn1 in itemnode)
{
string key = xn1["key"].InnerText;
string value = xn1["value"].InnerText;
itemData.Add(key, value);
}
items.Add(n, itemData);
n++;
}
return items;
我有以下 SOAP 响应。使用我的代码我只能提取一个元素。 然后它抛出空引用异常错误。
如何在 C# 函数中将 Item->key 和 Item->value 提取到我的字典中?
以下是我用来从中提取数据的函数的一部分。
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP- ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:Magento" xmlns:ns2="http://xml.apache.org/xml-soap" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns1:callResponse>
<callReturn SOAP-ENC:arrayType="ns2:Map[2]" xsi:type="SOAP-ENC:Array">
<item xsi:type="ns2:Map">
<item>
<key xsi:type="xsd:string">state</key>
<value xsi:type="xsd:string">processing</value>
</item>
<item>
<key xsi:type="xsd:string">status</key>
<value xsi:type="xsd:string">processing</value>
</item>
<item>
<key xsi:type="xsd:string">protect_code</key>
<value xsi:type="xsd:string">ba8dd7</value>
</item>
<item>
<key xsi:type="xsd:string">shipping_firstname</key>
<value xsi:type="xsd:string">Roshan</value>
</item>
<item>
<key xsi:type="xsd:string">billing_name</key>
<value xsi:type="xsd:string">Roshan India</value>
</item>
<item>
<key xsi:type="xsd:string">shipping_name</key>
<value xsi:type="xsd:string">Roshan India</value>
</item>
<item>
<key xsi:type="xsd:string">order_id</key>
<value xsi:type="xsd:string">2</value>
</item>
</item>
</callReturn>
</ns1:callResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
代码,
try
{
XmlDocument xdoc = new XmlDocument();//xml doc used for xml parsing
xdoc.LoadXml(content); // --------> THIS IS WHERE I PASS SOAP RESPONSE
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xdoc.NameTable);
nsmgr.AddNamespace("SOAP-ENV:encodingStyle", "http://schemas.xmlsoap.org/soap/encoding/");
XmlNodeList xNodelst = xdoc.DocumentElement.SelectNodes("//item");
int nodes = xNodelst.Count;
dynamic item;
Dictionary<string, string> items = new Dictionary<string, string>();
foreach (XmlNode xn in xNodelst)
{
XmlNode itemnode = xn["item"];
if (itemnode != null) {
string key = itemnode["key"].InnerText;
string value = itemnode["value"].InnerText;
items.Add(key, value);
}
}
var ss = items;
return "";
}
catch (Exception e) {
return e.Message;
}
xml有两层标签项。因此,您必须确保分别对待项目标签的每个级别。我使用 xml linq 获取数据并将结果放入字典。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XElement root = doc.Root;
XNamespace ns = root.GetDefaultNamespace();
XElement firstItem = doc.Descendants(ns + "item").FirstOrDefault();
Dictionary<string, string> dictItems = firstItem.Descendants(ns + "item")
.GroupBy(x => (string)x.Element("key"), y => (string)y.Element("value"))
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
}
}
}
我终于成功完成了这项工作。我在名称空间管理器变量中添加了所有名称空间。并使用 xPath 在 XML 中导航,如下所示,
XmlNodeList xNodelst = xdoc.DocumentElement.SelectNodes("//item[@xsi:type]",nsmgr);
这帮助我解决了我的问题。如果有人遇到类似问题,我会在这里发布。
干杯!
string soapString = @"<soapenv:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:urn=""urn:Magento""><soapenv:Header/><soapenv:Body><urn:call soapenv:encodingStyle=""http://schemas.xmlsoap.org/soap/encoding/""><sessionId xsi:type=""xsd:string"">"+ssid +@"</sessionId><resourcePath xsi:type=""xsd:string"">sales_order.list</resourcePath><args xsi:type=""xsd:anyType""></args></urn:call></soapenv:Body></soapenv:Envelope>";
HttpResponseMessage response = await PostXmlRequest("http://localhost/M1/api.php", soapString);
string content = await response.Content.ReadAsStringAsync();
XmlDocument xdoc = new XmlDocument();//xml doc used for xml parsing
xdoc.LoadXml(content);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xdoc.NameTable);
nsmgr.AddNamespace("ns1", "urn:Magento");
nsmgr.AddNamespace("ns2", "http://xml.apache.org/xml-soap");
nsmgr.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
nsmgr.AddNamespace("xsd", "http://www.w3.org/2001/XMLSchema");
nsmgr.AddNamespace("SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/");
nsmgr.AddNamespace("encodingStyle", "http://schemas.xmlsoap.org/soap/encoding/");
XmlNodeList xNodelst = xdoc.DocumentElement.SelectNodes("//item[@xsi:type]",nsmgr);
int nodes = xNodelst.Count;
Dictionary<int, IDictionary> items = new Dictionary<int, IDictionary>();
int n = 0;
foreach (XmlNode xn in xNodelst)
{
XmlNode itemnode = xn;
Dictionary<string, string> itemData = new Dictionary<string, string>();
foreach (XmlNode xn1 in itemnode)
{
string key = xn1["key"].InnerText;
string value = xn1["value"].InnerText;
itemData.Add(key, value);
}
items.Add(n, itemData);
n++;
}
return items;