54

Can I make XmlSerializer ignore the namespace (xmlns attribute) on deserialization so that it doesn't matter if the attribute is added or not or even if the attribute is bogus? I know that the source will always be trusted so I don't care about the xmlns attribute.

NotDan
  • 31,709
  • 36
  • 116
  • 156
  • 1
    be careful, if you overwrite `NamespaceURI` it not only affects all of the elements but attributes as well. Sometimes that causes deserializer to ignore attributes which will set them all to null. – Stan R. Jun 09 '09 at 20:40
  • 1
    obviously there are pitfalls of ignoring namespaces. You could say the same thing about the elements - if the deserializer is expecting a namespace-qualified element, and finds an element in no namespace, then it will not set the associated property in the deserialized instance. Those are just the rules of the road. It worked in the example I gave because all elements had no namespace. – Cheeso Jun 11 '09 at 22:22

5 Answers5

58

Yes, you can tell the XmlSerializer to ignore namespaces during de-serialization.

Define an XmlTextReader that ignores namespaces. Like so:

// helper class to ignore namespaces when de-serializing
public class NamespaceIgnorantXmlTextReader : XmlTextReader
{
    public NamespaceIgnorantXmlTextReader(System.IO.TextReader reader): base(reader) { }

    public override string NamespaceURI
    {
        get { return ""; }
    }
}

// helper class to omit XML decl at start of document when serializing
public class XTWFND  : XmlTextWriter {
    public XTWFND (System.IO.TextWriter w) : base(w) { Formatting= System.Xml.Formatting.Indented;}
    public override void WriteStartDocument () { }
}

Here's an example of how you would de-serialize using that TextReader:

public class MyType1 
{
    public string Label
    {
        set {  _Label= value; } 
        get { return _Label; } 
    }

    private int _Epoch;
    public int Epoch
    {
        set {  _Epoch= value; } 
        get { return _Epoch; } 
    }        
}



    String RawXml_WithNamespaces = @"
      <MyType1 xmlns='urn:booboo-dee-doo'>
        <Label>This document has namespaces on its elements</Label>
        <Epoch xmlns='urn:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'>0</Epoch>
      </MyType1>";


    System.IO.StringReader sr;
    sr= new System.IO.StringReader(RawXml_WithNamespaces);
    var s1 = new XmlSerializer(typeof(MyType1));
    var o1= (MyType1) s1.Deserialize(new NamespaceIgnorantXmlTextReader(sr));
    System.Console.WriteLine("\n\nDe-serialized, then serialized again:\n");
    XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
    ns.Add("urn", "booboo-dee-doo");
    s1.Serialize(new XTWFND(System.Console.Out), o1, ns);
    Console.WriteLine("\n\n");

The result is like so:

    <MyType1>
      <Label>This document has namespaces on its elements</Label>
      <Epoch>0</Epoch>
    </MyType1>
Jay
  • 9,561
  • 7
  • 51
  • 72
Cheeso
  • 189,189
  • 101
  • 473
  • 713
  • 4
    Note this is the kind of thing I meant. You are not telling the XmlSerializer to ignore namespaces - you are giving it XML that has no namespaces. – John Saunders May 16 '09 at 21:09
  • 2
    ??? I don't understand. I gave it XML that had namespaces on the elements. The code de-serialized (read) the XML document and ignored the namespaces. – Cheeso May 17 '09 at 03:21
  • 1
    It ignored the _default_ namespace. Not other namespaces. – Suncat2000 Jul 11 '22 at 19:41
32

If you expect no namespace, but the input has namespaces, then you can set

Namespaces = false

on your XmlTextReader.

  • That would have been nice, but it only keeps the XmlTextReader from _processing_ namespaces. It _does not ignore_ namespaces, which are still required. It does seem to set the default namespace to "", which may be useful in some circumstances, just not when prefixes are used. – Suncat2000 Jul 11 '22 at 19:40
23

Exdended Wolfgang Grinfeld answer (w/o exception handling):

public static Message Convert(XmlDocument doc)
{
    Message obj;
    using (TextReader textReader = new StringReader(doc.OuterXml))
    {
        using (XmlTextReader reader = new XmlTextReader(textReader))
        {
            reader.Namespaces = false;
            XmlSerializer serializer = new XmlSerializer(typeof(Message));
            obj = (Message)serializer.Deserialize(reader);
        }
    }

    return obj;
}
klm_
  • 1,199
  • 1
  • 10
  • 26
  • 1
    it doesn't really ignore. It requires you to not include namespace if its set to false. – Christian Jul 27 '21 at 08:35
  • 1
    This worked for me quite well. My use case was to ignore namespaces if received in XML documents when deserializing to an object, that way the behavior is consistent if the namespace is present or not. Thank you. – joelc Oct 13 '21 at 14:52
2

Solved this by using XmlSerializer Deserialize to read from xml instead from stream. This way before xml is Deserialized, using Regex to remove xsi:type from the xml. Was doing this is Portable Class Library for Cross Platform, so did not had many other options :(. After this the deserialization seems to work fine.

Following code can help,

public static TClass Deserialize<TClass>(string xml) where TClass : class, new()
{
    var tClass = new TClass();

    xml = RemoveTypeTagFromXml(xml);

    var xmlSerializer = new XmlSerializer(typeof(TClass));
    using (TextReader textReader = new StringReader(xml))
    {
        tClass = (TClass)xmlSerializer.Deserialize(textReader);
    }
    return tClass;
}

public static string RemoveTypeTagFromXml(string xml)
{
    if (!string.IsNullOrEmpty(xml) && xml.Contains("xsi:type"))
    {
        xml = Regex.Replace(xml, @"\s+xsi:type=""\w+""", "");
    }
    return xml;
}
  • You can inform the namespace to the XmlSerializer, so don't need to remove from the XML: XmlSerializer serializer = new XmlSerializer(typeof(T), elementXml.GetDefaultNamespace().NamespaceName); return (T)serializer.Deserialize(elementXml.CreateReader()); – Vagner Gon Aug 16 '17 at 14:37
-5

Why try to make the XmlSerializer forget how XML works? It's a fact of XML that two elements with the same name but different namespaces are different elements.

If you want to process XML that has no namespaces, then you should pre-process it to remove the namespaces, and then pass it to the serializer.

John Saunders
  • 160,644
  • 26
  • 247
  • 397
  • 9
    John, what you say is true, however, you sometimes get "xml" data from guys who think xml is just nicely formatted data following an opening-tag .. end-tag style that utilizes angle brackets; they're completely oblivious to the whole namespace-concept; my guess is that NotDan is one of those poor guys that need to consume xml data provided by this kind people. I experienced [something similar.](http://stackoverflow.com/questions/13763333/xmlns-namespace-resilency) – MrCC Feb 28 '13 at 09:36
  • 3
    @John: Sometimes you have to pick your fights. "Just say no" over something relatively trivial and the client says "If you can't do it, there are plenty of others who can. Hasta la vista, baby!". We can point out potential issues but in the end it's their coin and their decision. If we want to keep their business we have to respect that decision and work around it. – Simon Elms Jun 23 '16 at 11:28
  • @simon that attitude is what has caused the problem to persist, even seven years later. I should have said just say "no, but we'll be glad to help you learn to produce valid XML". – John Saunders Jun 23 '16 at 11:37
  • 1
    @John, yeah until you have to interface with zml you have no control over. Please tell UPS, FedEx and USPS to fix their broken Web Services. I would love it. – ATL_DEV Nov 27 '17 at 02:46
  • Let me reiterate that last paragraph. Rather than having all of your "xml programs" each process a different language which is not XML, use preprocessors. This will isolate the insanity of your sources from your programmers, who will be able to just use standard XML APIs to process the XML. – John Saunders Apr 06 '18 at 02:08