c# - 如何从 C# 中的 Soap 响应中提取数据
问题描述
以下是我用来从中提取数据的函数的一部分。
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<MP0118_GetGridHeaderData_001_Result xmlns="http://schemas.datastream.net/MP_functions/MP0118_GetGridHeaderData_001_Result">
<GRIDRESULT type="LIST.HEAD_DATA.STORED">
<DATA jsonclass="array">
<ROW id="1">
<D n="6721">10128</D>
<D n="6724">CL</D>
<D n="6771">*</D>
<D n="6773">ACT</D>
<D n="6774">PHON</D>
<D n="6775">04-MAR-2018 21:54</D>
<D n="6779">MEP-IU</D>
<D n="6780">MEP-IU-010</D>
<D n="6782">CWP2B19-113</D>
<D n="6792">11410</D>
<D n="6809"/>
<D n="6880"/>
<D n="11651">Tap is not working in the Back of the Apt </D>
<D n="100410">40977</D>
<D n="101312">AHMED.ALI@MERAAS.AE</D>
<D n="101313">HANDOVER</D>
</ROW>
<ROW id="2">
<D n="6721">10132</D>
<D n="6724">CL</D>
<D n="6771">*</D>
<D n="6773">ACT</D>
<D n="6774">PHON</D>
<D n="6775">05-MAR-2018 11:27</D>
<D n="6779">GENERAL</D>
<D n="6780">GENERAL-005</D>
<D n="6782">CWP2B17-303</D>
<D n="6792"/>
<D n="6809"/>
<D n="6880"/>
<D n="11651">Flat 303, 304, 305 and 307 asking for Water Activation. Reporter is property manager. Please do the needful.</D>
<D n="100410">40981</D>
<D n="101312">AHMED.ELSHAHD@MERAAS.AE</D>
<D n="101313">CAM</D>
</ROW>
<ROW id="3">
<D n="6721">10177</D>
<D n="6724">CL</D>
<D n="6771">*</D>
<D n="6773">ACT</D>
<D n="6774">PHON</D>
<D n="6775">06-MAR-2018 14:41</D>
<D n="6779">MEP-IU</D>
<D n="6780">MEP-IU-006</D>
<D n="6782">CWP2B19-605</D>
<D n="6792">10600</D>
<D n="6809"/>
<D n="6880"/>
<D n="11651">City Walk Building 19, APT 605, The drainage inside whole apartment is smelling bad</D>
<D n="100410">41026</D>
<D n="101312">MOHAMED.SAEED@MERAAS.AE</D>
<D n="101313">HANDOVER</D>
</ROW>
</DATA>
<FIELDS viewtype="LIST" visibleColumn="true" visiblerowcount="">
<FIELD aliasnum="6721" control="text" filterable="+" keyfield="+" label="ctr_code" lookup="" name="ctr_code" order="1" type="VARCHAR" visible="+" width="180"/>
<FIELD aliasnum="6792" control="text" filterable="+" keyfield="-" label="ctr_contactinfoid" lookup="" name="ctr_contactinfoid" order="2" type="VARCHAR" visible="+" width="180"/>
<FIELD aliasnum="6809" control="text" filterable="+" keyfield="-" label="ctr_contactnote" lookup="" name="ctr_contactnote" order="3" type="MIXVARCHAR" visible="+" width="180"/>
<FIELD aliasnum="6774" control="text" filterable="+" keyfield="-" label="ctr_contactsource" lookup="" name="ctr_contactsource" order="4" type="VARCHAR" visible="+" width="180"/>
<FIELD aliasnum="6775" control="text" filterable="+" keyfield="-" label="ctr_created" lookup="" name="ctr_created" order="5" type="DATETIME" visible="+" width="180"/>
<FIELD aliasnum="101312" control="text" filterable="+" keyfield="-" label="ctr_createdby" lookup="" name="ctr_createdby" order="6" type="VARCHAR" visible="+" width="180"/>
<FIELD aliasnum="6880" control="text" filterable="+" keyfield="-" label="ctr_desc" lookup="" name="ctr_desc" order="7" type="MIXVARCHAR" visible="+" width="180"/>
<FIELD aliasnum="100410" control="text" filterable="+" keyfield="-" label="ctr_event" lookup="" name="ctr_event" order="8" type="VARCHAR" visible="+" width="180"/>
<FIELD aliasnum="101313" control="text" filterable="+" keyfield="-" label="ctr_mrc" lookup="" name="ctr_mrc" order="9" type="VARCHAR" visible="+" width="180"/>
<FIELD aliasnum="11651" control="text" filterable="+" keyfield="-" label="ctr_note" lookup="" name="ctr_note" order="10" type="MIXVARCHAR" visible="+" width="180"/>
<FIELD aliasnum="6782" control="text" filterable="+" keyfield="-" label="ctr_object" lookup="" name="ctr_object" order="11" type="VARCHAR" visible="+" width="180"/>
<FIELD aliasnum="6771" control="text" filterable="+" keyfield="-" label="ctr_org" lookup="" name="ctr_org" order="12" type="VARCHAR" visible="+" width="180"/>
<FIELD aliasnum="6779" control="text" filterable="+" keyfield="-" label="ctr_servicecategory" lookup="" name="ctr_servicecategory" order="13" type="VARCHAR" visible="+" width="180"/>
<FIELD aliasnum="6780" control="text" filterable="+" keyfield="-" label="ctr_serviceproblem" lookup="" name="ctr_serviceproblem" order="14" type="VARCHAR" visible="+" width="180"/>
<FIELD aliasnum="6724" control="text" filterable="+" keyfield="-" label="ctr_status" lookup="" name="ctr_status" order="15" type="VARCHAR" visible="+" width="180"/>
<FIELD aliasnum="6773" control="text" filterable="+" keyfield="-" label="ctr_type" lookup="" name="ctr_type" order="16" type="VARCHAR" visible="+" width="180"/>
</FIELDS>
</GRID>
</GRIDRESULT>
</MP0118_GetGridHeaderData_001_Result>
</soapenv:Body>
</soapenv:Envelope>
这是我用来过滤数据的代码,
#region Namespaces
using System;
using System.Data;
using System.IO;
using System.Net;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
#endregion
/// <summary>
/// This is the class to which to add your code. Do not change the name, attributes, or parent
/// of this class.
/// </summary>
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
public override void PreExecute()
{
base.PreExecute();
}
public override void PostExecute()
{
base.PostExecute();
}
public override void CreateNewOutputRows()
{
IvokeAPICalls(Variables.CRMAPIEndPoint1, Variables.CRMSoapRequest1);
}
private static void IvokeAPICalls(string APIEndPoint, string XmlRequest)
{
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
HttpWebRequest httpWebRequest = (HttpWebRequest)(WebRequest.Create(APIEndPoint));
httpWebRequest.Headers.Add(@"SOAP:Action");
httpWebRequest.ContentType = "text/xml;charset=\"utf-8\"";
httpWebRequest.Accept = "text/xml";
httpWebRequest.Method = "POST";
httpWebRequest.Timeout = 99999999;
var fileContent = File.ReadAllText(XmlRequest);
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(fileContent);//.Replace("@StartDate", StartDate).Replace("@EndDate", EndDate).Replace("@Operations", Operations);
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(stringBuilder.ToString());
using (Stream stream = httpWebRequest.GetRequestStream())
{
xmlDocument.Save(stream);
}
using (WebResponse response = httpWebRequest.GetResponse())
{
using (StreamReader streamreader = new StreamReader(response.GetResponseStream()))
{
string result1 = streamreader.ReadToEnd();
MessageBox.Show(result1);
//Method1
//xmlDocument = new XmlDocument();
xmlDocument.LoadXml(result1);
//foreach (XmlElement xmlElement in xmlDocument.DocumentElement.SelectNodes("//DATA/ROW[*]"))
foreach (XmlElement xmlElement in xmlDocument.DocumentElement.SelectNodes("//GRIDRESULT/GRID/DATA/ROW[*]"))
{
Console.WriteLine(xmlElement.OuterXml);
//MessageBox.Show(xmlElement.OuterXml);
string result2 = streamreader.ReadToEnd();
}
//Method2
XmlDocument xmlDoc1 = new XmlDocument();
xmlDoc.LoadXml(result1);
XmlNamespaceManager xmlnsManager = new System.Xml.XmlNamespaceManager(xmlDoc1.NameTable);
xmlnsManager.AddNamespace("soapenv", "http://schemas.xmlsoap.org/soap/envelope/");
xmlnsManager.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
xmlnsManager.AddNamespace("xsd", "http://www.w3.org/2001/XMLSchema");
xmlnsManager.AddNamespace("si", "http://schemas.datastream.net/MP_functions/MP0118_GetGridHeaderData_001_Result");
XmlNode node = xmlDoc.SelectSingleNode("//si:DATA/ROW[*]", xmlnsManager);
string name = node.InnerText;
}
}
}
}
这就是我试图过滤数据的方法。但我没有得到。
我想从响应中提取所有记录的列表。我不确定如何编写代码来过滤数据。
我想从这个soap响应exml中获取数据我尝试了xml节点xpath但没有用。请帮助获取数据
解决方案
从提供的 XML 来看,它似乎分为两部分,行和字段。
字段只是行的定义。因此,您需要做的是使用每个字段的aliasnum
and 和name
andtype
的字段创建一个类模型。例如这个:
<FIELD aliasnum="6721" control="text" filterable="+" keyfield="+" label="ctr_code" lookup="" name="ctr_code" order="1" type="VARCHAR" visible="+" width="180"/>
将转换为:
public class SoapField
{
public string Aliasnum { get; set; }
public string Name { get; set; }
}
这里我们只取了 Aliasnum 和 Name,它们将存储aliasnum
和name
. 这两个是我们映射行所需要的。
现在,获取name
属性列表,我们将基于它为行创建另一个类模型。
public class SoapRow
{
public string Id { get; set; }
public string Code { get; set; }
public string ContactInfoId { get; set; }
public string ContactNote { get; set; }
public string ContactSource { get; set; }
}
现在您需要两个循环,一个用于读取这些字段,另一个用于读取行。
我已将 XML 减少到四个字段,仅用于演示目的,您需要根据需要完成其余部分。例子 :
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<MP0118_GetGridHeaderData_001_Result xmlns="http://schemas.datastream.net/MP_functions/MP0118_GetGridHeaderData_001_Result">
<GRIDRESULT type="LIST.HEAD_DATA.STORED">
<GRID>
<DATA jsonclass="array">
<ROW id="1">
<D n="6721">10128</D> <!-- code -->
<D n="6792">11410</D> <!-- contactinfoid -->
<D n="6809"/> <!-- contactnote -->
<D n="6774">PHON</D> <!-- contactsource -->
</ROW>
</DATA>
<FIELDS viewtype="LIST" visibleColumn="true" visiblerowcount="">
<FIELD aliasnum="6721" control="text" filterable="+" keyfield="+" label="ctr_code" lookup="" name="ctr_code" order="1" type="VARCHAR" visible="+" width="180"/>
<FIELD aliasnum="6792" control="text" filterable="+" keyfield="-" label="ctr_contactinfoid" lookup="" name="ctr_contactinfoid" order="2" type="VARCHAR" visible="+" width="180"/>
<FIELD aliasnum="6809" control="text" filterable="+" keyfield="-" label="ctr_contactnote" lookup="" name="ctr_contactnote" order="3" type="MIXVARCHAR" visible="+" width="180"/>
<FIELD aliasnum="6774" control="text" filterable="+" keyfield="-" label="ctr_contactsource" lookup="" name="ctr_contactsource" order="4" type="VARCHAR" visible="+" width="180"/>
</FIELDS>
</GRID>
</GRIDRESULT>
</MP0118_GetGridHeaderData_001_Result>
</soapenv:Body>
</soapenv:Envelope>
然后使用上面的类我们可以做到这一点:
var rowsList = new List<SoapRow>();
var fieldsList = new List<SoapField>();
//use XDocument instead of xmlDocument it's simpler and works very well with LINQ.
var doc = XDocument.Parse(xml);
// declare the namespace
var ns = doc.Root.GetNamespaceOfPrefix("soapenv");
// get Body
var body = doc.Descendants(ns + "Body").Elements();
// get MP0118_GetGridHeaderData_001_Result
var gridresultheader = body.ElementAt(0).Elements();
// get GRIDRESULT
var gridresult = gridresultheader.ElementAt(0).Elements();
// get GRID
var grid = gridresult.ElementAt(0).Elements();
// get DATA
var rows = grid.ElementAt(0).Elements();
// get FIELDS
var fields = grid.ElementAt(1).Elements();
// define the fields first
foreach(var field in fields)
{
fieldsList.Add(
new SoapField()
{
Aliasnum = field.Attribute("aliasnum").Value.Trim(),
Name = field.Attribute("name").Value.Substring(4).Trim() //get the name without (ctr_)
}
);
}
// now loop over the rows, and map them to the fields.
foreach (var row in rows)
{
// get the row id
var id = row.Attribute("id").Value.Trim();
//get the row elements
var d = row.Elements();
//set the row id first
var dataRow = new SoapRow
{
Id = id
};
// go over each element in the row
foreach (var element in d)
{
// get the row n attribute
var n = element.Attribute("n").Value.Trim();
// get the name of this element by the n attribute from the fields definition.
var name = fieldsList.Where(e => e.Aliasnum == n).Select(x => x.Name).First();
// now just map it using a simple switch statment.
switch(name)
{
case "code":
dataRow.Code = element.Value.Trim();
break;
case "contactinfoid":
dataRow.ContactInfoId = element.Value.Trim();
break;
case "contactnote":
dataRow.ContactNote = element.Value.Trim();
break;
case "contactsource":
dataRow.ContactSource = element.Value.Trim();
break;
}
}
// add the row results into the list
rowsList.Add(dataRow);
}
结果将在rowsList
.
代码可以进一步简化,但我想尽可能清楚地显示每个步骤。
推荐阅读
- javascript - 使用 Apollo 和 Nuxt 测试 VueJS fetch()
- javascript - 如何在 javascript 中按字母顺序打印此列表?
- mongodb - 从 kubernetes 集群外部访问 mongodb 副本集
- python-3.x - 如何更改输出结果显示
- javascript - 在不标记 DOM 的情况下获取 id 的值
- http - golang发送请求时偶尔报错400
- javascript - 在 Electron 中处理 UNC 路径和“映射网络驱动器”?
- android - 如何解决这个颤动的代码配音问题?
- javascript - 处理 Firebase 身份验证
- node.js - 使用 express.static 后 EJS 文件未加载