Andreas Grech
Andreas Grech

Reputation: 108040

Trouble deserializing an XML file which has only one node; the root node

This is the XML file I'm trying to deserialize:

<?xml version="1.0" encoding="utf-8"?>
<d:MyItem xmlns:d="http://someurl" xmlns:m="http://someotherurl">This is a string</d:MyItem>

The xsd tool generated the following class:

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://someurl")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://someurl", IsNullable=false)]
public partial class MyItem {

    private object[] itemsField;

    /// <remarks/>
    public object[] Items {
        get {
            return this.itemsField;
        }
        set {
            this.itemsField = value;
        }
    }
}

I'm currently trying to deserialize the same xml that xsd used to generate the class:

var xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<d:MyItem xmlns:d=\"http://someurl\" xmlns:m=\"http://someotherurl\">This is a string</d:MyItem>";
var deserialized = Deserialize<MyItem>(xml);

Where Deserialize<> is:

private static T Deserialize<T>(string xml)
{
    var xmlDocument = XDocument.Parse(xml);
    var serializer = new System.Xml.Serialization.XmlSerializer(typeof(T));
    return (T)serializer.Deserialize(xmlDocument.CreateReader());
}

The problem is that although Deserialize returns an instance (not null), the Items property inside it is null i.e. it's not being deserialized.

How am I able to get the string from inside this XML?

Upvotes: 2

Views: 924

Answers (3)

Piper Keairnes
Piper Keairnes

Reputation: 96

XSD.exe expects your root document element to be a complex type, but in your case it is a simple string, so various assumptions within XSD.exe cause problems. The bad schema that it generates is just the first of several problems.

The simplest solution is to ignore XSD.exe and just create your own XML serializable class:

[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://someurl")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://someurl", IsNullable = false)]
public partial class MyItem
{
    [System.Xml.Serialization.XmlTextAttribute]
    public string Value { get; set; }
}

Also, I'm not sure why you are using XDocument.Parse in Deserialize. You could simplify it like this:

private static T Deserialize<T>(string xml)
{
    var serializer = new System.Xml.Serialization.XmlSerializer(typeof(T));
    return (T)serializer.Deserialize(new StringReader(xml));
}

Here's the complete working code:

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

namespace ConsoleApplication1
{
    [System.SerializableAttribute()]
    [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://someurl")]
    [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://someurl", IsNullable = false)]
    public partial class MyItem
    {
        [System.Xml.Serialization.XmlTextAttribute]
        public string Value { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<d:MyItem xmlns:d=\"http://someurl\" xmlns:m=\"http://someotherurl\">This is a string</d:MyItem>";
            var deserialized = Deserialize<MyItem>(xml);
            // Result:  deserialized.Value == "This is a string"
        }

        private static T Deserialize<T>(string xml) where T : new()
        {
            var serializer = new System.Xml.Serialization.XmlSerializer(typeof(T));
            return (T)serializer.Deserialize(new StringReader(xml));
        }
    }
}

Upvotes: 3

Surjit Samra
Surjit Samra

Reputation: 4662

There is problem with your XML if you use this xml then you can deserilize it with your code.

var xml = "<MyItem xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://someurl\">  <Items>    <anyType xsi:type=\"xsd:string\">This is string</anyType>  </Items></MyItem>";

this will give you your string from inside of your xml

Upvotes: 0

Eugene
Eugene

Reputation: 1535

Your xml looks incorrect to me, try to serialize an instance of this class and take a look at generated xml. I think that there must be something like

<?xml version="1.0" encoding="utf-8"?>
<d:MyItem xmlns:d="http://someurl" xmlns:m="http://someotherurl">
<ArrayOfItems>
<Item>...</Item>
...
</ArrayOfItems>
</d:MyItem>

if you want to deserialize your xml you should have a class

public partial class MyItem {

/// <remarks/>
public String Item{ get; set;  }
}

and have the xml

<?xml version="1.0" encoding="utf-8"?>
<d:MyItem xmlns:d="http://someurl" xmlns:m="http://someotherurl">
<Item>some text</Item>    
</d:MyItem>

Upvotes: 0

Related Questions