简体   繁体   中英

Unable to convert XML to C# Object List

I'm trying to convert the XML data to an object list, but it throws an error.

XML

<?xml version="1.0" encoding="utf-8" ?>
<Servers>
  <Server>
    <ServerName>STAGING</ServerName>
    <ServerIP>XXX.XXX.XX.X</ServerIP>        
  </Server>
</Servers>

C#

public class ServerDetails
{
    public string ServerName { get; set; }
    public string ServerIP { get; set; }        
}

private void GetXMLData()
{
  XmlSerializer serializer = new XmlSerializer(typeof(List<ServerDetails>));

  using (FileStream stream = File.OpenRead("D:\\Resource.xml"))
  {
    List<ServerDetails> list = (List<ServerDetails>)serializer.Deserialize(stream);
    //Exception here
  }
}

ERROR

Inner Exception : <Servers xmlns=''> was not expected.   
There is an error in XML document (2,2)

I tried adding the [Serializabe] and [XMLElement] attributes to the class,
and also xmlns="http://www.example.com/xsd/ServerDetails" in the XML
but that did not help.

You have ServerDetails as your class name and in the xml the tag name is different, Try something like this.

public class ServerDetails
{
   public string ServerName { get; set; }
   public string ServerIP { get; set; }        
}

public class ServerList
{
   [XmlArray("Servers")]
   [XmlArrayItem("Server", Type = typeof(ServerDetails))]
   public ServerDetails[] Servers { get;set;}        
}

private void GetXMLData()
{
   XmlSerializer serializer = new XmlSerializer(typeof(ServerList));

   using (FileStream stream = File.OpenRead("D:\\Resource.xml"))
   {
      var list = (ServerList)serializer.Deserialize(stream);
      //Exception here
   }
}

I used to use XmlSerializer a lot, but I totally stopped using it because you are forced to create your object structure fitting the xml structure. That makes it hard to maintain. Also XmlSerializer has some serious memory leaks.

If you don't mind, I would suggest to switch to XElement

    public IEnumerable<ServerDetails> GetServers(string file)
    {
        using (var stream = File.Open(file, FileMode.Open, FileAccess.Read))
            return GetServers(stream);
    }

    public IEnumerable<ServerDetails> GetServers(Stream stream)
    {
        var root = XElement.Load(stream);
        return GetServers(root);
    }

    public IEnumerable<ServerDetails> GetServers(XElement root)
    {
        foreach (var server in root.Elements("Server"))
        {
            yield return new ServerDetails
            {
                ServerName = (string)server.Element("ServerName"),
                ServerIP = (string)server.Element("ServerIP"),
            };
        }
    }

Please note that you have to reference System.Xml.Linq

For your convenience here is a test case.

    [TestMethod]
    public void CanReadServers()
    {
        var xml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" + @"
<Servers>
  <Server>
    <ServerName>STAGING</ServerName>
    <ServerIP>XXX.XXX.XX.X</ServerIP>
  </Server>
</Servers>";

        IEnumerable<ServerDetails> servers;
        using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
            servers = GetServers(stream).ToList();

        Assert.AreEqual(1, servers.Count());
        Assert.AreEqual("STAGING", servers.ElementAt(0).ServerName);
        Assert.AreEqual("XXX.XXX.XX.X", servers.ElementAt(0).ServerIP);
    }

Use XmlElement Notation to specify the element name.

public class Servers
{        
    [XmlElement("Server")]
    public ServerDetails[] ServersDetails { get; set; }
}

public class ServerDetails
{
    public string ServerName { get; set; }
    public string ServerIP { get; set; }
}


private void GetXMLData()
{
  XmlSerializer serializer = new XmlSerializer(typeof(Servers));

  using (FileStream stream = File.OpenRead("D:\\Resource.xml"))
  {
    Servers list = (Servers)serializer.Deserialize(stream);
    //Exception here
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM