HugoRune February 2016

Writing compact xml with XmlDictionaryWriter.CreateBinaryWriter and a XmlDictionary

I want to write an xml document to disk in a compact format. To this end, I use the net framework method XmlDictionaryWriter.CreateBinaryWriter(Stream stream,IXmlDictionary dictionary)

This method writes a custom compact binary xml representation, that can later be read by XmlDictionaryWriter.CreateBinaryReader. The method accepts an XmlDictionary that can contain common strings, so that those strings do not have to be printed in the output each time. Instead of the string, the dictionary index will be printed in the file. CreateBinaryReader can later use the same dictionary to reverse the process.

However the dictionary I pass is apparently not used. Consider this code:

using System.IO;
using System.Xml;
using System.Xml.Linq;

class Program
    public static void Main()
        XmlDictionary dict = new XmlDictionary();

        XDocument xdoc = new XDocument();
        xdoc.Add(new XElement("myLongRoot",
                                new XAttribute("myLongAttribute", "myLongValue"),
                                new XElement("myLongChild", "myLongText"),
                                new XElement("myLongChild", "myLongText"),
                                new XElement("myLongChild", "myLongText")

        using (Stream stream = File.Create("binaryXml.txt"))
        using (var writer = XmlDictionaryWriter.CreateBinaryWriter(stream, dict))

The produced output is this (binary control characters not shown)



Ondrej Svejdar February 2016

Yes there is a misunderstanding. XmlDictionaryWriter is primarily used for serialization of objects and it is child class of XmlWriter. XDocument.WriteTo(XmlWriter something) takes XmlWriter as argument. The call XmlDictionaryWriter.CreateBinaryWriter will create an instance of System.Xml.XmlBinaryNodeWriter internally. This class has both methods for "regular" writing:

// override of XmlWriter
public override void WriteStartElement(string prefix, string localName)
  // plain old "xml" for me please

and for dictionary based approach:

// override of XmlDictionaryWriter
public override void WriteStartElement(string prefix, XmlDictionaryString localName)
  // I will use dictionary to hash element names to get shorter output

The later is mostly used if you serialize object via DataContractSerializer (notice its method WriteObject takes argument of both XmlDictionaryWriter and XmlWriter type), while XDocument takes just XmlWriter.

As for your problem - if I were you I'd make my own XmlWriter:

class CustomXmlWriter : XmlWriter
  private readonly XmlDictionaryWriter _writer;
  public CustomXmlWriter(XmlDictionaryWriter writer)
    _writer = writer;
  // override XmlWriter methods to use the dictionary-based approach instead

UPDATE (based on your comment)

If you indeed use DataContractSerializer you have few mistakes in your code.

1) POC classes have to be decorated with [DataContract] and [DataMember] attribute, the serialized value should be property and not field; also set namespace to empty value or you'll have to deal with namespaces in your dictionary as well. Like:

namespace  XmlStuff 

Post Status

Asked in February 2016
Viewed 2,282 times
Voted 10
Answered 1 times


Leave an answer