Eddie
Eddie

Reputation: 359

How to include attributes for an element (not the root) with XML Serialization in C#

I need to generate an XML that looks like this:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<inboundMessage xmlns="http://www.myurl.net">
  <header>
    <password>mypwd</password>
    <subscriberId>myuser</subscriberId>
  </header>
  <message xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="myType">
    <eventDate>2012-09-05T12:13:45.561-05:00</eventDate>
    <externalEventId />
    <externalId>SomeIdC</externalId>
  </message>
</inboundMessage>

The problem is that I don't know how to include the xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="myType" in my tag. My class that I need to serialize is this:

[XmlType("inboundMessage")]
[XmlRoot(Namespace = "http://www.myurl.net")]
public class InboundMessage
{
    [XmlElement(ElementName = "header")]
    public Header _header;
    [XmlElement(ElementName = "message")]
    public List<MyType> _messages;
}

What XmlAttributes do I need to add to my "_messages" member to make it serialize the way I want?

TIA, Ed

Upvotes: 5

Views: 855

Answers (2)

Eddie
Eddie

Reputation: 359

A coleague of mine came up with a somewhat similar solution, yet more complete. MyType had two properties added:

    [XmlNamespaceDeclarations]
    public XmlSerializerNamespaces Namespaces { get; set; }

    [XmlAttribute("type", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
    public string Type
    {
        get { return _type; }
        set { _type = value; }
    }

with _type being defined like this:

    private string _type = "myType";

Then the serialization was done in a different way:

        // declare an XmlAttributes object, indicating that the namespaces declaration should be kept
        var atts = new XmlAttributes { Xmlns = true };

        // declare an XmlAttributesOverrides object and ...
        var xover = new XmlAttributeOverrides();
        // ... add the XmlAttributes object with regard to the "Namespaces" property member of the "Message" type
        xover.Add(typeof(MyType), "Namespaces", atts);

        // set the Namespaces property for each message in the payload body
        var messageNamespaces = new XmlSerializerNamespaces();
        messageNamespaces.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance");
        foreach (var message in myInboundMessage._messages)
        {
            message.Namespaces = messageNamespaces;
        }

        // create a serializer
        var serializer = new XmlSerializer(object2Serialize.GetType(), xover);

        // add the namespaces for the root element
        var rootNamespaces = new XmlSerializerNamespaces();
        rootNamespaces.Add("", "http://www.myurl.net");

        // serialize and extract the XML as text
        string objectAsXmlText;
        using (var stream = new MemoryStream())
        using (var xmlTextWriter = new XmlTextWriter(stream, null))
        {
            serializer.Serialize(xmlTextWriter, object2Serialize, rootNamespaces);
            stream.Seek(0, SeekOrigin.Begin);
            var buffer = new byte[stream.Length];
            stream.Read(buffer, 0, (int)stream.Length);
            objectAsXmlText = Encoding.UTF8.GetString(buffer);
        }

Finally, the InboundMessage was decorated like this:

[XmlRoot("inboundMessage", Namespace = "http://www.myurl.net")]

With this approach I get exactely what I need.

Upvotes: 0

Matthias
Matthias

Reputation: 1799

Use XmlAttribute like this:

public class MyType
{
    [XmlAttribute("type", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
    public string Type { get; set; }
}

Upvotes: 1

Related Questions