0

I'm trying to serialize an object into a string.

The xml from which the c# models was taken had multiple namespaces:

xmlns="http://www.example.org/standards/def/1" 
xmlns:ac="http://www.example.org/Standards/xyz/1" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:rlc="http://www.example.org/standards/def/1" 
xmlns:def1="http://www.lol.com/Standards/lol.xsd" Version="2013-06" xsi:schemaLocation="http://www.lol.org/standards/def/1 lol.xsd"

I'm serializing it with:

var deserialize = (MyType)pageDeserializer.Deserialize(reader);
var namespaces = new XmlSerializerNamespaces();
namespaces.Add("ac", "urn:http://www.example.org/Standards/xyz/1");
namespaces.Add("rlc", "urn:http://www.example.org/standards/def/1");
namespaces.Add("def1", "http://www.lol.com/Standards/lol.xsd" Version="2013-06" xsi:schemaLocation="http://www.lol.org/standards/def/1 lol.xsd");


var str = pageDeserializer.SerializeAsUtf8<JvInsReinsurance>(deserialize, namespaces);

Where the method SerializeAsUtf8 is:

public static string SerializeAsUtf8<T>(this XmlSerializer serializer, T o, XmlSerializerNamespaces ns)
{
    using (var textWriter = new Utf8StringWriter())
    {
        serializer.Serialize(textWriter, o, ns);
        return textWriter.ToString();
    }
}

I was expecting my XML to look like:

   <rlc:element1 attribute1="value">
   <ac:element1>VALUR</ac:element1>
   </rlc:element1>

What I get is:

   <element1 attribute1="value">
   <element1>VALUR</element1>
   </element1>

But the information for the namespace is not included, and this makes the subsequent xsd validation fail. How can I get the namespace prefixes included?

UPDATE 1

Removing the urn as suggested in the comments, made me go past the first step. Now I'm getting an error when validating against the XSD.

I get the following errors:

1.

The element 'ElementX' in namespace 'urn:http://www.example.org/standards/def/1' has invalid child element 'ElementY' in namespace 'http://www.example.org/standards/def/1'.

2.

The element 'ElementP' in namespace 'urn:http://www.example.org/standards/def/1' has invalid child element 'ElementQ' in namespace 'http://www.example.org/standards/def/1'.

For 1. the classes are

[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.example.org/standards/def/1")]
public partial class ElementX
{
    [XmlElement("ElementYName")]
    public ElementY[] ElementYNames { get; set; }
}


[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.example.org/standards/def/1")]
public partial class ElementY
{

    [XmlAttribute]
    public string Field1 { get; set; }

    public ElementYFieldAmountType FieldAmount { get; set; }

    public string Field2 { get; set; }


    private string field3;


/// <remarks/>
public string Field3
{
    get
    {
        return this.field3;
    }
    set
    {
        this.field3 = value;
    }
}

}

[Serializable]
[DesignerCategory("code")]
[XmlType(AnonymousType = true, Namespace = "http://www.example.org/standards/def/1")]
public class ElementYFieldAmountType
{
    public FieldAmount Amt { get; set; }
}

    [System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.example.org/standards/def/1")]
public class FieldAmount
{

    private string _ccyField;

    private decimal valueField;

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string Ccy
    {
        get
        {
            return this._ccyField;
        }
        set
        {
            this._ccyField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlTextAttribute()]
    public decimal Value
    {
        get
        {
            return this.valueField;
        }
        set
        {
            this.valueField = value;
        }
    }
}

With XSD

<xs:complexType name="ElementX">
        <xs:sequence>
            <xs:element ref="ElementY" minOccurs="0" maxOccurs="unbounded"/>


<xs:element name="ElementY" type="ElementYType"/>
<xs:element name="FieldAmount" type="AnyAmtType"/>


<xs:complexType name="ElementYType">
        <xs:sequence>
            <xs:element ref="Field2" minOccurs="0"/>
            <xs:element ref="FieldAmount" minOccurs="0"/>
            <xs:element ref="Field3" minOccurs="0"/>
        </xs:sequence>
        <xs:attribute name="Field1" type="xs:NMTOKEN" use="required"/>
    </xs:complexType>

For 2

[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.example.org/standards/def/1")]
public partial class ElementP
{
    public ElementQ ElementQName { get; set; }
}

[Serializable]
[DesignerCategory("code")]
[XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.example.org/standards/def/1")]
public class ElementQ
{

    public PercentageRateType Rate { get; set; }

}

    [Serializable]
[DesignerCategory("code")]
[XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.example.org/standards/def/1")]
public class PercentageRateType
{

   [XmlAttribute]
    public string RateUnit { get; set; }

    [XmlText]
    public decimal Value { get; set; }

}

They look fine to me, what's wrong with those?

10
  • Why you use urn:http:// instead of http:// ? Commented Mar 27, 2019 at 12:09
  • Good question. It's out of my control, we're consuming existing messages coming with that definition Commented Mar 27, 2019 at 12:10
  • Have you tried to use XmlNamespaceManager? Here is a small example Commented Mar 27, 2019 at 12:15
  • I would assume that works in the same way as the XmlSerializerNamespaces parameter does. Also, correct if I'm wrong, but in the example the code is deserializing the string? Commented Mar 27, 2019 at 12:17
  • What do your class look like? the namespace for each class has to be in a property in square brackets above the class. Commented Mar 27, 2019 at 12:21

3 Answers 3

1

Make sure your capitalization is correct. In some cases you have 'standards' and others you have 'Standards'. See code below :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            ElementX elementX = new ElementX()
            {
                ElementYNames = new ElementY[] {
                    new ElementY() {
                        FieldAmount =  new ElementYFieldAmountType() {
                            Amt = new FieldAmount() {
                               Ccy = "VALUR",
                               Value = 123.456M
                            }
                        },
                        Field1 = "a",
                        Field2 = "b",
                        Field3 = "c"
                    }
                }
            };

            XmlSerializer serializer = new XmlSerializer(typeof(ElementX));
            var namespaces = new XmlSerializerNamespaces();
            namespaces.Add("ac", "http://www.example.org/Standards/xyz/1");
            namespaces.Add("rlc", "http://www.example.org/Standards/def/1");
            namespaces.Add("def1", "http://www.lol.com/Standards/lol.xsd");

            string xml = Test.SerializeAsUtf8<ElementX>(serializer, elementX, namespaces);

        }

    }
    public static class Test
    {
        public static string SerializeAsUtf8<T>(this XmlSerializer serializer, T o, XmlSerializerNamespaces ns)
        {
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            StringWriter writer = new StringWriter();
            using (XmlWriter xWriter = XmlWriter.Create(writer, settings))
            {
                serializer.Serialize(xWriter, o, ns);
                return writer.ToString();
            }
        }
    }

    [XmlRoot(Namespace = "http://www.example.org/Standards/def/1")]
    public partial class ElementX
    {
        [XmlElement("ElementYName")]
        public ElementY[] ElementYNames { get; set; }

    }


    [System.SerializableAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.example.org/Standards/xyz/1")]
    public partial class ElementY
    {

        [XmlAttribute]
        public string Field1 { get; set; }

        public ElementYFieldAmountType FieldAmount { get; set; }

        public string Field2 { get; set; }


        private string field3;


        /// <remarks/>
        public string Field3
        {
            get
            {
                return this.field3;
            }
            set
            {
                this.field3 = value;
            }
        }

    }

    [Serializable]
    [XmlRoot("code")]
    [XmlType(AnonymousType = true, Namespace = "http://www.example.org/Standards/xyz/1")]
    public class ElementYFieldAmountType
    {
        public FieldAmount Amt { get; set; }
    }

    [System.SerializableAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.example.org/Standards/xyz/1")]
    public class FieldAmount
    {

        private string _ccyField;

        private decimal valueField;

        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string Ccy
        {
            get
            {
                return this._ccyField;
            }
            set
            {
                this._ccyField = value;
            }
        }

        /// <remarks/>
        [System.Xml.Serialization.XmlTextAttribute()]
        public decimal Value
        {
            get
            {
                return this.valueField;
            }
            set
            {
                this.valueField = value;
            }
        }
    }
}
Sign up to request clarification or add additional context in comments.

Comments

1

Your xsd is incomplete. I've made some new Xsd's from your classes which could look like these 2:

Schema0.xsd:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:import namespace="http://www.example.org/standards/def/1" />
  <xs:element name="ElementP" nillable="true" xmlns:q1="http://www.example.org/standards/def/1" type="q1:ElementP" />
  <xs:element name="ElementQ" nillable="true" xmlns:q2="http://www.example.org/standards/def/1" type="q2:ElementQ" />
  <xs:element name="PercentageRateType" nillable="true" xmlns:q3="http://www.example.org/standards/def/1" type="q3:PercentageRateType" />
  <xs:element name="ElementX" nillable="true" xmlns:q4="http://www.example.org/standards/def/1" type="q4:ElementX" />
  <xs:element name="ElementY" nillable="true" xmlns:q5="http://www.example.org/standards/def/1" type="q5:ElementY" />
  <xs:element name="ElementYFieldAmountType" nillable="true" xmlns:q6="http://www.example.org/standards/def/1" type="q6:ElementYFieldAmountType" />
  <xs:element name="FieldAmount" nillable="true" xmlns:q7="http://www.example.org/standards/def/1" type="q7:FieldAmount" />
</xs:schema>

Schema1.xsd:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:tns="http://www.example.org/standards/def/1" elementFormDefault="qualified" targetNamespace="http://www.example.org/standards/def/1" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:complexType name="ElementP">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="1" name="ElementQName">
        <xs:complexType>
          <xs:sequence>
            <xs:element minOccurs="0" maxOccurs="1" name="Rate">
              <xs:complexType>
                <xs:simpleContent>
                  <xs:extension base="xs:decimal">
                    <xs:attribute name="RateUnit" type="xs:string" />
                  </xs:extension>
                </xs:simpleContent>
              </xs:complexType>
            </xs:element>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="ElementQ">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="1" name="Rate">
        <xs:complexType>
          <xs:simpleContent>
            <xs:extension base="xs:decimal">
              <xs:attribute name="RateUnit" type="xs:string" />
            </xs:extension>
          </xs:simpleContent>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="PercentageRateType">
    <xs:simpleContent>
      <xs:extension base="xs:decimal">
        <xs:attribute name="RateUnit" type="xs:string" />
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>
  <xs:complexType name="ElementX">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="unbounded" name="ElementYName">
        <xs:complexType>
          <xs:sequence>
            <xs:element minOccurs="0" maxOccurs="1" name="FieldAmount">
              <xs:complexType>
                <xs:sequence>
                  <xs:element minOccurs="0" maxOccurs="1" name="Amt">
                    <xs:complexType>
                      <xs:simpleContent>
                        <xs:extension base="xs:decimal">
                          <xs:attribute name="Ccy" type="xs:string" />
                        </xs:extension>
                      </xs:simpleContent>
                    </xs:complexType>
                  </xs:element>
                </xs:sequence>
              </xs:complexType>
            </xs:element>
            <xs:element minOccurs="0" maxOccurs="1" name="Field2" type="xs:string" />
            <xs:element minOccurs="0" maxOccurs="1" name="Field3" type="xs:string" />
          </xs:sequence>
          <xs:attribute name="Field1" type="xs:string" />
        </xs:complexType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="ElementY">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="1" name="FieldAmount">
        <xs:complexType>
          <xs:sequence>
            <xs:element minOccurs="0" maxOccurs="1" name="Amt">
              <xs:complexType>
                <xs:simpleContent>
                  <xs:extension base="xs:decimal">
                    <xs:attribute name="Ccy" type="xs:string" />
                  </xs:extension>
                </xs:simpleContent>
              </xs:complexType>
            </xs:element>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
      <xs:element minOccurs="0" maxOccurs="1" name="Field2" type="xs:string" />
      <xs:element minOccurs="0" maxOccurs="1" name="Field3" type="xs:string" />
    </xs:sequence>
    <xs:attribute name="Field1" type="xs:string" />
  </xs:complexType>
  <xs:complexType name="ElementYFieldAmountType">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="1" name="Amt">
        <xs:complexType>
          <xs:simpleContent>
            <xs:extension base="xs:decimal">
              <xs:attribute name="Ccy" type="xs:string" />
            </xs:extension>
          </xs:simpleContent>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="FieldAmount">
    <xs:simpleContent>
      <xs:extension base="xs:decimal">
        <xs:attribute name="Ccy" type="xs:string" />
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>
</xs:schema>

Then the code:

using System;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Linq;
using System.Xml.Serialization;

namespace MaPiTest
{
    public class Utf8StringWriter : StringWriter
    {
        public sealed override Encoding Encoding { get { return Encoding.UTF8; } }
    }

    class Program
    {
        public static string SerializeAsUtf8<T>(XmlSerializer serializer, T o, XmlSerializerNamespaces ns)
        {
            using (var textWriter = new Utf8StringWriter())
            {
                serializer.Serialize(textWriter, o, ns);
                return textWriter.ToString();
            }
        }

        static void Main(string[] args)
        {
            ElementX elementX = new ElementX()
            {
                ElementYNames = new ElementY[] {
                    new ElementY() {
                        FieldAmount =  new ElementYFieldAmountType() {
                            Amt = new FieldAmount() {
                               Ccy = "VALUR",
                               Value = 123.456M
                            }
                        },
                        Field1 = "a",
                        Field2 = "b",
                        Field3 = "c"
                    }
                }
            };

            // Serialize
            XmlSerializer serializer = new XmlSerializer(typeof(ElementX));
            var namespaces = new XmlSerializerNamespaces();
            namespaces.Add("ac", "http://www.example.org/standards/xyz/1");
            namespaces.Add("rlc", "http://www.example.org/standards/def/1");
            namespaces.Add("def1", "http://www.lol.com/standards/lol.xsd");
            var xml = SerializeAsUtf8(serializer, elementX, namespaces);

            // Read into document.
            var doc = XDocument.Parse(xml);

            // Validate document with xsd.
            var schemas = new XmlSchemaSet();
            schemas.Add("", XmlReader.Create(new StringReader(File.ReadAllText("schema0.xsd"))));
            schemas.Add("http://www.example.org/standards/def/1", XmlReader.Create(new StringReader(File.ReadAllText("schema1.xsd"))));

            string error = null;
            doc.Validate(schemas, (o, e) => Console.WriteLine(error = e.Message));

        }
    }
}

The resulting xml btw looks like this:

<?xml version="1.0" encoding="utf-8" ?>
<ElementX xmlns:ac="http://www.example.org/standards/xyz/1" xmlns:def1="http://www.lol.com/standards/lol.xsd" xmlns:rlc="http://www.example.org/standards/def/1">
  <rlc:ElementYName Field1="a">
    <rlc:FieldAmount>
      <rlc:Amt Ccy="VALUR">123.456</rlc:Amt>
    </rlc:FieldAmount>
    <rlc:Field2>b</rlc:Field2>
    <rlc:Field3>c</rlc:Field3>
  </rlc:ElementYName>
</ElementX>

This validates correct.

You could try to change the xml, either just adding a change manually or changing a property name in ElementX. And then inspect the validation error either in console or at a breakpoint.

Hope it helps...

Comments

0

Thanks everyone for your suggestions!

In the end the error was due to the fact that element were serialized out of order and the xsd validation was throwing a cryptic error message

The element 'ElementX' in namespace 'urn:http://www.example.org/standards/def/1' has invalid child element 'ElementY' in namespace 'http://www.example.org/standards/def/1'.

Using XmlOrder to order the attributes solved the issue

[XmlElement(Order = 1, IsNullable = true)]
public string ElementY

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.