You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将动态调用SOAP WebService的XML结果转回原始DataTable类型?

解决ASMX WebService返回SOAP XML转DataTable的问题

你有一个ASMX WebService(FoodWs.asmx),其WebMethod RetrieveData 返回DataTable类型数据,通过动态调用未添加Web引用的方式获取到了SOAP结果的XML字符串soapResult,需要将其转换为原始的DataTable类型。

注意:你的WebMethod代码中存在列名拼写错误——定义列时写了Prrice,但赋值用的是Price,建议统一为Price,否则会导致数据写入失败或解析异常。


方案一:利用DataSet.ReadXml直接解析(优先推荐)

ASMX返回的DataTable在SOAP中的结构完全符合DataSet的XML规范,因此可以直接用DataSet.ReadXml快速解析,无需手动处理节点:

修改你的Execute方法如下:

public static void Execute()
{
    HttpWebRequest request = CreateWebRequest();
    XmlDocument soapEnvelopeXml = new XmlDocument();
    soapEnvelopeXml.LoadXml(@"<?xml version=""1.0"" encoding=""utf-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/"">
              <soap:Body>
                <RetrieveData xmlns=""http://tempuri.org/"" />
              </soap:Body>
            </soap:Envelope>");

    using (Stream stream = request.GetRequestStream())
    {
        soapEnvelopeXml.Save(stream);
    }

    using (WebResponse response = request.GetResponse())
    {
        using (StreamReader rd = new StreamReader(response.GetResponseStream()))
        {
            string soapResult = rd.ReadToEnd();
            
            // 核心解析逻辑
            DataSet ds = new DataSet();
            using (XmlReader reader = XmlReader.Create(new StringReader(soapResult)))
            {
                // 定位到返回结果的节点(跳过SOAP信封和Body)
                reader.ReadToFollowing("RetrieveDataResult", "http://tempuri.org/");
                // 读取节点内的XML到DataSet
                ds.ReadXml(reader.ReadSubtree());
            }
            
            // 第一个表就是目标DataTable
            DataTable resultDt = ds.Tables[0];
            
            // 测试输出(可替换为你的业务逻辑)
            foreach (DataRow row in resultDt.Rows)
            {
                HttpContext.Current.Response.Write($"Name: {row["Name"]}, Price: {row["Price"]}<br/>");
            }
        }
    }
}

方案二:手动解析XmlDocument构建DataTable(精细控制场景)

如果需要自定义解析逻辑,可以手动遍历XML节点构建DataTable:

public static void Execute()
{
    HttpWebRequest request = CreateWebRequest();
    XmlDocument soapEnvelopeXml = new XmlDocument();
    soapEnvelopeXml.LoadXml(@"<?xml version=""1.0"" encoding=""utf-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/"">
              <soap:Body>
                <RetrieveData xmlns=""http://tempuri.org/"" />
              </soap:Body>
            </soap:Envelope>");

    using (Stream stream = request.GetRequestStream())
    {
        soapEnvelopeXml.Save(stream);
    }

    using (WebResponse response = request.GetResponse())
    {
        using (StreamReader rd = new StreamReader(response.GetResponseStream()))
        {
            string soapResult = rd.ReadToEnd();
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(soapResult);
            
            // 设置命名空间管理器(必须匹配SOAP中的命名空间)
            XmlNamespaceManager nsMgr = new XmlNamespaceManager(doc.NameTable);
            nsMgr.AddNamespace("soap", "http://schemas.xmlsoap.org/soap/envelope/");
            nsMgr.AddNamespace("temp", "http://tempuri.org/");
            nsMgr.AddNamespace("diffgr", "urn:schemas-microsoft-com:xml-diffgram-v1");
            nsMgr.AddNamespace("msdata", "urn:schemas-microsoft-com:xml-msdata");
            
            // 定位到DataTable的实际数据节点
            XmlNode dataNode = doc.SelectSingleNode("//diffgr:diffgram/msdata:DataSet/temp:Food", nsMgr);
            if (dataNode != null)
            {
                DataTable dt = new DataTable("Food");
                // 添加列(根据实际节点类型调整)
                dt.Columns.Add("Name", typeof(string));
                dt.Columns.Add("Price", typeof(int));
                
                // 遍历行节点填充数据
                XmlNodeList rowNodes = dataNode.SelectNodes("temp:Food", nsMgr);
                foreach (XmlNode rowNode in rowNodes)
                {
                    DataRow dr = dt.NewRow();
                    dr["Name"] = rowNode.SelectSingleNode("temp:Name", nsMgr).InnerText;
                    dr["Price"] = int.Parse(rowNode.SelectSingleNode("temp:Price", nsMgr).InnerText);
                    dt.Rows.Add(dr);
                }
                
                // 测试输出
                foreach (DataRow row in dt.Rows)
                {
                    HttpContext.Current.Response.Write($"Name: {row["Name"]}, Price: {row["Price"]}<br/>");
                }
            }
        }
    }
}

关键注意事项

  • 必须正确匹配SOAP中的命名空间,ASMX默认使用http://tempuri.org/作为服务命名空间
  • 方案一的DataSet.ReadXml会自动处理列类型和数据格式,效率更高且不易出错,优先使用
  • 若WebMethod返回多个DataTable,DataSet会自动生成对应数量的表,可通过表名或索引获取

内容的提问来源于stack exchange,提问作者Raymond Morphy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 00:15:37