3

This questions was asked before but the answer doesn't work for me: so here is the question again : )

I am having real trouble trying to deserialize some XML and was hoping someone can offer some assistance. I have read a lot of similar posts but I am unable to resolve this.

Here is the XML

<register-account success="false">
  <user-name>xxxxx</user-name>
  <password>fghgh</password>
  <email>test@example.com</email>
</register-account>

Class I am trying to deserialize to:

[Serializable, XmlRoot(ElementName = "register-account", Namespace = "MyNamespace")]
[XmlType("register-account")]
public class RegisterAccountResponse
{
    [XmlAttribute("success")]
    public bool Success { get; set; } 

    /// <summary>
    /// Gets or sets the Tennant email address
    /// </summary>
    [XmlElement("email")]
    public string Email { get; set; }

    /// <summary>
    /// Gets or sets the tennant password
    /// </summary>
    [XmlElement("password")]
    public string Password { get; set; }

    /// <summary>
    /// Gets or sets the Tennant username
    /// </summary>
    [XmlElement("user-name")]
    public string Username { get; set; }
}

Deserialization Method

public static T Deserialize<T>(string data) where T : class
{

    var ser = new XmlSerializer(typeof(T));

    using (var sr = new StringReader(data))
    {
        return (T)ser.Deserialize(sr);
    }
}

Deserialization Method Call

var data = Helper.Deserialize<RegisterAccountResponse>(xml);

Exception:

There is an error in XML document (1, 2). ---> System.InvalidOperationException: was not expected. at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderData.Read5_data()

Inner Exception as follows:

<register-account xmlns=''> was not expected.

The answer to the question was to remove the namespace from the class (remove Namespace = "MyNamespace"). The class however is part of a very large library that is autogenerated using xsd.exe. I don't want to change anything in the generated class. Is there away to still fix this issue without having to modify the class?

Cheeso
  • 189,189
  • 101
  • 473
  • 713
Amine Zegl
  • 71
  • 2
  • 8
  • Assuming that is the entirety of the XML, then the XML that you showed does not have a namespace (no xmlns declaration). So therefore, removing it from your class' serialization parameters makes sense... Or else, regen your class through XSD to make it generated without the namespace. – Reddog Mar 29 '12 at 18:14
  • I don't think XSD.exe supports generating classes withouth namespace attribute. – Amine Zegl Mar 29 '12 at 18:34

2 Answers2

6

Is there away to still fix this issue without having to modify the class?

Yes.

.NET has a class called XmlAttributeOverrides that is designed for this purpose. You can override attributes that are present in the code, at runtime.

The following modified Deserialize utility method will correctly deserialize an instance of the class you provided, using the XML you provided, without requiring a modification of either. No XSLT either.

    public static T DeserializeWithNoRootNamespace<T>(string data)
        where T : class
    {

        /* Each overridden field, property, or type requires
           an XmlAttributes object. We are overriding the serialization
           of the XmlRoot on the type, so we need one XmlAttributes collection. */
        var attrs = new XmlAttributes();

        /* Create an XmlRootAttribute to override the XmlRoot in-line attr.
           The override will use no namespace. */
        var root = new XmlRootAttribute("register-account");

        // set the XmlRoot on the XmlAttributes collection.
        attrs.XmlRoot= root;

        // Create the XmlAttributeOverrides object.
        var o = new XmlAttributeOverrides();

        /* Map the attributes collection to the thing being 
           overriden (the class). */
        o.Add(typeof(T), attrs);

        // create the serializer, specifying the overrides to use
        var ser = new XmlSerializer(typeof(T), o);

        using (var sr = new StringReader(data))
        {
            return (T)ser.Deserialize(sr);
        }
    }

The above code overrides the XmlRoot attribute. The XmlAttributeOverrides is general enough to allow overriding the xml-serialization attributes on any piece of the class to be deserialized. That wasn't necessary in your case.

More information.

ps: The [Serializable] attribute you have decorating your class, is not needed. It is a common error, to apply that to classes that will be XML- serialized and deserialized. But it is extraneous, and therefore wrong.

djv
  • 15,168
  • 7
  • 48
  • 72
Cheeso
  • 189,189
  • 101
  • 473
  • 713
  • This one was interresting, With this code I managed to override the namespace on my xml, that is, my schema has one namespace, but for some reason, the xml files that I have to read have different namespaces from vendor to vendor. But with this I could read the namespace from the file, then override it in my deserializing and thus deserialize element by element from the file. BUT.. lot of runtime codegeneration is going on: 'test.vshost.exe' (CLR v4.0.30319: test.vshost.exe): Loaded 'Microsoft.GeneratedCode'. And it is slow as hell.. is there other ways to do this? – neslekkiM Jun 09 '15 at 13:51
-2

Well if you can't or don't want to change the code then you must you xslt to transform your xml to add some namespaces where needed. that will help deserializer to deserialize document.

Regards.

Shoaib Shaikh
  • 4,565
  • 1
  • 27
  • 35
  • Can't I change the Deserialize code? or Change the incoming xml to inject the namespace? how can i go about doing that – Amine Zegl Mar 29 '12 at 18:21
  • i don't think so that you can avoid namespace declaration that has been written as attribute in you class. but you can change the incomming xml by using XSLT. it might need some study of XSLT as it is a markup language to style xml.http://support.microsoft.com/kb/307322/en-us/ or http://stackoverflow.com/questions/144713/add-a-namespace-to-elements-using-xslt – Shoaib Shaikh Mar 30 '12 at 05:01
  • This answer is incorrect. It is not true that xslt is required. @Amine - you can do what you want. See my answer. http://stackoverflow.com/a/10020010/48082 – Cheeso Apr 04 '12 at 22:23
  • thanks for clarification @Cheeso i missed the way we can override things. – Shoaib Shaikh Apr 05 '12 at 04:41