Erin Owen
Erin Owen

Reputation: 66

Have both DataType and additional Attribute during Xml Serialization

I am attempting to create an XML document through the application of attributes on fields/properties ([XmlAttribute], [XmlElement], etc.) My problem is that I have a requirement that I attach an additional attribute to a primitive datatype in the style of:

<document xmlns:dt="urn:schemas-microsoft-com:datatypes" >
  <binary addAttribute="X" dt:dt="bin.base64">
    [... binary ...]
  </binary>
</document>

I'm making use of code like the following:

[Serializable]
public class Document {
    [XmlElement]
    public BinaryObject Binary { get; set; }
}

[Serializable]
public class BinaryObject {
    [XmlText(DataType = "base64Binary")]
    public byte[] Binary { get; set; }

    [XmlAttribute]
    public int AddAttribute { get; set; }
}

public class XmlExample {
    public static void Main(string[] args)
    {
        Document document = new Document();
        document.Binary = new BinaryObject();
        document.Binary.Binary = File.ReadAllBytes(@"FileName");
        document.Binary.AddAttribute = 0;

        XmlSerializer serializer = new XmlSerializer(typeof(Document));

        serializer.Serialize(Console.Out, document);
        Console.ReadLine();
    }
}

This, however, provides the following output:

<document>
  <binary addAttribute="X">
    [... binary ...]
  </binary>
</document>

If I attempt to move the byte[] Binary to the Document class instead I can get the xmlns:dt="..." as expected but I cannot attach the arbitrary addAttribute when I do so (unless I missed something obvious.) This was incorrect; I misread something in the XML that I was getting out of the XML. The xmlns:dt element was not added in this case.

The question is: Can I do this (have both the DataType and the addAttribute) exclusively through C# attributes?

Upvotes: 1

Views: 1594

Answers (2)

Erin Owen
Erin Owen

Reputation: 66

The answer to this question came partially from here: XmlSerializer attribute namespace for element type dt:dt namespace. The DataType = "base64Binary" does not apply the xmlns:dt="urn:schemas-microsoft-com:datatypes" dt:dt="bin.base64" to the element that it is attached to. An attribute has to be added to the BinaryObject that provides the dt:dt = "bin.base64" with the correct name space.

Final Code

[Serializable]
public class Document {
    public BinaryObject Binary { get; set; }
}

[Serializable]
public class BinaryObject {
    [XmlText]
    public byte[] Binary { get; set; }

    [XmlAttribute]
    public int AddAttribute { get; set; }

    // Adds the dt:dt object to the correct name space.
    [XmlAttribute("dt", Namespace = "urn:schemas-microsoft-com:datatypes")]
    public string DataType { get; set; }

    public BinaryObject() { DataType = "bin.base64"; }
}


public class XmlExample {
    public static void Main(string[] args)
    {
        XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();

        // Adds the needed namespace to the document.
        namespaces.Add("dt", "urn:schemas-microsoft-com:datatypes");

        Document document = new Document();
        document.Binary = new BinaryObject();
        document.Binary.Binary = new byte[]{0,1,2,3,4,5,6,7,8,9};
        document.Binary.AddAttribute = 0;

        XmlSerializer serializer = new XmlSerializer(typeof(Document));

        serializer.Serialize(Console.Out, document, namespaces);
        Console.ReadLine();
    }
}

Final Output

<Document xmlns:dt="urn:schemas-microsoft-com:datatypes">
  <Binary AddAttribute="0" dt:dt="bin.base64">AAECAwQFBgcICQ==</Binary>
</Document>

Upvotes: 1

jdweng
jdweng

Reputation: 34421

Try this

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


namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
        }
    }
    [XmlRoot("Document")]
    public class Document
    {
        [XmlText(DataType = "base64Binary")]
        public byte[] Binary { get; set; }
        [XmlAttribute]
        public int AddAttribute { get; set; }
    }

}
​

Upvotes: 0

Related Questions