RSmart RSmart - 4 months ago 21
C# Question

XmlSerializer Deserializing List Without namespace

Trying to deserialize List.
Im getting the following error:


System.InvalidOperationException: There is an error in XML document
(1, 2). ---> System.InvalidOperationException: was not expected.


Saw other quesitons like : {"<user xmlns=''> was not expected.} Deserializing Twitter XML but this does not solve my problem either.

This is an Xml Sample

<authorizations>
<id>111</id>
<name>Name 1</name>
<Lists>
<List>
<id>1</id>
<id>2</id>
</List>
</Lists>
</authorizations>
<authorizations>
<id>222</id>
<name>Name 2</name>
<List />
</authorizations>
<authorizations>
<id>333</id>
<name>Name 3</name>
<List />
</authorizations>


The class are created as follow:

public class Authorization
{
[XmlElement("id")]
public string Id{ get; set; }
[XmlElement("name")]
public string Name{ get; set; }
[XmlArray("Lists")]
[XmlArrayItem("List")]
public List[] Items{ get; set; }
}

public class List
{
[XmlElement("id")]
public string Id{ get; set; }
}

public class AuthorizationList
{
[XmlArray("authorizations")]
public Authorization Authorizations{ get; set; }
}


Have tried changing the list to XmlArray, XmlArrayItem or Element. but still get the same error when I deserialize.

Deserializing Code Sample:

public static T FromXml<T>(string xmlString)
{
T obj = default(T);

if (!string.IsNullOrWhiteSpace(xmlString))
{
using (var stringReader = new StringReader(xmlString))
{
var xmlSerializer = new XmlSerializer(typeof(T));

obj = (T)xmlSerializer.Deserialize(stringReader);
}
}

return obj;
}

Answer

This is ALL premised on the assumption that you have minimal control over the xml and don't have the luxury of changing that too much. As others have noted, it is not well formed. Here is one way to get serialization to work with minimal changes to your XML and types. First get rid of your AuthorizationList type and assign an XmlType attribute to your Authorization type (this step serves to simply pluralize the name to match how your xml has it).

[XmlType("authorizations")]
public class Authorization { ... }

public class List { ... }

Wrap your xml in the following root element...

<ArrayOfAuthorizations>
...
</ArrayOfAuthorizations>

The xml now represents a list of "authorizations" so to deserialize is just this...

List<Authorization> l = FromXml<List<Authorization>>(xml);

Another Solution...

Change the Authorizations member to be of type Authorization[] (array type rather than singular) and to have an XmlElement attribute (not XmlArray). Apply the XmlType attribute to the Authorization (as with the above solution this is to match the xml since it has the pluralized name for each array element).

[XmlType("authorizations")]
public class Authorization
{
    [XmlElement("id")]
    public string Id { get; set; }
    [XmlElement("name")]
    public string Name { get; set; }
    [XmlArray("Lists")]
    [XmlArrayItem("List")]
    public List[] Items { get; set; }
}

public class List
{
    [XmlElement("id")]
    public string Id { get; set; }
}

public class AuthorizationList
{
    [XmlElement("authorizations")]
    public Authorization[] Authorizations { get; set; }
}

Then you deserialize instance of your AuthorizationList type rather that List<T> as with the previous solution.

AuthorizationList l = FromXml<AuthorizationList>(xml);

Note that the root XML element will also need to match that type name also.

<AuthorizationList>
<authorizations>
  <id>111</id>
  <name>Name 1</name>
  <Lists>
    <List>
      <id>1</id>
      <id>2</id>
    </List>
  </Lists>
</authorizations>
<authorizations>
  <id>222</id>
  <name>Name 2</name>
  <List />
</authorizations>
<authorizations>
  <id>333</id>
  <name>Name 3</name>
  <List />
</authorizations>
</AuthorizationList>