XMLStreamWriter.cs

Go to the documentation of this file.
00001 
00002 //
00003 // XML storage classes version 1.5
00004 //
00005 // XMLStreamWriter.cs
00006 //
00007 // Copyright (c) 2010 Martin Fuchs <martin-fuchs@gmx.net>
00008 //
00009 
00010 
00011 /*
00012 
00013  All rights reserved.
00014 
00015  Redistribution and use in source and binary forms, with or without
00016  modification, are permitted provided that the following conditions are met:
00017 
00018  * Redistributions of source code must retain the above copyright
00019     notice, this list of conditions and the following disclaimer.
00020  * Redistributions in binary form must reproduce the above copyright
00021     notice, this list of conditions and the following disclaimer in
00022     the documentation and/or other materials provided with the
00023     distribution.
00024 
00025  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00026  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00028  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00029  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00030  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00031  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00032  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00033  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00034  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00035  POSSIBILITY OF SUCH DAMAGE.
00036 
00037 */
00038 
00039 using System;
00040 using System.IO;
00041 using System.Text;
00042 using System.Collections.Generic;
00043 
00044 namespace XMLStorage {
00045 
00046 /**
00047  * XMLStreamWriter is used to Write XML streams in XMLStorage.
00048  */
00049 public class XMLStreamWriter
00050 {
00051      // PRETTY_FLAGS
00052     public enum PRETTY_FLAGS {
00053         PRETTY_PLAIN    = 0,
00054         PRETTY_LINEFEED = 1,
00055         PRETTY_INDENT   = 2
00056     };
00057 
00058     public XMLStreamWriter(TextWriter w)
00059     {
00060         init(w, PRETTY_FLAGS.PRETTY_INDENT, new XMLHeader());
00061     }
00062 
00063     public XMLStreamWriter(string path)
00064     {
00065         init(new StreamWriter(path), PRETTY_FLAGS.PRETTY_INDENT, new XMLHeader());
00066     }
00067 
00068     public XMLStreamWriter(TextWriter w, PRETTY_FLAGS pretty, XMLHeader header)
00069     {
00070         init(w, pretty, header);
00071     }
00072 
00073     public XMLStreamWriter(string path, PRETTY_FLAGS pretty, XMLHeader header)
00074     {
00075         init(new StreamWriter(path), pretty, header);
00076     }
00077 
00078     private void init(TextWriter w, PRETTY_FLAGS pretty, XMLHeader header)
00079     {
00080         _out = w;
00081         _pretty = pretty;
00082 
00083         header.print(_out, false);
00084     }
00085 
00086     public void close()
00087     {
00088         _out.Write('\n');
00089         _out.Close();
00090     }
00091 
00092      /// create node and move to it
00093     public void create(string name)
00094     {
00095         if (_stack.Count > 0) {
00096             StackEntry last = (StackEntry) _stack.Peek();
00097 
00098             if (last._state < WRITESTATE.PRE_CLOSED) {
00099                 writeAttributes(last);
00100                 closePre(last);
00101             }
00102 
00103             last._children = true;
00104         }
00105 
00106         StackEntry entry = new StackEntry(name);
00107         _stack.Push(entry);
00108 
00109         writePre(entry);
00110     }
00111 
00112      /// go back to previous position
00113     public bool back()
00114     {
00115         if (_stack.Count > 0) {
00116             writePost((StackEntry)_stack.Peek());
00117 
00118             _stack.Pop();
00119 
00120             return true;
00121         } else
00122             return false;
00123     }
00124 
00125      /// attribute setting
00126     public void put(string attrName, Object value)
00127     {
00128         if (_stack.Count > 0) {
00129             Dictionary<string, string> attributes = ((StackEntry)_stack.Peek())._attributes;
00130 
00131             if (value != null)
00132                 attributes.Add(attrName, value.ToString());
00133             else
00134                 attributes.Remove(attrName);
00135         }
00136     }
00137 
00138      /// attribute setting
00139     public void put(string attrName, string value)
00140     {
00141         if (_stack.Count > 0) {
00142             Dictionary<string, string> attributes = ((StackEntry)_stack.Peek())._attributes;
00143 
00144             if (value != null)
00145                 attributes.Add(attrName, value);
00146             else
00147                 attributes.Remove(attrName);
00148         }
00149     }
00150 
00151     public void setContent(string s)
00152     {
00153         setContent(s, false);
00154     }
00155 
00156     public void setContent(string s, bool cdata)
00157     {
00158         if (_stack.Count > 0)
00159             ((StackEntry)_stack.Peek())._content = s!=null? XMLHelper.encodeXMLString(s, cdata): "";
00160     }
00161 
00162     protected enum WRITESTATE {
00163         NOTHING     = 0,
00164         /*PRE       = 1,*/
00165         ATTRIBUTES  = 2,
00166         PRE_CLOSED  = 3,
00167         /*CONTENT   = 4,*/
00168         POST        = 5
00169     }
00170 
00171     protected TextWriter    _out;
00172     protected PRETTY_FLAGS  _pretty;
00173 
00174     /**
00175      * StackEntry is used to hold state information when moving between nodes.
00176      */
00177     protected class StackEntry {
00178         public string       _nodeName;
00179         public Dictionary<string, string> _attributes = new Dictionary<string, string>();
00180         public string       _content = "";
00181         public WRITESTATE   _state;
00182         public bool         _children;
00183 
00184         public StackEntry(string nodeName)
00185         {
00186             _nodeName = nodeName;
00187             _children = false;
00188             _state = WRITESTATE.NOTHING;
00189         }
00190     };
00191 
00192     protected Stack<StackEntry> _stack = new Stack<StackEntry>();
00193 
00194 //  protected static string s_empty_attr = "";
00195 
00196     protected void closePre(StackEntry entry)
00197     {
00198         _out.Write('>');
00199 
00200         entry._state = WRITESTATE.PRE_CLOSED;
00201     }
00202 
00203     protected void writePre(StackEntry entry)
00204     {
00205         if (_pretty >= PRETTY_FLAGS.PRETTY_LINEFEED)
00206             _out.Write('\n');
00207 
00208         if (_pretty == PRETTY_FLAGS.PRETTY_INDENT)
00209             for(int i=_stack.Count; --i>0; )
00210                 _out.Write(XMLNode.XML_INDENT_SPACE);
00211 
00212         _out.Write("<" + XMLHelper.encodeXMLString(entry._nodeName));
00213         //entry._state = WRITESTATE.PRE;
00214     }
00215 
00216     protected void writeAttributes(StackEntry entry)
00217     {
00218         foreach(KeyValuePair<string, string> it in entry._attributes)
00219             _out.Write(" " + XMLHelper.encodeXMLString(it.Key) +
00220                        "=\"" + XMLHelper.encodeXMLString(it.Value) + "\"");
00221 
00222         entry._state = WRITESTATE.ATTRIBUTES;
00223     }
00224 
00225     protected void writePost(StackEntry entry)
00226     {
00227         if (entry._state < WRITESTATE.ATTRIBUTES)
00228             writeAttributes(entry);
00229 
00230         if (entry._children || entry._content.Length>0) {
00231             if (entry._state < WRITESTATE.PRE_CLOSED)
00232                 closePre(entry);
00233 
00234             _out.Write(entry._content);
00235             //entry._state = WRITESTATE.CONTENT;
00236 
00237             if (_pretty>=PRETTY_FLAGS.PRETTY_LINEFEED && entry._content.Length==0)
00238                 _out.Write('\n');
00239 
00240             if (_pretty==PRETTY_FLAGS.PRETTY_INDENT && entry._content.Length==0)
00241                 for(int i=_stack.Count; --i>0; )
00242                     _out.Write(XMLNode.XML_INDENT_SPACE);
00243 
00244             _out.Write("</" + XMLHelper.encodeXMLString(entry._nodeName) + ">");
00245         } else {
00246             _out.Write("/>");
00247         }
00248 
00249         entry._state = WRITESTATE.POST;
00250     }
00251 }
00252 
00253 } // namespace XMLStorage