Search code examples
c#xmlserializationdeserializationserializable

C# XML Deserialization where root node sometimes has namespace attribute


I am trying to read PackageReferences from an XML document.

My xml file looks something like following:

<Project>
  <ItemGroup>
    <PackageReference Update="PackageName" Version="PackageVersion" />
  </ItemGroup>
</Project>

AND

<Project xmlns="http://url/">
  <ItemGroup>
    <PackageReference Update="PackageName" Version="PackageVersion" />
  </ItemGroup>
</Project>

Here is my deserialization code:

var xmlResolver = new XmlSecureResolver(new XmlUrlResolver(), new System.Security.PermissionSet(System.Security.Permissions.PermissionState.None));
using (var sr = new StringReader(this.FileSystem.File.ReadAllText(path)))
  {
    var xmlReaderSettings = new XmlReaderSettings { XmlResolver = xmlResolver };
    return (Project)new XmlSerializer(typeof(Project)).Deserialize(XmlReader.Create(sr, xmlReaderSettings));
  }

And here is the Project partial class:

{
    using System;
    using System.Xml.Serialization;

    [Serializable]
    public partial class Project
    {
        private ProjectItemGroup[] itemGroupField;

        [XmlElement("ItemGroup")]
        public ProjectItemGroup[] ItemGroup
        {
            //...
        }
    }

    [Serializable]
    public partial class ProjectItemGroup
    {
        private Package[] packageReferenceField;

        [XmlElement("PackageReference")]
        public Package[] PackageReference
        {
            get
            {
                return this.packageReferenceField;
            }
            set
            {
                this.packageReferenceField = value;
            }
        }
    }

}

My deserialization code can read the first xml file without issue, but crashes on the second one with xmlns="https://url/".

Error:

System.InvalidOperationException: There is an error in XML document (2, 2). ---> System.InvalidOperationException: <Project xmlns='http://url/'> was not expected.

How can I modify this program to safely ignore (or somehow handle) the xml namespace?


Solution

  • You can use a NamespaceIgnorantXmlTextReader

    public class NamespaceIgnorantXmlTextReader : XmlTextReader
    {
        public NamespaceIgnorantXmlTextReader(System.IO.TextReader reader) : base(reader) { }
    
        public override string NamespaceURI
        {
            get { return ""; }
        }
    }
    
    var ser = new XmlSerializer(typeof(Project));
    
    using var sr = new StringReader(xml);
    using var textReader = new NamespaceIgnorantXmlTextReader(sr);
    
    var proj = ser.Deserialize(textReader);
    

    You can also set textReader.Namespaces = false; before calling Deserialize