使用LINQ解析XML字符串,从xml创建新对象

时间:2017-02-02 19:26:08

标签: xml linq object tolist

鉴于以下要求和代码,我还没有找到一个实际有效的答案。

我在SQL Server数据库表中有一个XML字段。它为什么在那里?我不知道。我没有把它放在那里。我只需要将数据输出到List中,我可以将其与另一个List结合使用,以在具有MVVM架构的WPF应用程序中填充网格。
这是List: 列出QAItems = new List();

QADailyXValueCalCheck类型如下:

     using System.Xml.Serialization;

    namespace ConvertXmlToList {
    [XmlRoot(ElementName = "column")]
public class QADailyXValueCalCheck {
[XmlElement] 
public string Regs { get; set; }
    [XmlElement]
    public string BasisTStamp { get; set; }
    [XmlElement]
    public string DAsWriteTStamp { get; set; }
    [XmlElement]
    public string InjEndTime { get; set; }
    [XmlElement]
    public bool Manual { get; set; }
    [XmlElement]
    public decimal RefValue { get; set; }
    [XmlElement]
    public decimal MeasValue { get; set; }
    [XmlElement]
    public string Online { get; set; }
    [XmlElement]
    public decimal AllowableDrift { get; set; }
[XmlElement]
public bool FailOoc { get; set; } = false;
    [XmlElement]
    public bool FailAbove { get; set; }
    [XmlElement]
    public bool FailBelow { get; set; }
    [XmlElement]
    public bool FailOoc5Day { get; set; }
    [XmlElement]
    public decimal InstSpan { get; set; }
    [XmlElement]
    public decimal GasLevel { get; set; }
    [XmlElement]
    public string CId { get; set; }
    [XmlElement]
    public string MId { get; set; }
    [XmlElement]
    public string CylinderId { get; set; }
    [XmlElement]
    public string CylinderExpDate { get; set; }
    [XmlElement]
    public string CylinderVendorId { get; set; }
    [XmlElement]
    public string CylinderGasTypeCode { get; set; }
        }
    }

XML存储在字符串xmlString中,并以下列形式出现在数据库中:

    <Regs>40CFR75</Regs>
    <BasisTStamp>2016-02-15 05:18</BasisTStamp>
    <DASWriteTStamp>2016-02-15 05:40</DASWriteTStamp>
    <InjEndTime>2016-02-15 05:23</InjEndTime>
    <Manual>0</Manual>
    <RefValue>169.7</RefValue>
    <MeasValue>169.27</MeasValue>
    <Online>14</Online>
    <AllowableDrift>15</AllowableDrift>
    <FailAbove>0</FailAbove>
    <FailBelow>0</FailBelow>
    <InstSpan>300</InstSpan>
    <GasLevel>MID</GasLevel>
    <CID>111</CID>
    <MID>N10</MID>
    <CylinderID>CC357464</CylinderID>
    <CylinderExpDate>2022-08-12</CylinderExpDate>
    <CylinderVendorID>B22014</CylinderVendorID>
    <CylinderGasTypeCode>BALN,SO2,NO,CO2</CylinderGasTypeCode>

现在,为了通过“rootless”xml克服XML API的问题,我添加了一个根:

    xmlString = "<columns>" + xmlString + "</columns>";

要解析这个,我使用:

    XDocument doc = XDocument.Parse(xmlString);

最后,为了尝试从XML中提取VALUES并填充QADailyXValueCalCheck的实例,我有以下代码 - 它适用于其他示例 - 不起作用。

                var xfields =
            from r in doc.Elements("columns")
            select new QADailyXValueCalCheck
            {
                Regs = (string) r.Element("Regs"),
                BasisTStamp = (string) r.Element("BasisTStamp"),
                DAsWriteTStamp = (string) r.Element("DASWriteTStamp"),
                InjEndTime = (string) r.Element("InjEndTime"),
                Manual = (bool) r.Element("Manual"),
                RefValue = (decimal) r.Element("RefValue"),
                MeasValue = (decimal)r.Element("MeasValue"),
                Online = (string)r.Element("Online"),
                AllowableDrift = (decimal)r.Element("AllowableDrift"),
                //FailOoc = (bool)r.Element("FailOoc"),
                //FailAbove = (bool)r.Element("FailAbove"),
                //FailBelow = (bool)r.Element("FailBelow"),
                //FailOoc5Day = (bool)r.Element("FailOoc5Day"),
                //InstSpan = (decimal)r.Element("InstSpan"),
                //GasLevel = (decimal)r.Element("GasLevel"),
                CId = (string)r.Element("CID"),
                MId = (string)r.Element("MID"),
                CylinderId = (string)r.Element("CylinderId"),
                CylinderExpDate = (string)r.Element("CylinderExpDate"),
                CylinderVendorId = (string)r.Element("CylinderVendorId"),
                CylinderGasTypeCode = (string)r.Element("CylinderGasTypeCode")
            };

上面的代码不会创建类的新实例,“QADailyXValueCalCheck”可以添加到List中。我有一些空值导致该代码出现问题,但这是一个单独的问题,我将在另一个时间处理。

现在,有人可以告诉我“var xfields =”查询如何实例化一个新的QADailyXValueCalCheck对象,该对象可以添加到我的相同类型的列表中吗?

缺少什么代码?感谢能够解答这个问题的LINQ / XML天才。

1 个答案:

答案 0 :(得分:0)

前几天我在其他人的XML解析方面遇到过类似的问题: Create a List from XElements Dynamically

我认为最终使用带有xml装饰的类可以更好地服务,然后使用扩展类来序列化或反序列化数据。这使得恕我直言在两个方面更好: 1.您不必重写解析器和POCO类,只需要重写POCO类。 2.您可以在其他地方自由重用扩展方法。

using System;
using System.Collections.Generic;
using System.Xml.Serialization;

namespace GenericTesting.Models
{
  [XmlRoot(ElementName = "column")]
  public class QADailyXValueCalCheck
  {
  [XmlElement]
  public string Regs { get; set; }
  [XmlElement]
  public string BasisTStamp { get; set; }
  [XmlElement]
  public string DAsWriteTStamp { get; set; }
  [XmlElement]
  public string InjEndTime { get; set; }
  [XmlElement]
  public int Manual { get; set; }
  [XmlElement]
  public decimal RefValue { get; set; }
  [XmlElement]
  public decimal MeasValue { get; set; }
  [XmlElement]
  public int Online { get; set; }
  [XmlElement]
  public decimal AllowableDrift { get; set; }
  [XmlElement]
  public bool FailOoc { get; set; } = false;
  [XmlElement]
  public int FailAbove { get; set; }
  [XmlElement]
  public int FailBelow { get; set; }
  [XmlElement]
  public bool FailOoc5Day { get; set; }
  [XmlElement]
  public decimal InstSpan { get; set; }
  [XmlElement]
  public string GasLevel { get; set; }
  [XmlElement]
  public string CId { get; set; }
  [XmlElement]
  public string MId { get; set; }
  [XmlElement]
  public string CylinderId { get; set; }
  [XmlElement]
  public string CylinderExpDate { get; set; }
  [XmlElement]
  public string CylinderVendorId { get; set; }
  [XmlElement]
  public string CylinderGasTypeCode { get; set; }
  }
}

为了序列化/反序列化,让我为这些提供扩展方法:

using System.IO;        
using System.Xml;
using System.Xml.Serialization;

namespace GenericTesting
{                                   
  static class ExtensionHelper
  { 
    public static string SerializeToXml<T>(this T valueToSerialize)
    {
      dynamic ns = new XmlSerializerNamespaces();
      ns.Add("", "");
      StringWriter sw = new StringWriter();

      using (XmlWriter writer = XmlWriter.Create(sw, new XmlWriterSettings { OmitXmlDeclaration = true }))
      {
        dynamic xmler = new XmlSerializer(valueToSerialize.GetType());
        xmler.Serialize(writer, valueToSerialize, ns);
      }

      return sw.ToString();
    }

    public static T DeserializeXml<T>(this string xmlToDeserialize)
    {
      dynamic serializer = new XmlSerializer(typeof(T));

      using (TextReader reader = new StringReader(xmlToDeserialize))
      {
        return (T)serializer.Deserialize(reader);
      }
    }
  }
}

控制台应用中的一个简单主要入口点:

static void Main(string[] args)
{
    var thingie = new QADailyXValueCalCheck
    {
      Regs = "40CFR75",
      BasisTStamp = "2016-02-15 05:18",
      DAsWriteTStamp = "2016-02-15 05:40",
      InjEndTime = "2016-02-15 05:23",
      Manual = 0,       //Boolean This will probably mess up  Changed to Int
      RefValue = 169.7M,
      MeasValue = 169.27M,
      Online = 14,  //Mismatch Type?  Change to Int
      AllowableDrift = 15,
      FailAbove = 0,     //Boolean This will probably mess up   Changed to Int
      FailBelow = 0,     //Boolean This will probably mess up    Changed to Int
      InstSpan = 300,
      GasLevel = "MID",     //This is marked as a decimal?     Changed to string                                                
      CId = "111",             
      MId =  "N10",
      CylinderId= "CC357464",
      CylinderExpDate ="2022-08-12",
      CylinderVendorId = "B22014",
      CylinderGasTypeCode = "BALN,SO2,NO,CO2"
  };

  var serialized = thingie.SerializeToXml();

  var deserialized = serialized.DeserializeXml<QADailyXValueCalCheck>();

  Console.ReadLine();
}

这个序列化就像这样,我也可以把它重新反序列化。

example serialization