Home Ask Login Register

Developers Planet

Your answer is one click away!

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();
        dict.Add("myLongRoot");
        dict.Add("myLongAttribute");
        dict.Add("myLongValue");
        dict.Add("myLongChild");
        dict.Add("myLongText");

        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))
        {
            xdoc.WriteTo(writer);
        }
    }
}

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

@
myLongRootmyLongAttribute˜myLongValue@myLongChild™
myLongText@myLon        

Answers


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

Search




Leave an answer


Quote of the day: live life

Devs Planet ®

2014-2016 www.devsplanet.com

Devs Planet © all rights reserved

Search