Search code examples
c#xmlxml-serializationxml-namespacesxml-attribute

XML Serialization Namespace both Child and Parent Elements


Good day all,

I have trouble adding namespaces correctly to my XML. Both the parent and child elements have the own namespaces. When restructure the code I have gotten mixed results. My sample code below:

using System;
using System.IO;
using System.Xml.Serialization;

namespace XmlSerializationExample
{
    class Program
    {
        static void Main(string[] args)
        {
            var grandchild = new grandchild_element { Value = "randomResults" };
            var child = new child_element { grandchildElement = grandchild };
            var parent = new parent_element { childElement = child };

            var serializer = new XmlSerializer(typeof(parent_element), "www.testing.com");
            var namespaces = new XmlSerializerNamespaces(new[]
            {
                new XmlQualifiedName("xsi", "http://www.w3.org/2001/XMLSchema-instance")
            });
            var settings = new XmlWriterSettings
            {
                OmitXmlDeclaration = true,
                Indent = true,
                Encoding = System.Text.Encoding.UTF8
            };

            string xmlOutPut = @"C:\Users\[user]\Desktop\xml_test_file_" + DateTime.Now.ToString("HHmmss") + ".xml";

            using (var fileStream = new FileStream(xmlOutPut, FileMode.Create))
            using (var xmlWriter = XmlWriter.Create(fileStream, settings))
            {
                xmlWriter.WriteStartElement("parentElement", "www.testing.com");

                serializer.Serialize(xmlWriter, parent, namespaces);

                xmlWriter.WriteEndElement();
            }
        }
    }

    [XmlRoot(ElementName = "parentElement", Namespace = "www.testing.com")]
    public class parent_element
    {
        public child_element childElement { get; set; }
    }

    public class child_element
    {
        [XmlElement(ElementName = "grandchildElement")]
        public grandchild_element grandchildElement { get; set; }

        [XmlAttribute(AttributeName = "xsi", Namespace = "http://www.w3.org/2000/xmlns/")]
        public string xsi = "http://www.w3.org/2001/XMLSchema-instance";

        [XmlAttribute(AttributeName = "type", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
        public string type = "text_type";
    }

    public class grandchild_element
    {
        [XmlText]
        public string Value { get; set; }
    }
}

My results have been

<parentElement xmlns="www.testing.com">

  <parentElement xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    <childElement xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="text_type">

      <grandchildElement>randomResults</grandchildElement>

    </childElement>

  </parentElement>

</parentElement>

The result I am looking for is without the second parentElement. Something that looks like what is below

<parentElement xmlns="www.testing.com">

    <childElement xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="text_type">

      <grandchildElement>randomResults</grandchildElement>

    </childElement>

</parentElement>

Any help would be great. I know I am over looking something but I am not sure what. Huge thanks in advance


Solution

    • Remove below 2 calls to the xmlWriter.
    xmlWriter.WriteStartElement("parentElement", "www.testing.com");
    
    xmlWriter.WriteEndElement();
    
    • You don't need the XmlSerializerNamespaces setup.

    • Remove below xsi property from the child_element class.

    [XmlAttribute(AttributeName = "xsi", Namespace = "http://www.w3.org/2000/xmlns/")]
    public string xsi = "http://www.w3.org/2001/XMLSchema-instance";
    
    • For deserialization purposes, do add a [XmlType("text_type")] attribute to the child_element class.

    Your model classes will look like below.

    [XmlRoot(ElementName = "parentElement", Namespace = "www.testing.com")]
    public class parent_element
    {
        public child_element childElement { get; set; }
    }
    
    [XmlType("text_type")]
    public class child_element
    {
        [XmlElement(ElementName = "grandchildElement")]
        public grandchild_element grandchildElement { get; set; }
    
        [XmlAttribute(AttributeName = "type", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
        public string type = "text_type";
    }
    
    public class grandchild_element
    {
        [XmlText]
        public string Value { get; set; }
    }
    

    The following code shows how to do the serialization.

    var grandchild = new grandchild_element { Value = "randomResults" };
    var child = new child_element { grandchildElement = grandchild };
    var parent = new parent_element { childElement = child };
    
    var serializer = new XmlSerializer(typeof(parent_element));
    var settings = new XmlWriterSettings
    {
        OmitXmlDeclaration = true,
        Indent = true,
        Encoding = System.Text.Encoding.UTF8,
    };
    
    string xmlOutPut = @"C:\Users\[user]\Desktop\xml_test_file_" + DateTime.Now.ToString("HHmmss") + ".xml";
    
    using (var fileStream = new FileStream(xmlOutPut, FileMode.Create))
    using (var xmlWriter = XmlWriter.Create(fileStream, settings))
    {
        serializer.Serialize(xmlWriter, parent);
    }
    

    This will result in the following xml.

    <parentElement 
        xmlns="www.testing.com"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <childElement xsi:type="text_type">
        <grandchildElement>randomResults</grandchildElement>
      </childElement>
    </parentElement>