Search code examples
c#xmlnamespacesdeserializationxml-deserialization

Problem when I add Namespace to the XmlRoot attribute when deserializing an XML


I am deserializing an XML file to a class. I am having trouble with the namespace(s).

When I use the attribute [XmlRoot(ElementName = "LandXML")] it deserializes ok however when I then serialize to an XML again the namespace is missing.

I have tried using the attribute [XmlRoot(ElementName = "LandXML",Namespace = "http://www.landxml.org/schema/LandXML-1.2")] however for some reason it wont deserialize?

My Deserialization Class LandXML

{
    // Commented out as it causes an error. 
    //[XmlRoot(ElementName = "LandXML",Namespace = "http://www.landxml.org/schema/LandXML-1.2")] 
   
    [XmlRoot(ElementName = "LandXML")]
    public class LandXML
    {

        [XmlElement(ElementName = "Units")]
        public Units Units { get; set; }

The Input XML File generate by a Leica application.

LandXML xmlns="http://www.landxml.org/schema/LandXML-1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.landxml.org/schema/LandXML-1.2 http://www.landxml.org/schema/LandXML-1.2/LandXML-1.2.xsd" version="1.2" date="2018-10-23" time="21:27:08.63" readOnly="false" language="English">
<Units>
...
</Units>

Deep within the Input XML there is also an element (& child elements) that have a different namespace as shown below:

<LandXML ...>
   <Units>
   ...
   </Units>
   <Survey>
   ...
   </Survey>
   <HexagonLandXML xmlns="http://xml.hexagon.com/schema/HeXML-1.8" xmlns:landxml="http://www.landxml.org/schema/LandXML-1.2" xsi:schemaLocation="http://xml.hexagon.com/schema/HeXML-1.8 http://xml.hexagon.com/schema/HeXML-1.8.xsd" averagingMode="Average" averagingMethod="Weighted" averagingPosLimit="0.010000" averagingHgtLimit="0.015000">
      <CoordinateSystem name="None">
      ...
      </CoordinateSystem>

My Deserialization class for the HexagonLandXML element. I tried the [XmlType] attribute to get the namespace but it did not seem to work?

// The following causes an error so I have commented out.
//[XmlType(Namespace = "http://xml.hexagon.com/schema/HeXML-1.8", TypeName = "HexagonLandXML")]

public class HexagonLandXML
{
    [XmlElement(ElementName = "Codelist")]
    public Codelist Codelist { get; set; }
}

My Output.xml File below without the correct namespaces. This file is created by a Serialize class I have written that simply serializes by LandXML object created above.

<LandXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" date="2022-06-22" time="16:31:46.94" version="1.2" language="English">
<Units>
...
</Units>
...
</Application>
<HexagonLandXML>
...
</HexagonLandXML>
</LandXML>

How can I change my class to correctly deal with the namespaces. My serialized Output.XML should be the same as my Deserialized Input.XML


Solution

  • I got it to work by using XmlReader. Previously I was trying to deserialize using XmlTextReader.

    I used the following attributes in my Deserialization class.

      [XmlRoot(ElementName = "LandXML",Namespace = "http://www.landxml.org/schema/LandXML-1.2")]
      public class LandXML
    
      [XmlType(Namespace = "http://xml.hexagon.com/schema/HeXML-1.8", TypeName = "HexagonLandXML")]
      public class HexagonLandXML
    

    My Deserialization Code

       public LandXML Deserialize_XmlReader()
        {
    
            LandXML landXML = new LandXML();
    
            // Create an instance of the XmlSerializer specifying type.
            XmlSerializer serializer = new XmlSerializer(typeof(Hexagon.LandXML));
    
            // Create the XmlSchemaSet class.
            XmlSchemaSet sc = new XmlSchemaSet();
    
            // Add the schemas to the collection.
            sc.Add("http://www.landxml.org/schema/LandXML-1.2", "http://www.landxml.org/schema/LandXML-1.2/LandXML-1.2.xsd");
            sc.Add("http://xml.hexagon.com/schema/HeXML-1.8", "http://xml.hexagon.com/schema/HeXML-1.8.xsd");
    
            XmlReaderSettings settings = new XmlReaderSettings();
            settings.IgnoreWhitespace = true;
            settings.IgnoreComments = true;
            settings.ValidationType = ValidationType.Schema;
            settings.Schemas = sc;
    
            XmlReader reader = XmlReader.Create(_filePath, settings);
    
            if (serializer.CanDeserialize(reader))
            {
                landXML = (Hexagon.LandXML)serializer.Deserialize(reader);
                return landXML;
            }
    

    Previously, I was deserializing without properly adding the settings for the schemas. It now works fine and serializes as expected. Thanks @jdweng for taking the time to review. I took your advise and isolated the error one issue at a time.