1

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

learning
  • 15
  • 3
  • `new XmlSerializer(typeof(child_element)` probably – Charlieface Apr 24 '23 at 23:36
  • Just tried changing `var serializer = new XmlSerializer(typeof(parent_element), "www.testing.com")` to `var serializer = new XmlSerializer(typeof(child_element), "www.testing.com")`Unfortunately it didn't work. Still testing it and I think it maybe something with the `var namespaces` or `WriteStartElement` – learning Apr 25 '23 at 00:08

1 Answers1

1
  • 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>
pfx
  • 20,323
  • 43
  • 37
  • 57
  • Your xml is stll not valid – Serge Apr 25 '23 at 09:55
  • it can not be deserialized to a c# class. I will remove down vote as soon as you fix xml.Compiller gives an error was not expected. – Serge Apr 25 '23 at 10:10
  • @Serge On deserialization an error indeed occurred `The specified type was not recognized: name='text_type', namespace='www.testing.`. The deserialization now succeeds by adding a `[XmlType("text_type")]` on the `child_element` class. I've updated my post. Thanks for noticing. – pfx Apr 25 '23 at 11:15
  • I upvoted your answer but is still not completely valid. I don' t know XML since it is an ancient technology but I am using Visual Studio to check it. I copy xml text and if it is completely valid I can see VS editor option "Paste XML as class" but in this case I don't see this option – Serge Apr 25 '23 at 11:51
  • @Serge Hi, given your valid previous remark, I gave above code a full serialize and deserialize roundtrip, and don't hit any exceptions anymore. – pfx Apr 25 '23 at 12:23
  • @pfx Thank you for your help I think I am getting closer to the answer. I just ran it on my end with the revised code you provided and I was able to get your same results. Unfortunately the results I am looking for has the `xmlns:xsi` on the childElement and only the `xmlns = testing` on the parent – learning Apr 25 '23 at 14:07
  • @learning There's no added value in having the `xmlns:xsi` on a different level. By convention, you'll find them most often - if not always - on the root element. I would not put too much effort into that one. – pfx Apr 25 '23 at 14:19
  • @pfx Thank you for your help I think I am starting to grasp it a lot more. Marking yours off as the answer. Once again thank you so much – learning Apr 25 '23 at 14:40