J-Y
J-Y

Reputation: 375

Deserialize XML to object (need to return a list of objects)

Started practicing with XML and C# and I have an error message of "There is an error in XML document (3,2)". After looking at the file, I can't see anything wrong with it (Mind you, I probably missed something since I'm a noob). I'm using a Console Application for C# right now. I'm trying to return a list of Adventurers and just a side note, the GEAR element is optional. Here is what I have so far:

XML File - Test1

<?xml version="1.0" encoding="utf-8"?>
<Catalog>
    <Adventurer>
        <ID>001</ID>
        <Name>John Smith</Name>
        <Address>123 Fake Street</Address>
        <Phone>123-456-7890</Phone>
        <Gear>
            <Attack>
                <Item>
                    <IName>Sword</IName>
                    <IPrice>15.00</IPrice>
                </Item> 
                <Item>
                    <IName>Wand</IName>
                    <IPrice>20.00</IPrice>
                </Item>         
            </Attack>
            <Defense>
                <Item>
                    <IName>Shield</IName>
                    <IPrice>5.00</IPrice>
                </Item>
        </Defense>  
        </Gear>
    </Adventurer>
    <Adventurer>
        <ID>002</ID>
        <Name>Guy noone likes</Name>
        <Address>Some Big House</Address>
        <Phone>666-666-6666</Phone>
        <Gear></Gear>
    </Adventurer>
</Catalog>

C# Classes

public class Catalog
{
    List<Adventurer> Adventurers { get; set; }
}

public class Adventurer
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Address { get; set; }
    public string Phone { get; set; }
    public Gear Gear { get; set; }
}

public class Gear
{
    public List<Item> Attack { get; set; }
    public List<Item> Defense { get; set; }
}

public class Item
{
    public string IName { get; set; }
    public decimal IPrice { get; set; }
}

Serialize Function - Where the Problem Occurs at Line 5

Catalog obj = null;
string path = @"C:\Users\Blah\Desktop\test1.xml";
XmlSerializer serializer = new XmlSerializer(typeof(Catalog));
StreamReader reader = new StreamReader(path);
obj = (Catalog)serializer.Deserialize(reader);
reader.Close();

Console.ReadLine();

Upvotes: 5

Views: 4607

Answers (4)

jimmy k lu
jimmy k lu

Reputation: 11

I was able to get your xml to deserialize with a couple minor changes (namely the public qualifier on Adventurer).

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

namespace TempSandbox
{
    [XmlRoot]
    public class Catalog
    {
        [XmlElement("Adventurer")]
        public List<Adventurer> Adventurers;

        private readonly static Type[] myTypes = new Type[] { typeof(Adventurer), typeof(Gear), typeof(Item) };
        private readonly static XmlSerializer mySerializer = new XmlSerializer(typeof(Catalog), myTypes);

        public static Catalog Deserialize(string xml)
        {
            return (Catalog)Utils.Deserialize(mySerializer, xml, Encoding.UTF8);
        }
    }

    [XmlRoot]
    public class Adventurer
    {
        public int ID;

        public string Name;

        public string Address;

        public string Phone;

        [XmlElement(IsNullable = true)]
        public Gear Gear;
    }

    [XmlRoot]
    public class Gear
    {
        public List<Item> Attack;

        public List<Item> Defense;
    }

    [XmlRoot]
    public class Item
    {
        public string IName;

        public decimal IPrice;
    }
}

I'm using [XmlElement("Adventurer")] because the xml element names don't exactly match the class property names.

NOTE: I'm using a generic deserialization utility i already had on hand .

Upvotes: 1

Kevin DiTraglia
Kevin DiTraglia

Reputation: 26078

Your XML doesn't quite line up with your objects... namely these two...

public string City { get; set; }

and

<Address>123 Fake Street</Address>

Change City to Address or vice versa and it should fix the problem.

Edit: Got this to work in a test project, combination of all our answers...

Add <Adventurers> tag after <Catalog> (and </Adventurers> before </Catalog>) and change

List<Adventurer> Adventurers { get; set; }

to

public List<Adventurer> Adventurers { get; set; }

and it works properly for me.

Upvotes: 1

Hamza_L
Hamza_L

Reputation: 654

First, "Adventurers" property is not public, it's inaccessible, I think that the best way to find the error is to serialize your object and then compare the result with your xml file.

Upvotes: 2

Chris Sinclair
Chris Sinclair

Reputation: 23208

The issue is the list of Adventurers in Catalog:

<?xml version="1.0" encoding="utf-8"?>
<Catalog>
    <Adventurers> <!-- you're missing this -->
        <Adventurer>
        </Adventurer>
        ...
        <Adventurer>
        </Adventurer>
    </Adventurers> <!-- and missing this -->
</Catalog>

You don't have the wrapping element for the Adventurers collection.

EDIT: By the way, I find the easiest way to build the XML structure and make sure it's compatible is to create the object(s) in C#, then run through the built-in XmlSerializer and use its XML output as a basis for any XML I create rather than forming it by hand.

Upvotes: 3

Related Questions