Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XmlSerializer + Abstract class + Derived classes = Useless namespaces

My first question on SO :,) and it's about XmlSerializer and namespace issue.

I know that there's already a lot of subject on how to remove the default Xml namespace from the root element of the Xml file and it's not the subject.

My question is how to remove it from child nodes when you're using derived classes ?

I've created my own serializer that can take custom namespaces or simply ignore them, and it's working well for the root element.

But when I use an abstract class to list some derived classes inside a List the serialization insert 2 attributes inside each derived classes' nodes.

Like this :

<root>
  <elements>
    <element p3:type="XmlDerivedClass" xmlns:p3="{schema_url}" >
    </element>
  </elements>
</root>

As for my classes :

// Root element
[XmlRoot("root", Namespace="")]
public class XmlRootElement
{
    List<XmlBaseClass> _Elements;
}    

// Base class
[XmlInclude(typeof(XmlDerivedClass))] // Mandatory, prevents serialization errors
[XmlRoot(Namespace="")]
public abstract class XmlBaseClass

// Derived class
[XmlRoot("element", Namespace="")]
public class XmlDerivedClass : XmlBaseClass

I tried some common solutions :

  • Using the Namespace="" attribute
  • Implementing the XmlNamespaceDeclarations property (with the right empty Namespace)
  • Moving the XmlRoot() from base clase to derived one
  • Changing XmlRoot() to XmlElement()

I'll try to add the XmlInclude tag on the List to see if it changes something.

So far, nothing worked to remove those damn namespaces...

If anyone has a solution for this, I'll be glad to try it.

[EDIT 21/02/2014] Well, it seems that I'm the only one facing this issue. I'll use a simple string.Replace to remove the useless XML but that's quite dirty.


PS : For the context, the tags aren't an issue for the parser on the other end BUT they're not needed so I'm looking for a way to remove them.

PS2 : Sorry for the any spelling mistakes, English isn't my native language.

like image 524
Ethenyl Avatar asked Nov 28 '13 10:11

Ethenyl


1 Answers

I am not sure whether this is a solution which satisfies your needs because it's not really nice but it works and it doesn't seem too dirty.

public abstract class Abs
{
    public int Data { get; set; }
}


public class A : Abs{}

public class B : Abs{}

[Serializable]
[XmlRoot(elementName: "name")]
public class Ser
{
    [XmlElement(elementName: "A")]
    public List<A> AList { get; set; }

    [XmlElement(elementName: "B")]
    public List<B> BList { get; set; }

    [XmlIgnore]
    public List<Abs> AbsList {
        get
        {
            var list = new List<Abs>(AList.ConvertAll(x=>(Abs)x));
            list.AddRange(BList.ConvertAll(x=>(Abs)x));
            return list;
        }
    }
}

Instead of XmlInclude you can create a List with derived-class objects and afterwards add them together or maybe cache them within a private member. Please notice again this is still far from ideal but it works for me so i wanted to share it.

like image 95
user3194973 Avatar answered Nov 10 '22 23:11

user3194973