Cannot parse simple XML into an object?

2019-05-26 05:33发布

XML

<MeterWalkOrder>
  <Name>Red Route</Name>
  <Meters>
    <Meter>
      <MeterID>1</MeterID>
      <SerialNumber>12345</SerialNumber>
    </Meter>
    <Meter>
      <MeterID>2</MeterID>
      <SerialNumber>SE</SerialNumber>
    </Meter>
  </Meters>
</MeterWalkOrder>

I cannot get simple XML into an object using any serializer

var xml = File.ReadAllText("WalkOrder.xml");
var xmlSerializer = new NFormats.Xml.XmlSerializer();
var obj = xmlSerializer.Deserialize<MeterWalkOrder>(new StringReader(xml));

I just get back 2 meter objects that have none of the attributes set and the name is not even set in walk order.

 public partial class MeterWalkOrder
 {
        public MeterWalkOrder()
        {
            Meters = new List<Meter>();
        }

        [DataMember]
        public String Name { get; set; }
     }
}

using System;
using System.Xml.Serialization;

namespace WindowsFormsApplication1.Classes
{    
    public class Meter : IMeter
    {
        [XmlAttribute]
        public int MeterID { get; set; }

        [XmlAttribute]
        public String SerialNumber { get; set; }
    }
}

I am willing to try any xml serializer.

2条回答
Juvenile、少年°
2楼-- · 2019-05-26 05:54

I used your sample XML and generated the classes inside VisualStudio with the Paste Special -> Paste XML as Classes, modified them a little bit to make them more readable and got the following class definitions from it:

[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public class MeterWalkOrder
{
  public string Name { get; set; }

  [System.Xml.Serialization.XmlArrayItemAttribute("Meter", IsNullable = false)]
  public List<MeterWalkOrderMeter> Meters { get; set; }
}

[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public class MeterWalkOrderMeter
{
  public int MeterID { get; set; }
  public string SerialNumber { get; set; }
}

using the above classes and the below code, it generated the objects without errors.

string inputXml = File.ReadAllText(@"C:\Temp\SOTest.xml");
//using System.Xml.Serialization;
System.Xml.Serialization.XmlSerializer xmlSerializer = new System.Xml.Serialization.XmlSerializer(typeof(MeterWalkOrder));
MeterWalkOrder outputObject = xmlSerializer.Deserialize(new StringReader(inputXml)) as MeterWalkOrder;
查看更多
爷、活的狠高调
3楼-- · 2019-05-26 05:55

First of all i suggest you to read Introducing XML Serialization on MSDN You made a couple of errors which lead to not mentioned exceptions thrown when you run your code.

  1. in your Xml MeterID and SerialNumber are not attributes they are elements. (As Wyat Earp commented)
  2. if you want to serialize something you have to tell that it should be [Serializable]
  3. serialization requires an implemented public empty constructor
  4. dont open streams when you are not closing them (use "using")
  5. To test if your serialization works best first serialize, then check the output and then implement deserialize

Find a fully working example below:

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

namespace X123
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            MeterWalkOrder mo = new MeterWalkOrder();
            mo.Name = "name";
            mo.Meters.Add(new Meter { MeterID = 1, SerialNumber = "kdkdkd" });
            mo.Meters.Add(new Meter { MeterID = 2, SerialNumber = "holladrio" });

            var xmlSerializer = new XmlSerializer(typeof(MeterWalkOrder), new Type[] { typeof(Meter) });
            {
                xmlSerializer.Serialize(File.CreateText("hello.xml"), mo);
                using (Stream s = File.OpenRead("hello.xml"))
                {
                    var obj = xmlSerializer.Deserialize(s);
                }
            }
        }



    }

    [Serializable]
    public class MeterWalkOrder
    {
        public MeterWalkOrder()
        {
        }

        public string Name { get; set; }
        public List<Meter> Meters { get { return meters; } set { meters = value; } }
        private List<Meter> meters = new List<Meter>();
    }

    [Serializable]
    public class Meter
    {
        public Meter()
        {
        }

        [XmlAttribute]
        public int MeterID { get; set; }

        [XmlAttribute]
        public string SerialNumber { get; set; }
    }
查看更多
登录 后发表回答