Carlo Luisito
Carlo Luisito

Reputation: 229

How to implement Multiple XML Root , Multiple Element Names

Is it possible to deserialize xml with mutiple xml root?

If not, what is the best way to bind elements to a single model if it has the same properties on it?

Here are my codes:

[XmlRoot(ElementName = "residential")]
[XmlRoot(ElementName = "commercial")]
public class Property
{
    [XmlElement(ElementName = "name")]
    public string Name{ get; set; }

    [XmlElement(ElementName = "description")]
    public string Description { get; set; }
}


[XmlRoot(ElementName = "propertyList")]
public class PropertyList
{
    [XmlChoiceIdentifier("EnumType")]
    [XmlElement(ElementName = "residential")]
    [XmlElement(ElementName = "commercial")]
    [XmlElement(ElementName = "land")]
    [XmlElement(ElementName = "rental")]
    [XmlElement(ElementName = "holidayRental")]
    [XmlElement(ElementName = "rural")]
    public List<Property> Properties { get; set; }

    [XmlIgnore]
    public PropertyType[] EnumType;

    [XmlAttribute(AttributeName = "date")]
    public string Date { get; set; }
    [XmlAttribute(AttributeName = "username")]
    public string Username { get; set; }
    [XmlAttribute(AttributeName = "password")]
    public string Password { get; set; }

    [XmlIgnore]
    public string Type { get; set; }
}

[XmlType(IncludeInSchema = false)]
public enum PropertyType
{
    residential,
    commercial,
    land,
    rental,
    holidayRental,
    rural
}


var serializer = new XmlSerializer(typeof(Business.Models.PropertyList), new XmlRootAttribute("propertyList"));

I'm getting Object reference not set to an instance of an object error when trying to deserialize the XML.

Here's the sample xml

<propertyList date="2020-09-09T09:35:38" username="test" password="test">
<commercial modTime="2020-09-09T09:35:38" status="current">
<agentID>12345</agentID>
<uniqueID>12345</uniqueID>
</commercial>
<commercial modTime="2020-09-09T09:35:38" status="current">
<agentID>12345</agentID>
<uniqueID>12345</uniqueID>
</commercial>
<commercial modTime="2020-09-09T09:35:38" status="current">
<agentID>12345</agentID>
<uniqueID>12345</uniqueID>
</commercial>
<residentialmodTime="2020-09-09T09:35:38" status="current">
<agentID>12345</agentID>
<uniqueID>12345</uniqueID>
</residential>
<residentialmodTime="2020-09-09T09:35:38" status="current">
<agentID>12345</agentID>
<uniqueID>12345</uniqueID>
</residential>
<commercial modTime="2020-09-09T09:35:38" status="current">
<agentID>12345</agentID>
<uniqueID>12345</uniqueID>
</commercial>
</propertylist

Upvotes: 0

Views: 1574

Answers (2)

jdweng
jdweng

Reputation: 34421

Use IXmlSerilizable with xml linq

sing System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.Schema;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        const string INPUT_FILENAME = @"c:\temp\test.xml";
        const string OUTPUT_FILENAME = @"c:\temp\test1.xml";
        static void Main(string[] args)
        {
            XmlReader reader = XmlReader.Create(INPUT_FILENAME);
            XmlSerializer serializer = new XmlSerializer(typeof(PropertyList));
            PropertyList PropertyList = (PropertyList)serializer.Deserialize(reader);

            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            XmlWriter writer = XmlWriter.Create(OUTPUT_FILENAME, settings);
            serializer.Serialize(writer, PropertyList);
        }
    }
    public enum PropertyType
    {
        residential,
        commercial,
        land,
        rental,
        holidayRental,
        rural
    }
    public class Property
    {
        public PropertyType propertyType { get; set; }
        public DateTime Date { get; set; }
        public string status { get; set; }

        [XmlElement(ElementName = "agentID")]
        public string agentID { get; set; }

        [XmlElement(ElementName = "uniqueID")]
        public string uniqueID { get; set; }
    }
    [XmlRoot(ElementName = "propertyList")]
    public class PropertyList : IXmlSerializable
    {

        public List<Property> Properties { get; set; }
        // Constructors

 
        public PropertyList()
        {
            Properties = new List<Property>();
        }

        // Xml Serialization Infrastructure

        public void WriteXml(XmlWriter writer)
        {
            XElement propertyList = new XElement("propertyList");
            propertyList.Add(new XAttribute("date", Date.ToString("yyyy-MM-ddTHH:mm:ss")));
            propertyList.Add(new XAttribute("username", Username));
            propertyList.Add(new XAttribute("password", Password));
            foreach (Property xProperty in Properties)
            {
                XElement property = new XElement(xProperty.propertyType.ToString(), new object[] {
                    new XAttribute("modTime", xProperty.Date.ToString("yyyy-MM-ddTHH:mm:ss")),
                    new XAttribute("status", xProperty.status),
                    new XElement("agentID", xProperty.agentID),
                    new XElement("uniqueID", xProperty.uniqueID)
                });
                propertyList.Add(property);
            }

            propertyList.WriteTo(writer);
        }

        public void ReadXml(XmlReader reader)
        {
            XElement element = (XElement)XElement.ReadFrom(reader);
            Date = (DateTime)element.Attribute("date");
            Username = (string)element.Attribute("username");
            Password = (string)element.Attribute("password");
            foreach (XElement xProperty in element.Elements())
            {
                Property property = new Property()
                {
                    propertyType = (PropertyType)Enum.Parse(typeof(PropertyType), xProperty.Name.LocalName),
                    Date = (DateTime)xProperty.Attribute("modTime"),
                    status = (string)xProperty.Attribute("status"),
                    agentID = (string)xProperty.Element("agentID"),
                    uniqueID = (string)xProperty.Element("uniqueID")
                };
                Properties.Add(property);
            }
        }

        public XmlSchema GetSchema()
        {
            return (null);
        }

        public DateTime Date { get; set; }
        public string Username { get; set; }
        public string Password { get; set; }

     }
}

Upvotes: 1

Alexander Petrov
Alexander Petrov

Reputation: 14231

Reading can be implemented as follows

var settings = new XmlReaderSettings { ConformanceLevel = ConformanceLevel.Fragment };

var list = new List<PropertyList>();

using (var xmlReader = XmlReader.Create("test.xml", settings))
{
    while (xmlReader.MoveToContent() == XmlNodeType.Element)
    {
        list.Add((PropertyList)serializer.Deserialize(xmlReader));
    }
}

Each xml fragment is deserialized separately and added to the list.

Upvotes: 1

Related Questions