• Main Page
  • Namespaces
  • Classes
  • Files
  • Directories
  • File List

XMLNode.cs

Go to the documentation of this file.
00001 
00002 //
00003 // XML storage classes version 1.5
00004 //
00005 // XMLNode.cs
00006 //
00007 // Copyright (c) 2010, 2014 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.Collections.Generic;
00042 
00043 namespace XMLStorage {
00044 
00045 /**
00046  * XMLNode is the in memory representation of an XML node
00047  * in the XMLStorage library.
00048  */
00049 public class XMLNode : AbstractXMLNode
00050 {
00051     public XMLNode(string name)
00052     {
00053         _name = name;
00054     }
00055 
00056     public XMLNode(string name, string leading)
00057     {
00058          _name = name;
00059          _leading = leading;
00060     }
00061 
00062     public XMLNode(XMLNode other)
00063     {
00064         assign(other);
00065     }
00066 
00067     protected string _name;
00068 
00069     public override string getName()
00070     {
00071         return _name;
00072     }
00073 
00074     public override string ToString()
00075     {
00076         return _name;
00077     }
00078 
00079     /**
00080      * Children contains the list of immediate child nodes.
00081      */
00082     public class Children : LinkedList<XMLNode>
00083     {
00084         public void assign(Children other)
00085         {
00086             this.Clear();
00087 
00088             foreach(XMLNode node in other)
00089                 AddLast(new XMLNode(node));
00090         }
00091 
00092         public void clear()
00093         {
00094             while(Count > 0) {
00095                 XMLNode node = Last.Value;
00096                 RemoveLast();
00097 
00098                 node.clear();
00099             }
00100         }
00101     }
00102 
00103     protected Children _children = new Children();
00104 
00105     public string _leading = "";
00106     public string _endLeading = "";
00107     public string _trailing = "";
00108 
00109     public void clear()
00110     {
00111         _leading = "";
00112         _content = "";
00113         _endLeading = "";
00114         _trailing = "";
00115 
00116         _attributes.Clear();
00117         _children.Clear();
00118 
00119         _name = "";
00120     }
00121 
00122     public void assign(XMLNode other)
00123     {
00124         _children.assign(other._children);
00125 
00126         _attributes = (Dictionary<string, string>) other._attributes;//@@ .clone();
00127 
00128         _leading = other._leading;
00129         _content = other._content;
00130         _endLeading = other._endLeading;
00131         _trailing = other._trailing;
00132     }
00133 
00134      /// add a new child node
00135     public void addChild(XMLNode child)
00136     {
00137         _children.AddLast(child);
00138     }
00139 
00140      /// read only access to an attribute
00141     public override string get(string attrName)
00142     {
00143         string found;
00144 
00145         if (_attributes.TryGetValue(attrName, out found))
00146             return found;
00147         else
00148             return "";
00149     }
00150 
00151      /// read only access to an attribute with default value
00152     public override string get(string attrName, string def)
00153     {
00154         string found;
00155 
00156         if (_attributes.TryGetValue(attrName, out found))
00157             return found;
00158         else
00159             return def;
00160     }
00161 
00162      /// Write access to an attribute
00163     public void put(string attrName, string value)
00164     {
00165         try {
00166             _attributes.Add(attrName, value);
00167         } catch(ArgumentException) {
00168             _attributes.Remove(attrName);
00169             _attributes.Add(attrName, value);
00170         }
00171     }
00172 
00173      /// convenient value access in children node
00174     public string getSubattrib(string nodeName, string attrName)
00175     {
00176         AbstractXMLNode node = find(nodeName);
00177 
00178         if (node != null)
00179             return node.get(attrName);
00180         else
00181             return "";
00182     }
00183 
00184     public string getSubattrib(string nodeName, string attrName, int n)
00185     {
00186         AbstractXMLNode node = find(nodeName, n);
00187 
00188         if (node != null)
00189             return node.get(attrName);
00190         else
00191             return "";
00192     }
00193 
00194     /// convenient storage of distinct values in children node
00195     public void putSubattrib(string nodeName, string attrName, string value)
00196     {
00197         XMLNode node = find(nodeName);
00198 
00199         if (node == null) {
00200             node = new XMLNode(nodeName);
00201             addChild(node);
00202         }
00203 
00204         node.put(attrName, value);
00205     }
00206 
00207     public void putSubattrib(string nodeName, string attrName, string value, int n)
00208     {
00209         XMLNode node = find(nodeName, n);
00210 
00211         if (node == null) {
00212             node = new XMLNode(nodeName);
00213             addChild(node);
00214         }
00215 
00216         node.put(attrName, value);
00217     }
00218 
00219     public Children getChildren()
00220     {
00221         return _children;
00222     }
00223 
00224     public override string getContent()
00225     {
00226         return XMLHelper.decodeXMLString(_content);
00227     }
00228 
00229     public void setContent(string s)
00230     {
00231         setContent(s, false);
00232     }
00233 
00234     public void setContent(string s, bool cdata)
00235     {
00236         _content = XMLHelper.encodeXMLString(s, cdata);
00237     }
00238 
00239     public enum WRITE_MODE {
00240 //TODO  FORMAT_PLAIN,       /// Write XML without any white space
00241         FORMAT_SMART,       /// preserve original white space and comments if present; pretty print otherwise
00242         FORMAT_ORIGINAL,    /// Write XML stream preserving original white space and comments
00243         FORMAT_PRETTY       /// pretty print node to stream without preserving original white space
00244     };
00245 
00246     public virtual void write(TextWriter w)
00247     {
00248         write(w, WRITE_MODE.FORMAT_SMART, 0);
00249     }
00250 
00251     public virtual void write(TextWriter w, WRITE_MODE mode)
00252     {
00253         write(w, mode, 0);
00254     }
00255 
00256      /// Write node with children tree
00257     public void write(TextWriter w, WRITE_MODE mode/*=FORMAT_SMART*/, int indent/*=0*/)
00258     {
00259         switch(mode) {
00260           case WRITE_MODE.FORMAT_PRETTY:
00261             prettyWriteWorker(w, indent);
00262             break;
00263 
00264           case WRITE_MODE.FORMAT_ORIGINAL:
00265             writeWorker(w, indent);
00266             break;
00267 
00268           default: // FORMAT_SMART
00269             smartWriteWorker(w, indent);
00270             break;
00271         }
00272     }
00273 
00274     public XMLNode getFirstChild()
00275     {
00276         if (_children.Count > 0)
00277             return _children.First.Value;
00278         else
00279             return null;
00280     }
00281 
00282     /**
00283      * Find a children node by name.
00284      * @param nodeName
00285      * @return
00286      */
00287     public XMLNode find(string nodeName)
00288     {
00289         foreach(XMLNode child in _children)
00290             if (child._name == nodeName)
00291                 return child;
00292 
00293         return null;
00294     }
00295 
00296     /**
00297      * Find the n'th children node with tag nodeName.
00298      * @param nodeName
00299      * @param n
00300      * @return
00301      */
00302     public XMLNode find(string nodeName, int n)
00303     {
00304         foreach(XMLNode child in _children)
00305             if (child._name == nodeName)
00306                 if (n-- == 0)
00307                     return child;
00308 
00309         return null;
00310     }
00311 
00312     /**
00313      * Search matching child node identified by key name and an attribute value.
00314      * @param nodeName
00315      * @param attrName
00316      * @param attrValue
00317      * @return XMLNode
00318      */
00319     public XMLNode find(string nodeName, string attrName, string attrValue)
00320     {
00321         foreach(XMLNode child in _children)
00322             if (child._name==nodeName && child.get(attrName)==attrValue)
00323                 return child;
00324 
00325         return null;
00326     }
00327 
00328     /**
00329      * Search matching child node identified by key name and an attribute value.
00330      * @param nodeName
00331      * @param attrName
00332      * @param attrValue
00333      * @param n
00334      * @return XMLNode
00335      */
00336     public XMLNode find(string nodeName, string attrName, string attrValue, int n)
00337     {
00338         foreach(XMLNode node in _children)
00339             if (node._name==nodeName && node.get(attrName)==attrValue)
00340                 if (n-- == 0)
00341                     return node;
00342 
00343         return null;
00344     }
00345 
00346      /// XPath find function
00347     public XMLNode findRelative(XPath xpath)
00348     {
00349         XMLNode node = this;
00350 
00351         foreach(XPathElement xelem in xpath)
00352         {
00353             node = xelem.find(node);
00354 
00355             if (node == null)
00356                 break;
00357         }
00358 
00359         return node;
00360     }
00361 
00362      /// relative XPath create function
00363     public AbstractXMLNode createRelative(XPath xpath)
00364     {
00365         XMLNode node = this;
00366 
00367         foreach(XPathElement elem in xpath) {
00368             XMLNode child = elem.find(node);
00369 
00370             if (child == null) {
00371                 child = new XMLNode(elem._childName);
00372                 node.addChild(child);
00373 
00374                 foreach(KeyValuePair<string, string> it in elem._mAttrAndAttr)
00375                     put(it.Key, it.Value);
00376             }
00377 
00378             node = child;
00379         }
00380 
00381         return node;
00382     }
00383 
00384 
00385     /**
00386      * Write node with children tree using original white space.
00387      * @param o
00388      * @param indent
00389      */
00390     protected void writeWorker(TextWriter w, int indent)
00391     {
00392         w.Write(_leading);
00393         w.Write('<');
00394         w.Write(XMLHelper.encodeXMLString(_name));
00395 
00396         foreach(KeyValuePair<string,string> it in _attributes) {
00397             string attrValue = it.Value;
00398 
00399             if (attrValue != null) {
00400                 w.Write(' ');
00401                 w.Write(XMLHelper.encodeXMLString(it.Key));
00402                 w.Write("=\"");
00403                 w.Write(XMLHelper.encodeXMLString(attrValue));
00404                 w.Write("\"");
00405             }
00406         }
00407 
00408 
00409         if (_children.Count>0 || _content.Length>0) {
00410             w.Write('>');
00411             w.Write(_content);
00412 
00413             foreach(XMLNode child in _children)
00414                 child.writeWorker(w, indent+1);
00415 
00416             w.Write(_endLeading);
00417             w.Write("</");
00418             w.Write(XMLHelper.encodeXMLString(_name));
00419             w.Write('>');
00420         } else
00421             w.Write("/>");
00422 
00423         w.Write(_trailing);
00424     }
00425 
00426     public static string XML_INDENT_SPACE = "  ";
00427 
00428     protected void prettyWriteWorker(TextWriter w, int indent)
00429     {
00430         for(int i=indent; i-->0; )
00431             w.Write(XML_INDENT_SPACE);
00432 
00433         w.Write('<');
00434         w.Write(XMLHelper.encodeXMLString(_name));
00435 
00436         foreach(KeyValuePair<string,string> it in _attributes) {
00437             string attrValue = it.Value;
00438 
00439             if (attrValue != null) {
00440                 w.Write(' ');
00441                 w.Write(XMLHelper.encodeXMLString(it.Key));
00442                 w.Write("=\"");
00443                 w.Write(XMLHelper.encodeXMLString(attrValue));
00444                 w.Write("\"");
00445             }
00446         }
00447 
00448         if (_children.Count>0 || _content.Length>0) {
00449             w.Write(">\n");
00450 
00451             foreach(XMLNode child in _children)
00452                 child.prettyWriteWorker(w, indent+1);
00453 
00454             for(int i=indent; i-->0; )
00455                 w.Write(XML_INDENT_SPACE);
00456 
00457             w.Write("</");
00458             w.Write(XMLHelper.encodeXMLString(_name));
00459             w.Write(">\n");
00460         } else
00461             w.Write("/>\n");
00462     }
00463 
00464     protected void smartWriteWorker(TextWriter w, int indent)
00465     {
00466         if (_leading.Length == 0)
00467             for(int i=indent; i-->0; )
00468                 w.Write(XML_INDENT_SPACE);
00469         else
00470             w.Write(_leading);
00471 
00472         w.Write('<');
00473         w.Write(XMLHelper.encodeXMLString(_name));
00474 
00475         foreach(KeyValuePair<string,string> it in _attributes) {
00476             string attrValue = it.Value;
00477 
00478             if (attrValue != null) {
00479                 w.Write(' ');
00480                 w.Write(XMLHelper.encodeXMLString(it.Key));
00481                 w.Write("=\"");
00482                 w.Write(XMLHelper.encodeXMLString(attrValue));
00483                 w.Write("\"");
00484             }
00485         }
00486 
00487         if (_children.Count==0 && _content.Length==0)
00488             w.Write("/>");
00489         else {
00490             w.Write('>');
00491 
00492             if (_content.Length == 0)
00493                 w.Write('\n');
00494             else
00495                 w.Write(_content);
00496 
00497             LinkedListNode<XMLNode> it = _children.First;
00498 
00499             if (it != null) {
00500                 for( ; it != null; it = it.Next )
00501                     it.Value.smartWriteWorker( w, indent + 1 );
00502 
00503                 if (_endLeading.Length == 0)
00504                     for(int i=indent; i-->0; )
00505                         w.Write(XML_INDENT_SPACE);
00506                 else
00507                     w.Write(_endLeading);
00508             } else
00509                 w.Write(_endLeading);
00510 
00511             w.Write("</");
00512             w.Write(XMLHelper.encodeXMLString(_name));
00513             w.Write('>');
00514         }
00515 
00516         if (_trailing.Length == 0)
00517             w.Write('\n');
00518         else
00519             w.Write(_trailing);
00520     }
00521 }
00522 
00523 } // namespace XMLStorage

Generated on Tue Oct 28 2014 00:05:07 for XMLStorage/C# by  doxygen 1.7.2