Click here to Skip to main content
15,889,528 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
How do I Deserialize the following xml into object. I could not recognize the mistake that I am doing and I getting the "There is an error in XML document (2, 2)" error. Could you please help me on this.


Input Xml format i.e. books.xml


XML
<?xml version="1.0" encoding="utf-8"?>
<catalog xmlns="http://library.by/catalog" date="2016-02-05">
  <book id="bk101">
    <isbn>0-596-00103-7</isbn>
    <author>Löwy, Juval</author>
    <title>COM and .NET Component Services</title>
    <genre>Computer</genre>
    <publisher>O'Reilly</publisher>
    <publish_date>2001-09-01</publish_date>
    <description>
      COM & .NET Component Services provides both traditional COM programmers and new .NET
      component developers with the information they need to begin developing applications that take full advantage of COM+ services.
      This book focuses on COM+ services, including support for transactions, queued components, events, concurrency management, and security
    </description>
    <registration_date>2016-01-05</registration_date>
  </book>
  <book id="bk109">
    <author>Kress, Peter</author>
    <title>Paradox Lost</title>
    <genre>Science Fiction</genre>
    <publisher>R & D</publisher>
    <publish_date>2000-11-02</publish_date>
    <description>
      After an inadvertant trip through a Heisenberg
      Uncertainty Device, James Salway discovers the problems
      of being quantum.
    </description>
    <registration_date>2016-01-05</registration_date>
  </book>
</catalog>


Here are the classes:


C#
using System;
using System.Xml.Serialization;

namespace Seralization
{
    [Serializable()]
    public class Book
    {
        [XmlAttribute("id")]
        public string BookId { get; set; }

        [XmlElement("isbn")]
        public string Isbn { get; set; }

        [XmlElement("author")]
        public string Author { get; set; }

        [XmlElement("title")]
        public string Title { get; set; }

        [XmlElement("publisher")]
        public string Publisher { get; set; }

        [XmlElement("publish_date")]
        public DateTime PublishDate { get; set; }

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

        [XmlElement("registration_date")]
        public DateTime RegisteredDate { get; set; }

        [XmlIgnore]
        public Genre Genre;

        [XmlAttribute("genre")]
        public string GenreValue
        {
            get { return Genre.ToString(); }
            set
            {
                if (string.IsNullOrEmpty(value))
                {
                    Genre = default(Genre);
                }
                else
                {
                    Genre = (Genre)Enum.Parse(typeof(Genre), value);
                }
            }
        }
    }
}


C#
using System;
using System.Xml.Serialization;

namespace Seralization
{
    [Serializable()]
    [XmlRoot("catalog")]
    public class Calalog
    {
        [XmlAttribute]
        public DateTime createdDate;

        [XmlArray("catalog")]
        [XmlArrayItem("book", typeof(Book))]
        public Book[] Books { get; set; }
    }
}

using System.ComponentModel;

namespace Seralization
{
    public enum Genre
    {
        Computer = 1,
        Fantasy = 2,
        Romance = 3,
        Horror = 4,
        [Description("Science Fiction")]
        ScienceFiction = 5
    }
}


What I have tried:

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

class Program
    {
        static void Main(string[] args)
        {
            Calalog cars = null;
            string path = @"C:\input\books.xml";

            XmlSerializer serializer = new XmlSerializer(typeof(Calalog));

            StreamReader reader = new StreamReader(path);
            cars = (Calalog)serializer.Deserialize(reader);
            Console.WriteLine(cars.Books.GetType());
            reader.Close();
            Console.ReadLine();
        }
}
Posted
Updated 30-Apr-17 23:53pm

1 solution

1) Well, if you look into the inner exception you see that the namespace of the xml is not known

2) To get along, I would first build a valid object, then serialize it and see how the valid serialized structure looks like. A base class that does the serialization and deserialization might help you with this.

2.a)

public abstract class PersistentSettingsBase<T>
{
	public string XMLSerialize()
	{
		XmlSerializer serializer = new XmlSerializer(this.GetType());
		using (StringWriter myStream = new StringWriter())
		{
			serializer.Serialize(myStream, this);
			myStream.Flush();
			return (myStream.ToString());
		}
	}

	public static T XMLDeserialize(string xmlString)
	{
		if (string.IsNullOrEmpty(xmlString))
		{
			throw new ArgumentNullException("xmlString");
		}

		XmlSerializer serializer = new XmlSerializer(typeof(T));
		using (StringReader myStream = new StringReader(xmlString))
		{
			try
			{
				return (T)serializer.Deserialize(myStream);
			}
			catch (Exception ex)
			{
				// The serialization error messages are cryptic at best. Give a hint at what
				// happended
				throw new InvalidOperationException("Failed to create object from xml string", ex);
			}
		}
	}
}



2.b)

[Serializable()]
[XmlRoot("catalog")]
public class Calalog : PersistentSettingsBase<Calalog>
{


btw. "calalog" is a typo or what?


2.c)

void Main()
{		
	Calalog cars = null;
    cars = new Calalog();
	cars.createdDate = DateTime.Now;
	var b1 = new Book();
	b1.BookId = "bk101";
	b1.Title = "COM and .NET Component Services";
	b1.Isbn = "0-596-00103-7";
	b1.Genre = Genre.Computer;
	var b2 = new Book();
	b2.BookId = "bk109";
	b2.Title = "Paradox Lost";
	b2.Isbn = "not set";
	b2.Author = "Kress, Peter";
	b2.Genre = Genre.ScienceFiction;
	cars.Books = new[] { b1, b2 };
	
	string serializedCatalog = cars.XMLSerialize();
	
	Calalog deserializedCatalog = Calalog.XMLDeserialize(serializedCatalog);
    //deserializedCatalog.Dump(); // this is a linqpad command

    //your code starts here
	string path = @"C:\temp\books.xml";
	XmlSerializer serializer = new XmlSerializer(typeof(Calalog));
	StreamReader reader = new StreamReader(path);
	cars = (Calalog)serializer.Deserialize(reader);
	Console.WriteLine(cars.Books.GetType());
	reader.Close();
	Console.ReadLine();
}


Now you have a working XML representation and can compare it to yours that is not yet working. You will see that you encoded Genre as an XMLElement in the file, however as an XmlAttribute in your code (there are other differences as well).

2.d, update:)

If you are not free to change the structure of the given xml-file you need to
change the definition of you Catalog class

[Serializable()]
[XmlRoot(ElementName = "catalog", Namespace = "http://library.by/catalog")]
public class Catalog : PersistentSettingsBase<Catalog>
{
	[XmlAttribute]
	public DateTime date;

	[XmlElement("book")]
	public Book[] Books { get; set; }
}


The DateTime in the XML-File has an attribute Name of "date" not "createdDate", the Namespace parameter in the root attribute avoids the error you get when reading this part.
You still will get an error with "Science Fiction" because your code makes no effort to use the Description attribute for conversion. I don't know how to handle this.
 
Share this answer
 
v3
Comments
Naga Sindhura 1-May-17 7:38am    
Hi FranzBe,
When I serialize the declared object and then Deserialize then it is working as expected. However, I have modified the code as follows but still I am getting the same error @ "return (T)serializer.Deserialize(myStream);" line.

string path = @"C:\temp\books.xml";
StreamReader reader = new StreamReader(path);
string s = reader.ReadToEnd();
reader.Close();

Catalog deserializedCatalog1 = Catalog.XMLDeserialize(s);

Along with that I have corrected the Genre property to XMLElement.
Naga Sindhura 1-May-17 7:39am    
"xmlns="http://library.by/catalog" is in Russian language. Will it effect my code?
FranzBe 1-May-17 8:52am    
Hi Naga Sindhura have a look at 2.d) above. Hope that helps.
There is also a problem left with the ampersand in your data, you need to remove it to make it work. you may want to look here:
http://stackoverflow.com/questions/1744046/deserialize-xml-with-ampersand-using-xmlserializer

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900