c# - Writing compact xml with XmlDictionaryWriter.CreateBinaryWriter and a XmlDictionary -


i want write xml document disk in compact format. end, use net framework method xmldictionarywriter.createbinarywriter(stream stream,ixmldictionary dictionary)

this method writes custom compact binary xml representation, can later read xmldictionarywriter.createbinaryreader. method accepts xmldictionary can contain common strings, strings not have printed in output each time. instead of string, dictionary index printed in file. createbinaryreader can later use same dictionary reverse process.

however dictionary pass apparently not used. consider 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 (binary control characters not shown)

@ mylongrootmylongattribute˜mylongvalue@mylongchild™ mylongtext@mylongchild™ mylongtext@mylongchild™ mylongtext 

so apparently xmldictionary has not been used. strings appear in entirety in output, multiple times.

this not problem limited xdocument. in above minimal example used xdocument demonstrate problem, stumbled upon while using xmldictionarywriter in conjunction datacontractserializer, commonly used. results same:

[serializable] public class mylongchild {     public double mylongtext = 0; } ... using (stream stream = file.create("binaryxml.txt")) using (var writer = xmldictionarywriter.createbinarywriter(stream, dict)) {     var dcs = new datacontractserializer(typeof(mylongchild));     dcs.writeobject(writer, new mylongchild()); } 

the resulting output did not use xmldictionary.

how can xmldictionarywriter use suplied xmldictionary?

or have misunderstood how works?

with datacontractserializer approach, tried debugging net framework code (visual studio/options/debugging/enable net. framework source stepping). apparently writer attempt lookup each of above strings in dictionary, expected. lookup fails in line 356 of xmlbinarywriter.cs, reasons not clear me.

alternatives have considered:

  • there overload xmldictionarywriter.createbinarywriter, accepts xmlbinarywritersession. writer adds new strings encounters session dictionary. however, i want use static dictionary reading , writing, known beforehand.

  • i wrap whole thing gzipstream , let compression take care of multiple instances of strings. however, not compress first instance of each string, , seems clumsy workaround overall.

yes there misunderstanding. xmldictionarywriter used serialization of objects , child class of xmlwriter. xdocument.writeto(xmlwriter something) takes xmlwriter argument. call xmldictionarywriter.createbinarywriter create instance of system.xml.xmlbinarynodewriter internally. class has both methods "regular" writing:

// override of xmlwriter public override void writestartelement(string prefix, string localname) {   // plain old "xml" me please } 

and dictionary based approach:

// override of xmldictionarywriter public override void writestartelement(string prefix, xmldictionarystring localname) {   // use dictionary hash element names shorter output } 

the later used if serialize object via datacontractserializer (notice method writeobject takes argument of both xmldictionarywriter , xmlwriter type), while xdocument takes xmlwriter.

as problem - if i'd make own xmlwriter:

class customxmlwriter : xmlwriter {   private readonly xmldictionarywriter _writer;   public customxmlwriter(xmldictionarywriter writer)   {     _writer = writer;   }   // override xmlwriter methods use dictionary-based approach instead } 

update (based on comment)

if indeed use datacontractserializer have few mistakes in code.

1) poc classes have decorated [datacontract] , [datamember] attribute, serialized value should property , not field; set namespace empty value or you'll have deal namespaces in dictionary well. like:

namespace  xmlstuff {   [datacontract(namespace = "")]   public class mylongchild   {     [datamember]     public double mylongtext { get; set; }   }    [datacontract(namespace = "")]   public class mylongroot   {     [datamember]     public ilist<mylongchild> items { get; set; }   } } 

2) provide instance of session well; null session dictionary writer uses default (xmlwriter-like) implementation:

// order matters - add new items @ bottom static readonly string[] s_terms = new string[] {     "mylongroot", "mylongchild", "mylongtext",      "http://www.w3.org/2001/xmlschema-instance", "items" };  public class customxmlbinarywritersession : xmlbinarywritersession {   private bool m_lock;   public void lock() { m_lock = true; }    public override bool tryadd(xmldictionarystring value, out int key)   {     if (m_lock)     {       key = -1;       return false;     }      return base.tryadd(value, out key);   } }  static void initializewriter(out xmldictionary dict, out xmlbinarywritersession session) {   dict = new xmldictionary();   var result = new customxmlbinarywritersession();   var key = 0;   foreach(var term in s_terms)   {     result.tryadd(dict.add(term), out key);   }   result.lock();   session = result; }  static void initializereader(out xmldictionary dict, out xmlbinaryreadersession session) {   dict = new xmldictionary();   var result = new xmlbinaryreadersession();   (var = 0; < s_terms.length; i++)   {     result.add(i, s_terms[i]);   }   session = result; }  static void main(string[] args) {   xmldictionary dict;   xmlbinarywritersession session;   initializewriter(out dict, out session);    var root = new mylongroot { items = new list<mylongchild>() };   root.items.add(new mylongchild { mylongtext = 24 });   root.items.add(new mylongchild { mylongtext = 25 });   root.items.add(new mylongchild { mylongtext = 27 });    byte[] buffer;   using (var stream = new memorystream())   {     using (var writer = xmldictionarywriter.createbinarywriter(stream, dict, session))     {       var dcs = new datacontractserializer(typeof(mylongroot));       dcs.writeobject(writer, root);     }     buffer = stream.toarray();   }     xmlbinaryreadersession readersession;   initializereader(out dict, out readersession);   using (var stream = new memorystream(buffer, false))   {     using (var reader = xmldictionaryreader.createbinaryreader(stream, dict, new xmldictionaryreaderquotas(), readersession))     {       var dcs = new datacontractserializer(typeof(mylongroot));       var rootcopy = dcs.readobject(reader);     }   } }     

Comments

Popular posts from this blog

javascript - jQuery: Add class depending on URL in the best way -

caching - How to check if a url path exists in the service worker cache -

Redirect to a HTTPS version using .htaccess -