【问题标题】:Parse XML in c# with XMLReader for multiple similar Nodes使用 XMLReader 在 c# 中解析 XML 以获取多个相似的节点
【发布时间】:2015-01-09 12:22:50
【问题描述】:

我收到了肥皂服务的回复。它看起来像:

<ArrayOfPaymentHistory_ST xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/">
  <PaymentHistory_ST>
    <tTRANSDATE>2015-01-05T08:58:17</tTRANSDATE>
    <tPAIDTO>2015-02-01T00:00:00</tPAIDTO>
    <dAMOUNT>110</dAMOUNT>
    <dBALANCE>0</dBALANCE>
    <TRANSKIND>Auto CC Payment</TRANSKIND>
    <csUnit>Lee</csUnit>
  </PaymentHistory_ST>
  <PaymentHistory_ST>
    <tTRANSDATE>2015-01-01T08:58:17</tTRANSDATE>
    <tPAIDTO>2015-01-01T00:00:00</tPAIDTO>
    <dAMOUNT>-110</dAMOUNT>
    <dBALANCE>110</dBALANCE>
    <TRANSKIND>Rent Posted</TRANSKIND>
    <csUnit>Lee</csUnit>
  </PaymentHistory_ST>
</ArrayOfPaymentHistory_ST>


我已经定义了一个这样的模型:

public class payment_history
{
    public DateTime tTRANSDATE { get; set; }
    public DateTime tPAIDTO { get; set; }
    public double dAMOUNT { get; set; }
    public double dBALANCE { get; set; }
    public string TRANSKIND { get; set; }
}

我正在尝试解析此 XML 响应并列出 payment_history 类型的对象。 然后,我将在我的标记上发送此对象并显示在表格中。 我发现很多关于使用 XMLReader 解析 XML 的帖子。我仍然无法找到一个可以优雅地做到这一点的好解决方案。

这是我的 C# 代码。

List<payment_history> ph = new List<payment_history>();
payment_history p = new payment_history();

            using (WebResponse response = request.GetResponse())
            {
                using (StreamReader rd = new StreamReader(response.GetResponseStream()))
                {
                    string soapResult = rd.ReadToEnd();

                    using (XmlReader reader = XmlReader.Create(new StringReader(soapResult)))
                    {
                        #region parseXML
                        while (reader.Read())
                        {
                            foreach (var el in reader.ReadOuterXml())
                            {
                                if (reader.IsStartElement())
                                {
                                    //return only when you have START tag
                                    switch (reader.Name.ToString())
                                    {
                                        case "tTRANSDATE":
                                            p.tTRANSDATE = Convert.ToDateTime(reader.ReadString());
                                            break;

                                        case "tPAIDTO":
                                            p.tPAIDTO = Convert.ToDateTime(reader.ReadString());
                                            break;

                                        case "dAMOUNT":
                                            p.dAMOUNT = Convert.ToDouble(reader.ReadString());
                                            break;

                                        case "dBALANCE":
                                            p.dBALANCE = Convert.ToDouble(reader.ReadString());
                                            break;
                                        case "TRANSKIND":
                                            p.TRANSKIND = reader.ReadString();
                                            break;
                                    }
                                    ph.Add(p);
                                }
                            }
                        }
                        #endregion
                    }
                }
            }
            return ph;

有人可以指导完成这项工作吗?我是 C# 的新手。任何形式的帮助将不胜感激。


我尝试遵循 LINQ2XML。但不返回任何东西!

ph = XDocument.Parse(soapResult)
                 .Descendants("PaymentHistory_ST")
                 .Select(g => new payment_history
                 {
                     tTRANSDATE = (DateTime)g.Element("tTRANSDATE"),
                     tPAIDTO = (DateTime)g.Element("tPAIDTO"),
                     dAMOUNT = (double)g.Element("dAMOUNT"),
                     dBALANCE = (double)g.Element("dBALANCE"),
                     TRANSKIND = (string)g.Element("TRANSKIND")
                 }).ToList();

【问题讨论】:

  • 大概LINQ2XML会是一个很好的解决方案,但是我还是不知道怎么用!!有谁请指教!!

标签: c# xml object soap linq-to-xml


【解决方案1】:

使用

XDocument doc = XDocument.Load(response.GetResponseStream());
XNamespace df = "http://tempuri.org/";

List<payment_history> ph = doc.Descendants(df + "PaymentHistory_ST")
                 .Select(g => new payment_history
                 {
                     tTRANSDATE = (DateTime)g.Element(df + "tTRANSDATE"),
                     tPAIDTO = (DateTime)g.Element(df + "tPAIDTO"),
                     dAMOUNT = (double)g.Element(df + "dAMOUNT"),
                     dBALANCE = (double)g.Element(df + "dBALANCE"),
                     TRANSKIND = (string)g.Element(df + "TRANSKIND")
                 }).ToList();

【讨论】:

  • 我试过它不工作。奇怪的是它没有给出任何错误,同时“ph”的计数为 0。我验证了该服务返回一个包含许多项目的有效响应..
  • 我添加了一个截图供您参考。请指教。
  • XML 是否比您发布的多?根元素标记&lt;ArrayOfPaymentHistory_ST xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/"&gt; 是否与您的示例中一样?还是有更多包含您发布的示例的元素?
  • 在您的屏幕截图中有更多元素,因此我的代码无法工作,因为它读取了根元素的名称空间,该名称空间应该包含数据的目标名称空间,而在您的屏幕截图中它是一个不同的元素.所以我现在对命名空间进行了硬编码。
  • 在标记为&lt;root xmlns="http://example.com/"&gt;&lt;child&gt;&lt;grand-child/&gt;&lt;/child&gt;&lt;/root&gt;的情况下,所有三个 XML 元素都位于根元素上声明的命名空间中。为了使用 LINQ to XML 选择这样的元素,我们需要构造一个 XName 连接 XNamespace 和一个字符串。详情请见msdn.microsoft.com/en-us/library/bb387093%28v=vs.110%29.aspx
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-13
  • 1970-01-01
  • 2019-04-19
  • 1970-01-01
  • 2012-12-30
相关资源
最近更新 更多