XML contains element with the namespace as empty URI breaks deserialization

39 views Asked by At

I have an XML with the following structure:

<?xml version="1.0" encoding="utf-8"?>
<ClientInfo xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tempuri.org/">
  <Error>0</Error>
  <ErrorMsg />
  <doc>
    <NewDataSet xmlns="">
      <Table>
        <SEGMENT>123456</SEGMENT>
      </Table>
    </NewDataSet>
  </doc>
</ClientInfo>

Please notice the NewDataSet xmlns="" tag. I'm trying to deserialize this XML with the following class ClientInfo:

[XmlRoot(ElementName = "Table")]
public partial class Table
{
    [XmlElement(ElementName = "SEGMENT")]
    public string SEGMENT { get; set; }
}

[XmlRoot(ElementName = "NewDataSet")]
public partial class MyDataSet
{
    [XmlElement(ElementName = "Table")]
    public Table Table { get; set; }
}

[XmlRoot(ElementName = "doc")]
public class Doc
{

    [XmlElement(ElementName = "NewDataSet")]
    public MyDataSet MyDataSet { get; set; }
}

[Serializable, XmlRoot(ElementName = "ClientInfo", Namespace = "http://tempuri.org/")]
public partial class ClientInfo
{

    [XmlElement(ElementName = "Error")]
    public int Error { get; set; }

    [XmlElement(ElementName = "ErrorMsg")]
    public object ErrorMsg { get; set; }

    [XmlElement(ElementName = "doc")]
    public Doc Doc { get; set; }
}

As a result, MyDataSet from the resulting object xmlResult.Doc.MyDataSet.Table.SEGMENT returns null.

Without xmlns="" everything works fine. Now this attribute is to stay. Can't really make people get rid of it. How can I make the app work with this thing in XML?

1

There are 1 answers

3
Yong Shun On BEST ANSWER

Approach 1: Add the namespace to Doc

A quick approach to resolve the issue is adding the namespace with empty string to the XmlElement attribute for the NewDataSet property as below:

[XmlRoot(ElementName = "doc")]
public class Doc
{
    [XmlElement(ElementName = "NewDataSet", Namespace="")]
    public MyDataSet MyDataSet { get; set; }
}

Approach 2: Remove the "xmlns" attribute and overwrite the Name

Similar to Gehan's answer on Unable to remove empty "xmlns" attribute from XElement using c#, you need to remove the "xmlns" attribute and overwrite the Name for each XmlNode as below:

After performing the steps above, and deserialize the XML to an object.

XDocument doc = XDocument.Parse(xml);
XNamespace df = doc.Root.Name.Namespace;

foreach (var node in doc.Descendants())
{
    if (node.Name.NamespaceName == String.Empty)
    {
        node.Attributes("xmlns").Remove();

        node.Name = df + node.Name.LocalName;
    }
}

using (TextReader sr = new StringReader(doc.ToString()))
{
    var serializer = new System.Xml.Serialization.XmlSerializer(typeof(ClientInfo));
    ClientInfo xmlResult = (ClientInfo)serializer.Deserialize(sr);
    Console.WriteLine(xmlResult.Doc.MyDataSet.Table.SEGMENT);
}