0

I have a class representing a book and when I run the SerializeToXmlElement() method, it includes the class but not the class properties. How can I ensure that the public properties are included in the XML output?

Book class

[XmlType("Edition")]
public class Book 
{
    #region Attributes
    private string series;
    private string title;
    private string isbn;
    private string pubDate;
    #endregion Attributes

    #region Encapsulated fields
    [XmlElement]
    public string Series { get => series; set => series = value; }
    [XmlElement]
    public string Title { get => title; set => title = value; }
    [XmlElement("ISBN")]
    public string Isbn { get => isbn; set => isbn = value; }
    [XmlElement("Publication_Date")]
    public string EditionPubDate { get => pubDate; set => pubDate = value; }
    #endregion Encapsulated fields

    #region Constructors
    public Book() { }
    #endregion Constructors

    #region Methods
    public XmlElement SerializeToXmlElement()
    {
        XmlDocument doc = new XmlDocument();
        using (XmlWriter writer = doc.CreateNavigator().AppendChild())
        {
            new XmlSerializer(this.GetType()).Serialize(writer, this);
        }
        return doc.DocumentElement;
    }
    #endregion Methods
}

Input

XmlDocument doc = new XmlDocument();
doc.AppendChild(doc.CreateXmlDeclaration("1.0","utf-8",null));
XmlNode rootnode = doc.AppendChild(doc.CreateElement("Root_Node"));
XmlNode editionsNode = rootnode.AppendChild(doc.CreateElement("Editions"));

Book b = new Book();
b.Isbn = "978-0-553-10953-5";
b.Title = "A Brief History of Time";
XmlNode edition = doc.ImportNode(b.SerializeToXmlElement(), false);
editionsNode.AppendChild(edition);
edition.AppendChild(doc.CreateElement("Impressions"));

Output

<Root_Node>
    <Editions>
        <Edition xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
            <Impressions />
        </Edition>
    </Editions>
</Root_Node>

Bonus points for someone who can tell me how I can remove the xmlns:xsi and xmlns:xsd attributes from the Edition node in the XML output.

dbc
  • 104,963
  • 20
  • 228
  • 340
ryansin
  • 1,735
  • 2
  • 26
  • 49

1 Answers1

1

You need to pass true for the second parameter to XmlDocument.ImportNode(XmlNode, Boolean):

deep
 Type: System.Boolean
true to perform a deep clone; otherwise, false.

This indicates that the child nodes of the incoming node should be copied as well. Thus, your code should look like:

XmlNode edition = doc.ImportNode(b.SerializeToXmlElement(), true);

Bonus points for someone who can tell me how I can remove the xmlns:xsi and xmlns:xsd attributes from the Edition node in the XML output.

As explained in this answer to Omitting all xsi and xsd namespaces when serializing an object in .NET? by Thomas Levesque you need to pass an XmlSerializerNamespaces with an empty name/namespace pair into Serialize():

public XmlElement SerializeToXmlElement()
{
    XmlDocument doc = new XmlDocument();
    using (XmlWriter writer = doc.CreateNavigator().AppendChild())
    {
        var ns = new XmlSerializerNamespaces();
        ns.Add("", ""); // Disable the xmlns:xsi and xmlns:xsd lines.
        new XmlSerializer(this.GetType()).Serialize(writer, this, ns);
    }
    return doc.DocumentElement;
}

Working .Net fiddle.

dbc
  • 104,963
  • 20
  • 228
  • 340
  • Perfect, thank you. Is there also a way to omit inherited properties from being serialized to XML? – ryansin Mar 16 '18 at 10:19
  • 1
    @ryansin - there are already questions about this, e.g. [XMLSerialize and EXCLUDE the base class](https://stackoverflow.com/q/26916696/3744182) and [.net XmlSerializer, ignore base class properties](https://stackoverflow.com/q/1089967/3744182). If those don't meed your needs I'd suggest asking another question. – dbc Mar 16 '18 at 10:23
  • Thanks @dbc I was able to include ShouldSerializeXXX methods to override base class properties – ryansin Mar 16 '18 at 11:02