Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

XMLStack.h

Go to the documentation of this file.
00001 // XMLStack.h
00002 // Author: Scott Moore
00003 // Permission to freely use, copy, modify, and distribute this source code 
00004 // is hereby granted.  No representations are made about the
00005 // suitability of this software for any purpose.  It is provided
00006 // "as is" without express or implied warranty.
00007 #ifndef _XMLSTACK_H
00008 #define _XMLSTACK_H
00009 
00010 #include <string>
00011 #include <vector>
00012 #include <map>
00013 #include <exception>
00014 #include <algorithm>
00015 #include <sstream>
00016 #include <iomanip>
00017 #include "ConvertEncoding.h"
00018 
00019 // The comments in this file are formatted to work with doxygen.
00020 // See http://www.doxygen.org for details.
00021 
00022 #define _CE ConvertEncoding
00023 
00024 // Forward declarations
00025 template<class _E, class _Tr, class _A> class XMLStackDocument;
00026 template<class _E, class _Tr, class _A> class XMLStackAttribute;
00027 
00028 
00029 
00031 class XMLStackException : public std::exception
00032 {
00033 public:
00035   XMLStackException(const std::string & Text) : m_Msg(Text) {}
00036 
00038   virtual ~XMLStackException() {}
00039 
00041   virtual const char *what() const { return m_Msg.c_str(); }
00042 private:
00043   std::string m_Msg;
00044 };
00045 
00046 
00047 
00048 
00050 template<class _E, class _Tr = std::char_traits<_E>,  class _A = std::allocator<_E> >
00051 class XMLStackNode
00052 {
00053 public:
00054   typedef XMLStackNode<_E, _Tr, _A> _XMLStackNode;
00055   typedef XMLStackDocument<_E, _Tr, _A> _XMLStackDocument;
00056   typedef XMLStackAttribute<_E, _Tr, _A> _XMLStackAttribute;
00057   typedef std::basic_string<_E, _Tr, _A> _XMLStackString;
00058 
00068   XMLStackNode(_XMLStackDocument *     Doc,
00069                const _XMLStackString & Name) : m_Doc(Doc), m_Name(Name) {}
00070   
00072   virtual ~XMLStackNode() {}
00073 
00075   const _XMLStackString & getNodeName(void) const { return m_Name; }
00076   
00078   _XMLStackString getPrefix(void) const
00079   {
00080     _XMLStackString::size_type Pos;
00081     _XMLStackString            Prefix;
00082 
00083     Pos = m_Name.find(':');
00084     if (Pos != _XMLStackString::npos)
00085     {
00086       Prefix.assign(m_Name.begin(), m_Name.begin() + Pos);
00087     }
00088     return Prefix;
00089   }
00090 
00092   _XMLStackString getLocalName(void) const
00093   {
00094     _XMLStackString::size_type Pos;
00095     _XMLStackString            Name;
00096 
00097     Pos = m_Name.find(':');
00098     if (Pos != _XMLStackString::npos)
00099     {
00100       Name.assign(m_Name, Pos + 1, _XMLStackString::npos);
00101     }
00102     else
00103     {
00104       return m_Name;
00105     }
00106     return Name;
00107   }
00108 
00110   virtual _XMLStackAttribute & createAttribute
00111     (const _XMLStackString & Name,
00112      const _XMLStackString & NamespaceURI = _XMLStackString())
00113   {
00114     throw XMLStackException("ERROR: Node type does not support attributes.");
00115   }
00116 
00118   virtual _XMLStackAttribute & getAttribute(const _XMLStackString & Name)
00119   {
00120     throw XMLStackException("ERROR: Node type does not support attributes.");
00121   }
00122 
00124   virtual bool hasAttribute(const _XMLStackString & Name) const
00125   {
00126     throw XMLStackException("ERROR: Node type does not support attributes.");
00127   }
00128 
00140   virtual void setValue(const _XMLStackString & Value)
00141   {
00142     throw XMLStackException("ERROR: setValue() not implemented for this"
00143       " node type");
00144   }
00145   virtual void setValue(unsigned long Value)
00146   {
00147     throw XMLStackException("ERROR: setValue() not implemented for this"
00148       " node type");
00149   }
00150   virtual void setValue(long Value)
00151   {
00152     throw XMLStackException("ERROR: setValue() not implemented for this"
00153       " node type");
00154   }
00155   virtual void setValue(unsigned int Value)
00156   {
00157     throw XMLStackException("ERROR: setValue() not implemented for this"
00158       " node type");
00159   }
00160   virtual void setValue(int Value)
00161   {
00162     throw XMLStackException("ERROR: setValue() not implemented for this"
00163       " node type");
00164   }
00165   virtual void setValue(unsigned short Value)
00166   {
00167     throw XMLStackException("ERROR: setValue() not implemented for this"
00168       " node type");
00169   }
00170   virtual void setValue(short Value)
00171   {
00172     throw XMLStackException("ERROR: setValue() not implemented for this"
00173       " node type");
00174   }
00175   virtual void setValue(signed char Value)
00176   {
00177     throw XMLStackException("ERROR: setValue() not implemented for this"
00178       " node type");
00179   }
00180   virtual void setValue(char Value)
00181   {
00182     throw XMLStackException("ERROR: setValue() not implemented for this"
00183       " node type");
00184   }
00185   virtual void setValue(unsigned char Value)
00186   {
00187     throw XMLStackException("ERROR: setValue() not implemented for this"
00188       " node type");
00189   }
00190   virtual void setValue(double Value, int Scale = 6)
00191   {
00192     throw XMLStackException("ERROR: setValue() not implemented for this"
00193       " node type");
00194   }
00195   virtual void setValue(float Value, int Scale = 6)
00196   {
00197     throw XMLStackException("ERROR: setValue() not implemented for this"
00198       " node type");
00199   }
00200 
00202   _XMLStackNode & operator=(const _XMLStackString & Value)
00203   {
00204     setValue(Value);
00205     return *this;
00206   }
00208   _XMLStackNode & operator=(unsigned long & Value)
00209   {
00210     setValue(Value);
00211     return *this;
00212   }
00214   _XMLStackNode & operator=(long Value)
00215   {
00216     setValue(Value);
00217     return *this;
00218   }
00220   _XMLStackNode & operator=(unsigned int Value)
00221   {
00222     setValue(Value);
00223     return *this;
00224   }
00226   _XMLStackNode & operator=(int Value)
00227   {
00228     setValue(Value);
00229     return *this;
00230   }
00232   _XMLStackNode & operator=(unsigned short Value)
00233   {
00234     setValue(Value);
00235     return *this;
00236   }
00238   _XMLStackNode & operator=(short Value)
00239   {
00240     setValue(Value);
00241     return *this;
00242   }
00244   _XMLStackNode & operator=(signed char Value)
00245   {
00246     setValue(Value);
00247     return *this;
00248   }
00250   _XMLStackNode & operator=(char Value)
00251   {
00252     setValue(Value);
00253     return *this;
00254   }
00256   _XMLStackNode & operator=(unsigned char Value)
00257   {
00258     setValue(Value);
00259     return *this;
00260   }
00262   _XMLStackNode & operator=(double Value)
00263   {
00264     setValue(Value);
00265     return *this;
00266   }
00268   _XMLStackNode & operator=(float Value)
00269   {
00270     setValue(Value);
00271     return *this;
00272   }
00273 protected:
00274   virtual bool childNodePushed(void) { return false; }
00275   virtual void popped(void) { }
00276   virtual _XMLStackNode * clone(void) const = 0;
00277 
00278   typedef std::basic_stringstream<_E, _Tr, _A> _XMLStackStringStream;
00279 
00280   _XMLStackString convertValue(unsigned long Value)
00281   {
00282     _XMLStackStringStream Stream;
00283     Stream << Value;
00284     return Stream.str();
00285   }
00286 
00287   _XMLStackString convertValue(long Value)
00288   {
00289     _XMLStackStringStream Stream;
00290     Stream << Value;
00291     return Stream.str();
00292   }
00293 
00294   _XMLStackString convertValue(unsigned int Value)
00295   {
00296     _XMLStackStringStream Stream;
00297     Stream << Value;
00298     return Stream.str();
00299   }
00300 
00301   _XMLStackString convertValue(int Value)
00302   {
00303     _XMLStackStringStream Stream;
00304     Stream << Value;
00305     return Stream.str();
00306   }
00307 
00308   _XMLStackString convertValue(unsigned short Value)
00309   {
00310     _XMLStackStringStream Stream;
00311     Stream << Value;
00312     return Stream.str();
00313   }
00314 
00315   _XMLStackString convertValue(short Value)
00316   {
00317     _XMLStackStringStream Stream;
00318     Stream << Value;
00319     return Stream.str();
00320   }
00321 
00322   _XMLStackString convertValue(signed char Value)
00323   {
00324     _XMLStackStringStream Stream;
00325     Stream << Value;
00326     return Stream.str();
00327   }
00328 
00329   _XMLStackString convertValue(char Value)
00330   {
00331     _XMLStackStringStream Stream;
00332     Stream << Value;
00333     return Stream.str();
00334   }
00335 
00336   _XMLStackString convertValue(unsigned char Value)
00337   {
00338     _XMLStackStringStream Stream;
00339     Stream << Value;
00340     return Stream.str();
00341   }
00342 
00343   _XMLStackString convertValue(double Value, int Scale)
00344   {
00345     _XMLStackStringStream Stream;
00346     Stream << std::fixed << std::setprecision(Scale) << Value;
00347     return Stream.str();
00348   }
00349 
00350   _XMLStackString convertValue(float Value, int Scale)
00351   {
00352     _XMLStackStringStream Stream;
00353     Stream << std::fixed << std::setprecision(Scale) << Value;
00354     return Stream.str();
00355   }
00356 
00357   // Appends the passed in XML to the document's XML buffer.
00358   // NOTE: It is important to use this method instead of
00359   // GetBuffer().append() because this method provides
00360   // better performance by minimizing memory allocations
00361   // and copying.
00362   void appendXML(const _XMLStackString & XML)
00363   {
00364     m_Doc->appendXML(XML);
00365   }
00366 
00367   // Returns a reference to the XML buffer held by the XMLStackDocument
00368   inline _XMLStackString & getBuffer(void) { return m_Doc->m_XML; }
00369 
00370   _XMLStackDocument * m_Doc;
00371   _XMLStackString     m_Name;
00372 
00373 private:
00374 
00375   friend class XMLStackDocument<_E, _Tr, _A>;
00376 };
00377 
00378 
00384 template<class _E, class _Tr = std::char_traits<_E>,  class _A = std::allocator<_E> >
00385 class XMLStackElement : public XMLStackNode<_E, _Tr, _A>
00386 {
00387 public:
00388   typedef XMLStackElement<_E, _Tr, _A> _XMLStackElement;
00389 
00402   XMLStackElement(_XMLStackDocument *     Doc,
00403                   const _XMLStackString & Name)
00404    : _XMLStackNode(Doc, Name)
00405   {
00406     m_StartTagBegin = 0;
00407     m_StartTagEnd   = 0;
00408     m_Dirty         = false;
00409     m_NSDefined     = false;
00410 
00411 #ifdef _DEBUG
00412     checkName();
00413 #endif
00414   }
00415 
00440   XMLStackElement(_XMLStackDocument *     Doc,
00441                   const _XMLStackString & Name,
00442                   const _XMLStackString & NamespaceURI)
00443    : _XMLStackNode(Doc, Name), m_NamespaceURI(NamespaceURI)
00444   {
00445     m_StartTagBegin = 0;
00446     m_StartTagEnd   = 0;
00447     m_Dirty         = false;
00448     m_NSDefined     = true;
00449 
00450 #ifdef _DEBUG
00451     checkName();
00452 #endif
00453   }
00454 
00456   virtual ~XMLStackElement()
00457   {
00458     // Free up any attributes
00459     for (AttributesVec::iterator Iter = m_AttributesVec.begin();
00460          Iter != m_AttributesVec.end(); ++Iter)
00461     {
00462       delete (*Iter);
00463     }
00464   }
00465 
00467   const _XMLStackString & getNamespaceURI(void) const
00468   {
00469     return m_NamespaceURI;
00470   }
00471 
00485   virtual void setValue(const _XMLStackString & Value)
00486   {
00487     m_Doc->pushText(Value);
00488     m_Doc->pop();
00489   }
00490   virtual void setValue(unsigned long Value) { setValue(convertValue(Value)); }
00491   virtual void setValue(long Value) { setValue(convertValue(Value)); }
00492   virtual void setValue(unsigned int Value) { setValue(convertValue(Value)); }
00493   virtual void setValue(int Value) { setValue(convertValue(Value)); }
00494   virtual void setValue(unsigned short Value) { setValue(convertValue(Value)); }
00495   virtual void setValue(short Value) { setValue(convertValue(Value)); }
00496   virtual void setValue(signed char Value) { setValue(convertValue(Value)); }
00497   virtual void setValue(char Value) { setValue(convertValue(Value)); }
00498   virtual void setValue(unsigned char Value) { setValue(convertValue(Value)); }
00499   virtual void setValue(double Value, int Scale = 6)
00500   { 
00501     setValue(convertValue(Value, Scale)); 
00502   }
00503   virtual void setValue(float Value, int Scale = 6)
00504   { 
00505     setValue(convertValue(Value, Scale)); 
00506   }
00507 
00528   virtual _XMLStackAttribute & createAttribute
00529     (const _XMLStackString & Name,
00530      const _XMLStackString & NamespaceURI = _XMLStackString())
00531   {
00532     if (m_Attributes.find(Name) == m_Attributes.end())
00533     {
00534       // We use the vector to maintain the attributes in the order they
00535       // are created
00536       m_AttributesVec.push_back
00537         (new _XMLStackAttribute(m_Doc, Name, NamespaceURI));
00538 
00539       // We use the map for fast lookup
00540       m_Attributes[Name] = m_AttributesVec.back();
00541       m_Dirty = true;
00542       return *m_AttributesVec.back();
00543     }
00544     std::string Msg;
00545 
00546     Msg = "ERROR: Element node ";
00547     Msg += _CE(m_Name.c_str());
00548     Msg += " already has an Attribute node named ";
00549     Msg += _CE(Name.c_str());
00550     Msg += ".";
00551     throw XMLStackException(Msg);
00552   }
00553 
00560   virtual _XMLStackAttribute & getAttribute(const _XMLStackString & Name)
00561   {
00562     Attributes::iterator Iter = m_Attributes.find(Name);
00563 
00564     if (Iter != m_Attributes.end())
00565     {
00566       return *(*Iter).second;
00567     }
00568     std::string Msg;
00569 
00570     Msg = "ERROR: Element node ";
00571     Msg += _CE(m_Name.c_str());
00572     Msg += " does not have an Attribute node named ";
00573     Msg += _CE(Name.c_str());
00574     Msg += ".";
00575     throw XMLStackException(Msg);
00576   }
00577 
00582   virtual bool hasAttribute(const _XMLStackString & Name) const
00583   {
00584     if (m_Attributes.find(Name) != m_Attributes.end())
00585     {
00586       return true;
00587     }
00588     return false;
00589   }
00590   
00592   _XMLStackElement & operator=(const _XMLStackString & Value)
00593   {
00594     setValue(Value);
00595     return *this;
00596   }
00597 
00599   _XMLStackElement & operator=(unsigned long & Value)
00600   {
00601     setValue(Value);
00602     return *this;
00603   }
00604 
00606   _XMLStackElement & operator=(long Value)
00607   {
00608     setValue(Value);
00609     return *this;
00610   }
00611 
00613   _XMLStackElement & operator=(unsigned int Value)
00614   {
00615     setValue(Value);
00616     return *this;
00617   }
00618 
00620   _XMLStackElement & operator=(int Value)
00621   {
00622     setValue(Value);
00623     return *this;
00624   }
00625 
00627   _XMLStackElement & operator=(unsigned short Value)
00628   {
00629     setValue(Value);
00630     return *this;
00631   }
00632 
00634   _XMLStackElement & operator=(short Value)
00635   {
00636     setValue(Value);
00637     return *this;
00638   }
00639 
00641   _XMLStackElement & operator=(signed char Value)
00642   {
00643     setValue(Value);
00644     return *this;
00645   }
00646 
00648   _XMLStackElement & operator=(char Value)
00649   {
00650     setValue(Value);
00651     return *this;
00652   }
00653 
00655   _XMLStackElement & operator=(unsigned char Value)
00656   {
00657     setValue(Value);
00658     return *this;
00659   }
00660 
00662   _XMLStackElement & operator=(double Value)
00663   {
00664     setValue(Value);
00665     return *this;
00666   }
00667 
00669   _XMLStackElement & operator=(float Value)
00670   {
00671     setValue(Value);
00672     return *this;
00673   }
00674 
00675 
00676 protected:
00677   virtual bool childNodePushed(void)
00678   {
00679     writeStartTag();
00680     return true;
00681   }
00682 
00683   typedef std::map<_XMLStackString, _XMLStackAttribute *> Attributes;
00684   typedef std::vector<_XMLStackAttribute *> AttributesVec;
00685 
00686   _XMLStackString m_NamespaceURI;
00687   Attributes      m_Attributes;
00688   AttributesVec   m_AttributesVec;
00689   size_t          m_StartTagBegin;
00690   size_t          m_StartTagEnd;
00691   bool            m_Dirty;
00692   bool            m_NSDefined;
00693 
00694   void writeStartTag(bool EndTag = false)
00695   {
00696     if ((m_StartTagBegin + m_StartTagEnd) == 0 || m_Dirty)
00697     {
00698       _XMLStackString Tag;
00699 
00700       Tag = m_Doc->VALS.LT;
00701       Tag += m_Name;
00702 
00703       // A namespace was defined, so we will need to output the definition
00704       if (m_NSDefined)
00705       {
00706         _XMLStackString Prefix = getPrefix();
00707 
00708         if (Prefix.length() > 0)
00709         {
00710           Tag += m_Doc->VALS.S_XMLNS_C;
00711           Tag += Prefix;
00712           Tag += m_Doc->VALS.EQUAL + m_Doc->VALS.QUOTE;
00713           Tag += m_NamespaceURI + m_Doc->VALS.QUOTE;
00714         }
00715         else
00716         {
00717           Tag += m_Doc->VALS.SPACE + m_Doc->VALS.XMLNS + m_Doc->VALS.EQUAL;
00718           Tag += m_Doc->VALS.QUOTE + m_NamespaceURI + m_Doc->VALS.QUOTE;
00719         }
00720       }
00721 
00722       // Write out all the attributes
00723       for (AttributesVec::iterator Iter = m_AttributesVec.begin();
00724            Iter != m_AttributesVec.end(); ++Iter)
00725       {
00726         Tag += m_Doc->VALS.SPACE;
00727         Tag += (*Iter)->xml();
00728         (*Iter)->setDirty(false);
00729       }
00730 
00731       if (EndTag)
00732       {
00733         Tag += m_Doc->VALS.SLASH + m_Doc->VALS.GT;
00734       }
00735       else
00736       {
00737         Tag += m_Doc->VALS.GT;
00738       }
00739 
00740       if ((m_StartTagBegin + m_StartTagEnd) == 0)
00741       {
00742         // Never written out before, this is the most efficient
00743         m_StartTagBegin = getBuffer().size();
00744         appendXML(Tag);
00745         m_StartTagEnd = getBuffer().size();
00746       }
00747       else
00748       {
00749         // There have been changes that require us to replace the XML text
00750         // that was already written.  This is a performance hit and
00751         // the programmer should minimize this activity as much as possible
00752         getBuffer().replace(m_StartTagBegin, m_StartTagEnd - m_StartTagBegin, Tag);
00753         m_StartTagEnd = m_StartTagBegin + Tag.size() - 1;
00754       }
00755       m_Dirty = false;
00756     }
00757   }
00758 
00759   virtual void popped(void)
00760   {
00761     _XMLStackString Tag;
00762 
00763     if ((m_StartTagBegin + m_StartTagEnd) == 0)
00764     {
00765       writeStartTag(true);
00766     }
00767     else
00768     {
00769       if (!m_Dirty)
00770       {
00771         // Check our attributes and make sure they aren't dirty
00772         for (AttributesVec::iterator Iter = m_AttributesVec.begin();
00773              Iter != m_AttributesVec.end(); ++Iter)
00774         {
00775           if ((*Iter)->isDirty())
00776           {
00777             m_Dirty = true;
00778             break;
00779           }
00780         }
00781       }
00782 
00783       if (m_Dirty)
00784       {
00785         // There have been changes that require us to replace the text
00786         // that was already written.  This is a performance hit and
00787         // the programmer should minimize this activity as much as possible
00788         writeStartTag(false);
00789       }
00790       Tag += m_Doc->VALS.LT + m_Doc->VALS.SLASH;
00791       Tag += m_Name;
00792       Tag += m_Doc->VALS.GT;
00793       appendXML(Tag);
00794     }
00795   }
00796 
00797   virtual _XMLStackNode * clone(void) const
00798   { 
00799     return new _XMLStackElement(*this); 
00800   }
00801 
00802   void checkName(void) const
00803   {
00804     // This is part of the set of characters that are illegal as a node
00805     // name.  In C++, to specify a non-printable character, you escape it
00806     // and provide it's octal code.  For example, "\13" is the decimal
00807     // character with the value 11.
00808     const wchar_t * IllegalChars = L"/;<=>?@[\\]^`\173\174\175\176";
00809     bool            Illegal      = false;
00810   
00811     if (m_Name.size() == 0)
00812     {
00813       throw XMLStackException("ERROR: Element nodes must have a defined"
00814         " name.");
00815     }
00816 
00817     // This performs some rudimentary checking for illegal node names.
00818     // This is by no means exhaustive, but does catch some of the more
00819     // common mistakes.
00820     // This is a time consuming test, so only perform it in debug builds
00821     int j;
00822     for (int i = 0; i < m_Name.size(); ++i)
00823     {
00824       if (m_Name[i] <= 44)
00825       {
00826         // No character below value 45 is legal
00827         Illegal = true;
00828       }
00829 
00830       j = 0;
00831       while (!Illegal && IllegalChars[j] != 0)
00832       {
00833         if (m_Name[i] == IllegalChars[j])
00834         {
00835           Illegal = true;
00836         }
00837         j++;
00838       }
00839 
00840       if (Illegal)
00841       {
00842         std::stringstream Msg;
00843         Msg << "ERROR: Invalid character found in node name";
00844         if (m_Name[i] < L' ' || m_Name[i] > L'z')
00845         {
00846           Msg << ".  Decimal value of illegal character is " << (int) m_Name[i];
00847         }
00848         else
00849         {
00850           Msg << " -->" << (char) m_Name[i] << "<--";
00851         }
00852         throw XMLStackException(Msg.str());
00853       }
00854     }
00855   }
00856 
00857 };
00858 
00859 
00861 template<class _E, class _Tr = std::char_traits<_E>,  class _A = std::allocator<_E> >
00862 class XMLStackAttribute : public XMLStackNode<_E, _Tr, _A>
00863 {
00864 public:
00888   XMLStackAttribute(_XMLStackDocument *     Doc,
00889                     const _XMLStackString & Name,
00890                     const _XMLStackString & NamespaceURI = _XMLStackString())
00891    : _XMLStackNode(Doc, Name), m_NamespaceURI(NamespaceURI)
00892   {
00893     m_Dirty = false;
00894 
00895     // This is a time consuming test, so only perform it in debug builds
00896 #ifdef _DEBUG
00897     // This is part of the set of characters that are illegal as a node
00898     // name.  In C++, to specify a non-printable character, you escape it
00899     // and provide it's octal code.  For example, "\13" is the decimal
00900     // character with the value 11.
00901     const wchar_t * IllegalChars = L"/;<=>?@[\\]^`\173\174\175\176";
00902     bool            Illegal      = false;
00903   
00904     if (Name.size() == 0)
00905     {
00906       throw XMLStackException("ERROR: Attribute nodes must have a defined"
00907         " name.");
00908     }
00909 
00910     // This performs some rudimentary checking for illegal node names.
00911     // This is by no means exhaustive, but does catch some of the more
00912     // common mistakes.
00913     int j;
00914     for (int i = 0; i < Name.size(); ++i)
00915     {
00916       if (Name[i] <= 44)
00917       {
00918         // No character below value 45 is legal
00919         Illegal = true;
00920       }
00921 
00922       j = 0;
00923       while (!Illegal && IllegalChars[j] != L'\0')
00924       {
00925         if (Name[i] == IllegalChars[j])
00926         {
00927           Illegal = true;
00928         }
00929         j++;
00930       }
00931 
00932       if (Illegal)
00933       {
00934         std::stringstream Msg;
00935         Msg << "ERROR: Invalid character found in node name";
00936         if (Name[i] < L' ' || Name[i] > L'z')
00937         {
00938           Msg << ".  Decimal value of illegal character is " << (int) Name[i];
00939         }
00940         else
00941         {
00942           Msg << " -->" << (char) Name[i] << "<--";
00943         }
00944         throw XMLStackException(Msg.str());
00945       }
00946     }
00947 #endif
00948   }
00949   
00951   virtual ~XMLStackAttribute() {}
00952 
00954   const _XMLStackString & getNamespaceURI(void) const
00955   {
00956     return m_NamespaceURI;
00957   }
00958 
00963   virtual void setValue(const _XMLStackString & Value)
00964   {
00965     m_Value = Value;
00966     m_Dirty = true;
00967   }
00968   virtual void setValue(unsigned long Value) { setValue(convertValue(Value)); }
00969   virtual void setValue(long Value) { setValue(convertValue(Value)); }
00970   virtual void setValue(unsigned int Value) { setValue(convertValue(Value)); }
00971   virtual void setValue(int Value) { setValue(convertValue(Value)); }
00972   virtual void setValue(unsigned short Value) { setValue(convertValue(Value)); }
00973   virtual void setValue(short Value) { setValue(convertValue(Value)); }
00974   virtual void setValue(signed char Value) { setValue(convertValue(Value)); }
00975   virtual void setValue(char Value) { setValue(convertValue(Value)); }
00976   virtual void setValue(unsigned char Value) { setValue(convertValue(Value)); }
00977   virtual void setValue(double Value, int Scale = 6)
00978   { 
00979     setValue(convertValue(Value, Scale)); 
00980   }
00981   virtual void setValue(float Value, int Scale = 6)
00982   { 
00983     setValue(convertValue(Value, Scale)); 
00984   }
00985 
00986   
00988   _XMLStackString xml(void) const
00989   {
00990     _XMLStackString Value;
00991 
00992     if (m_NamespaceURI.length() > 0)
00993     {
00994       _XMLStackString Prefix = getPrefix();
00995 
00996       if (Prefix.length() > 0)
00997       {
00998         Value += m_Doc->VALS.XMLNS + m_Doc->VALS.COLON;
00999         Value += Prefix + m_Doc->VALS.EQUAL + m_Doc->VALS.QUOTE;
01000         Value += m_NamespaceURI + m_Doc->VALS.QUOTE + m_Doc->VALS.SPACE;
01001       }
01002     }
01003 
01004     Value += m_Name + m_Doc->VALS.EQUAL + m_Doc->VALS.QUOTE;
01005 
01006     if (m_Value.size() > 0)
01007     {
01008       _XMLStackString::size_type Pos = 0;
01009 
01010       Pos = Value.size();
01011       Value += m_Value;
01012 
01013       while (Pos < Value.size())
01014       {
01015         if (Value[Pos] == '&')
01016         {
01017           Value.replace(Pos, 1, m_Doc->VALS.AMP_REF);
01018           Pos += m_Doc->VALS.AMP_REF.size();
01019         }
01020         else if (Value[Pos] == '<')
01021         {
01022           Value.replace(Pos, 1, m_Doc->VALS.LT_REF);
01023           Pos += m_Doc->VALS.LT_REF.size();
01024         }
01025         else if (Value[Pos] == '"')
01026         {
01027           Value.replace(Pos, 1, m_Doc->VALS.QUOTE_REF);
01028           Pos += m_Doc->VALS.QUOTE_REF.size();
01029         }
01030         else
01031         {
01032           Pos++;
01033         }
01034       }
01035     }
01036     Value += m_Doc->VALS.QUOTE;
01037 
01038     return Value;
01039   }
01040 
01042   bool isDirty(void) const { return m_Dirty; }
01043 
01045   void setDirty(bool Dirty) { m_Dirty = Dirty; }
01046 
01048   _XMLStackAttribute & operator=(const _XMLStackString & Value)
01049   {
01050     setValue(Value);
01051     return *this;
01052   }
01053 
01055   _XMLStackAttribute & operator=(unsigned long & Value)
01056   {
01057     setValue(Value);
01058     return *this;
01059   }
01060 
01062   _XMLStackAttribute & operator=(long Value)
01063   {
01064     setValue(Value);
01065     return *this;
01066   }
01067 
01069   _XMLStackAttribute & operator=(unsigned int Value)
01070   {
01071     setValue(Value);
01072     return *this;
01073   }
01074 
01076   _XMLStackAttribute & operator=(int Value)
01077   {
01078     setValue(Value);
01079     return *this;
01080   }
01081 
01083   _XMLStackAttribute & operator=(unsigned short Value)
01084   {
01085     setValue(Value);
01086     return *this;
01087   }
01088 
01090   _XMLStackAttribute & operator=(short Value)
01091   {
01092     setValue(Value);
01093     return *this;
01094   }
01095 
01097   _XMLStackAttribute & operator=(signed char Value)
01098   {
01099     setValue(Value);
01100     return *this;
01101   }
01102 
01104   _XMLStackAttribute & operator=(char Value)
01105   {
01106     setValue(Value);
01107     return *this;
01108   }
01109 
01111   _XMLStackAttribute & operator=(unsigned char Value)
01112   {
01113     setValue(Value);
01114     return *this;
01115   }
01116 
01118   _XMLStackAttribute & operator=(double Value)
01119   {
01120     setValue(Value);
01121     return *this;
01122   }
01123 
01125   _XMLStackAttribute & operator=(float Value)
01126   {
01127     setValue(Value);
01128     return *this;
01129   }
01130 
01131 
01132 protected:
01133 
01134   _XMLStackString m_NamespaceURI;
01135   _XMLStackString m_Value;
01136   bool            m_Dirty;
01137 
01138   virtual _XMLStackNode * clone(void) const
01139   { 
01140     return new _XMLStackAttribute(*this); 
01141   }
01142   friend class XMLStackElement<_E, _Tr, _A>;
01143 };
01144 
01145 
01152 template<class _E, class _Tr = std::char_traits<_E>,  class _A = std::allocator<_E> >
01153 class XMLStackText : public XMLStackNode<_E, _Tr, _A>
01154 {
01155 public:
01156   typedef XMLStackText<_E, _Tr, _A> _XMLStackText;
01157 
01165   XMLStackText(_XMLStackDocument *     Doc,
01166                const _XMLStackString & Data)
01167    : _XMLStackNode(Doc, _XMLStackString()), m_Value(Data)
01168   {
01169   }
01170 
01172   virtual ~XMLStackText() {}
01173 
01175   virtual void setValue(const _XMLStackString & Value) { m_Value = Value; }
01176   virtual void setValue(unsigned long Value) { setValue(convertValue(Value)); }
01177   virtual void setValue(long Value) { setValue(convertValue(Value)); }
01178   virtual void setValue(unsigned int Value) { setValue(convertValue(Value)); }
01179   virtual void setValue(int Value) { setValue(convertValue(Value)); }
01180   virtual void setValue(unsigned short Value) { setValue(convertValue(Value)); }
01181   virtual void setValue(short Value) { setValue(convertValue(Value)); }
01182   virtual void setValue(signed char Value) { setValue(convertValue(Value)); }
01183   virtual void setValue(char Value) { setValue(convertValue(Value)); }
01184   virtual void setValue(unsigned char Value) { setValue(convertValue(Value)); }
01185   virtual void setValue(double Value, int Scale = 6)
01186   { 
01187     setValue(convertValue(Value, Scale)); 
01188   }
01189   virtual void setValue(float Value, int Scale = 6)
01190   { 
01191     setValue(convertValue(Value, Scale)); 
01192   }
01193   
01195   _XMLStackText & operator=(const _XMLStackString & Value)
01196   {
01197     setValue(Value);
01198     return *this;
01199   }
01200 
01202   _XMLStackText & operator=(unsigned long & Value)
01203   {
01204     setValue(Value);
01205     return *this;
01206   }
01207 
01209   _XMLStackText & operator=(long Value)
01210   {
01211     setValue(Value);
01212     return *this;
01213   }
01214 
01216   _XMLStackText & operator=(unsigned int Value)
01217   {
01218     setValue(Value);
01219     return *this;
01220   }
01221 
01223   _XMLStackText & operator=(int Value)
01224   {
01225     setValue(Value);
01226     return *this;
01227   }
01228 
01230   _XMLStackText & operator=(unsigned short Value)
01231   {
01232     setValue(Value);
01233     return *this;
01234   }
01235 
01237   _XMLStackText & operator=(short Value)
01238   {
01239     setValue(Value);
01240     return *this;
01241   }
01242 
01244   _XMLStackText & operator=(signed char Value)
01245   {
01246     setValue(Value);
01247     return *this;
01248   }
01249 
01251   _XMLStackText & operator=(char Value)
01252   {
01253     setValue(Value);
01254     return *this;
01255   }
01256 
01258   _XMLStackText & operator=(unsigned char Value)
01259   {
01260     setValue(Value);
01261     return *this;
01262   }
01263 
01265   _XMLStackText & operator=(double Value)
01266   {
01267     setValue(Value);
01268     return *this;
01269   }
01270 
01272   _XMLStackText & operator=(float Value)
01273   {
01274     setValue(Value);
01275     return *this;
01276   }
01277 
01278 protected:
01279   _XMLStackString m_Value;
01280 
01281   virtual void popped(void)
01282   {
01283     if (m_Value.size() == 0)
01284     {
01285       return;
01286     }
01287     _XMLStackString::size_type Pos = 0;
01288 
01289     while (Pos < m_Value.size())
01290     {
01291       if (m_Value[Pos] == '&')
01292       {
01293         m_Value.replace(Pos, 1, m_Doc->VALS.AMP_REF);
01294         Pos += m_Doc->VALS.AMP_REF.size();
01295       }
01296       else if (m_Value[Pos] == '<')
01297       {
01298         m_Value.replace(Pos, 1, m_Doc->VALS.LT_REF);
01299         Pos += m_Doc->VALS.LT_REF.size();
01300       }
01301       else
01302       {
01303         Pos++;
01304       }
01305     }
01306     appendXML(m_Value);
01307   }
01308   
01309   virtual _XMLStackNode * clone(void) const
01310   { 
01311     return new _XMLStackText(*this); 
01312   }
01313 };
01314 
01326 template<class _E, class _Tr = std::char_traits<_E>,  class _A = std::allocator<_E> >
01327 class XMLStackCDATASection : public XMLStackNode<_E, _Tr, _A>
01328 {
01329 public:
01330   typedef XMLStackCDATASection<_E, _Tr, _A> _XMLStackCDATASection;
01331 
01341   XMLStackCDATASection(_XMLStackDocument *     Doc,
01342                        const _XMLStackString & Data)
01343    : _XMLStackNode(Doc, _XMLStackString()), m_Value(Data)
01344   {
01345   }
01346 
01348   virtual ~XMLStackCDATASection() {}
01349 
01351   virtual void setValue(const _XMLStackString & Value) { m_Value = Value; }
01352   virtual void setValue(unsigned long Value) { setValue(convertValue(Value)); }
01353   virtual void setValue(long Value) { setValue(convertValue(Value)); }
01354   virtual void setValue(unsigned int Value) { setValue(convertValue(Value)); }
01355   virtual void setValue(int Value) { setValue(convertValue(Value)); }
01356   virtual void setValue(unsigned short Value) { setValue(convertValue(Value)); }
01357   virtual void setValue(short Value) { setValue(convertValue(Value)); }
01358   virtual void setValue(signed char Value) { setValue(convertValue(Value)); }
01359   virtual void setValue(char Value) { setValue(convertValue(Value)); }
01360   virtual void setValue(unsigned char Value) { setValue(convertValue(Value)); }
01361   virtual void setValue(double Value, int Scale = 6)
01362   { 
01363     setValue(convertValue(Value, Scale)); 
01364   }
01365   virtual void setValue(float Value, int Scale = 6)
01366   { 
01367     setValue(convertValue(Value, Scale)); 
01368   }
01369   
01371   _XMLStackCDATASection & operator=(const _XMLStackString & Value)
01372   {
01373     setValue(Value);
01374     return *this;
01375   }
01376 
01378   _XMLStackCDATASection & operator=(unsigned long & Value)
01379   {
01380     setValue(Value);
01381     return *this;
01382   }
01383 
01385   _XMLStackCDATASection & operator=(long Value)
01386   {
01387     setValue(Value);
01388     return *this;
01389   }
01390 
01392   _XMLStackCDATASection & operator=(unsigned int Value)
01393   {
01394     setValue(Value);
01395     return *this;
01396   }
01397 
01399   _XMLStackCDATASection & operator=(int Value)
01400   {
01401     setValue(Value);
01402     return *this;
01403   }
01404 
01406   _XMLStackCDATASection & operator=(unsigned short Value)
01407   {
01408     setValue(Value);
01409     return *this;
01410   }
01411 
01413   _XMLStackCDATASection & operator=(short Value)
01414   {
01415     setValue(Value);
01416     return *this;
01417   }
01418 
01420   _XMLStackCDATASection & operator=(signed char Value)
01421   {
01422     setValue(Value);
01423     return *this;
01424   }
01425 
01427   _XMLStackCDATASection & operator=(char Value)
01428   {
01429     setValue(Value);
01430     return *this;
01431   }
01432 
01434   _XMLStackCDATASection & operator=(unsigned char Value)
01435   {
01436     setValue(Value);
01437     return *this;
01438   }
01439 
01441   _XMLStackCDATASection & operator=(double Value)
01442   {
01443     setValue(Value);
01444     return *this;
01445   }
01446 
01448   _XMLStackCDATASection & operator=(float Value)
01449   {
01450     setValue(Value);
01451     return *this;
01452   }
01453 
01454 protected:
01455   _XMLStackString m_Value;
01456 
01457   virtual void popped(void)
01458   {
01459 #ifdef _DEBUG
01460     if (m_Value.find(m_Doc->CDATA_END) != _XMLStackString::npos)
01461     {
01462       // Oops, "]]>" is the only reserved delimiter for CDATASection sections
01463       // and it cannot be escaped.  Throw an error.
01464       throw XMLStackException("ERROR: CDATASection node contains the reserved"
01465         " delimiter \"]]>\", which cannot be escaped.");
01466     }
01467 #endif
01468     _XMLStackString Value;
01469 
01470     Value = m_Doc->CDATA_START;
01471     Value += m_Value;
01472     Value += m_Doc->CDATA_END;
01473     appendXML(Value);
01474   }
01475 
01476   virtual _XMLStackNode * clone(void) const
01477   { 
01478     return new _XMLStackCDATASection(*this); 
01479   }
01480 };
01481 
01482 
01491 template<class _E, class _Tr = std::char_traits<_E>,  class _A = std::allocator<_E> >
01492 class XMLStackComment : public XMLStackNode<_E, _Tr, _A>
01493 {
01494 public:
01495   typedef XMLStackComment<_E, _Tr, _A> _XMLStackComment;
01496 
01507   XMLStackComment(_XMLStackDocument *     Doc,
01508                   const _XMLStackString & Data)
01509    : _XMLStackNode(Doc, _XMLStackString()), m_Text(Data)
01510   {
01511   }
01512 
01514   virtual ~XMLStackComment() {}
01515 
01517   virtual void setValue(const _XMLStackString & Value) { m_Text = Value; }
01518   virtual void setValue(unsigned long Value) { setValue(convertValue(Value)); }
01519   virtual void setValue(long Value) { setValue(convertValue(Value)); }
01520   virtual void setValue(unsigned int Value) { setValue(convertValue(Value)); }
01521   virtual void setValue(int Value) { setValue(convertValue(Value)); }
01522   virtual void setValue(unsigned short Value) { setValue(convertValue(Value)); }
01523   virtual void setValue(short Value) { setValue(convertValue(Value)); }
01524   virtual void setValue(signed char Value) { setValue(convertValue(Value)); }
01525   virtual void setValue(char Value) { setValue(convertValue(Value)); }
01526   virtual void setValue(unsigned char Value) { setValue(convertValue(Value)); }
01527   virtual void setValue(double Value, int Scale = 6)
01528   { 
01529     setValue(convertValue(Value, Scale)); 
01530   }
01531   virtual void setValue(float Value, int Scale = 6)
01532   { 
01533     setValue(convertValue(Value, Scale)); 
01534   }
01535   
01537   _XMLStackComment & operator=(const _XMLStackString & Value)
01538   {
01539     setValue(Value);
01540     return *this;
01541   }
01542 
01544   _XMLStackComment & operator=(unsigned long & Value)
01545   {
01546     setValue(Value);
01547     return *this;
01548   }
01549 
01551   _XMLStackComment & operator=(long Value)
01552   {
01553     setValue(Value);
01554     return *this;
01555   }
01556 
01558   _XMLStackComment & operator=(unsigned int Value)
01559   {
01560     setValue(Value);
01561     return *this;
01562   }
01563 
01565   _XMLStackComment & operator=(int Value)
01566   {
01567     setValue(Value);
01568     return *this;
01569   }
01570 
01572   _XMLStackComment & operator=(unsigned short Value)
01573   {
01574     setValue(Value);
01575     return *this;
01576   }
01577 
01579   _XMLStackComment & operator=(short Value)
01580   {
01581     setValue(Value);
01582     return *this;
01583   }
01584 
01586   _XMLStackComment & operator=(signed char Value)
01587   {
01588     setValue(Value);
01589     return *this;
01590   }
01591 
01593   _XMLStackComment & operator=(char Value)
01594   {
01595     setValue(Value);
01596     return *this;
01597   }
01598 
01600   _XMLStackComment & operator=(unsigned char Value)
01601   {
01602     setValue(Value);
01603     return *this;
01604   }
01605 
01607   _XMLStackComment & operator=(double Value)
01608   {
01609     setValue(Value);
01610     return *this;
01611   }
01612 
01614   _XMLStackComment & operator=(float Value)
01615   {
01616     setValue(Value);
01617     return *this;
01618   }
01619 
01620 protected:
01621   _XMLStackString m_Text;
01622 
01623   virtual void popped(void)
01624   {
01625 #ifdef _DEBUG
01626     if (m_Text.find(m_Doc->VALS.DASH2) != _XMLStackString::npos
01627       || (m_Text.size() > 0 && m_Text[m_Text.size() - 1] == '-'))
01628     {
01629       throw XMLStackException("ERROR: Comment nodes cannot contain the"
01630         " character sequence \"--\" or end with a single dash '-'");
01631     }
01632 #endif
01633     _XMLStackString Value(m_Doc->VALS.COMMENT_START);
01634     Value += m_Text + m_Doc->VALS.COMMENT_END;
01635     appendXML(Value);
01636   }
01637   virtual _XMLStackNode * clone(void) const
01638   { 
01639     return new _XMLStackComment(*this); 
01640   }
01641 };
01642 
01643 
01645 template<class _E, class _Tr = std::char_traits<_E>,  class _A = std::allocator<_E> >
01646 class XMLStackProcessingInstruction : public XMLStackNode<_E, _Tr, _A>
01647 {
01648 public:
01649   typedef XMLStackProcessingInstruction<_E, _Tr, _A>
01650     _XMLStackProcessingInstruction;
01651   
01660   XMLStackProcessingInstruction(_XMLStackDocument *     Doc,
01661                                 const _XMLStackString & Target)
01662    : _XMLStackNode(Doc, Target)
01663   {
01664 #ifdef _DEBUG
01665     if (Target.size() == 0)
01666     {
01667       throw XMLStackException("ERROR: Processing Instruction nodes must"
01668         " have a defined name.");
01669     }
01670 #endif 
01671   }
01672 
01674   virtual ~XMLStackProcessingInstruction() {}
01675 
01677   virtual void setValue(const _XMLStackString & Value) { m_Value = Value; }
01678   virtual void setValue(unsigned long Value) { setValue(convertValue(Value)); }
01679   virtual void setValue(long Value) { setValue(convertValue(Value)); }
01680   virtual void setValue(unsigned int Value) { setValue(convertValue(Value)); }
01681   virtual void setValue(int Value) { setValue(convertValue(Value)); }
01682   virtual void setValue(unsigned short Value) { setValue(convertValue(Value)); }
01683   virtual void setValue(short Value) { setValue(convertValue(Value)); }
01684   virtual void setValue(signed char Value) { setValue(convertValue(Value)); }
01685   virtual void setValue(char Value) { setValue(convertValue(Value)); }
01686   virtual void setValue(unsigned char Value) { setValue(convertValue(Value)); }
01687   virtual void setValue(double Value, int Scale = 6)
01688   { 
01689     setValue(convertValue(Value, Scale)); 
01690   }
01691   virtual void setValue(float Value, int Scale = 6)
01692   { 
01693     setValue(convertValue(Value, Scale)); 
01694   }
01695   
01697   _XMLStackProcessingInstruction & operator=(const _XMLStackString & Value)
01698   {
01699     setValue(Value);
01700     return *this;
01701   }
01702 
01704   _XMLStackProcessingInstruction & operator=(unsigned long & Value)
01705   {
01706     setValue(Value);
01707     return *this;
01708   }
01709 
01711   _XMLStackProcessingInstruction & operator=(long Value)
01712   {
01713     setValue(Value);
01714     return *this;
01715   }
01716 
01718   _XMLStackProcessingInstruction & operator=(unsigned int Value)
01719   {
01720     setValue(Value);
01721     return *this;
01722   }
01723 
01725   _XMLStackProcessingInstruction & operator=(int Value)
01726   {
01727     setValue(Value);
01728     return *this;
01729   }
01730 
01732   _XMLStackProcessingInstruction & operator=(unsigned short Value)
01733   {
01734     setValue(Value);
01735     return *this;
01736   }
01737 
01739   _XMLStackProcessingInstruction & operator=(short Value)
01740   {
01741     setValue(Value);
01742     return *this;
01743   }
01744 
01746   _XMLStackProcessingInstruction & operator=(signed char Value)
01747   {
01748     setValue(Value);
01749     return *this;
01750   }
01751 
01753   _XMLStackProcessingInstruction & operator=(char Value)
01754   {
01755     setValue(Value);
01756     return *this;
01757   }
01758 
01760   _XMLStackProcessingInstruction & operator=(unsigned char Value)
01761   {
01762     setValue(Value);
01763     return *this;
01764   }
01765 
01767   _XMLStackProcessingInstruction & operator=(double Value)
01768   {
01769     setValue(Value);
01770     return *this;
01771   }
01772 
01774   _XMLStackProcessingInstruction & operator=(float Value)
01775   {
01776     setValue(Value);
01777     return *this;
01778   }
01779 
01780 protected:
01781   _XMLStackString m_Value;
01782 
01783   virtual void popped(void)
01784   {
01785     _XMLStackString Value(m_Doc->VALS.PI_START);
01786     Value += m_Name + m_Doc->VALS.SPACE + m_Value + m_Doc->VALS.PI_END;
01787     appendXML(Value);
01788   }
01789 
01790   virtual _XMLStackNode * clone(void) const
01791   { 
01792     return new _XMLStackProcessingInstruction(*this); 
01793   }
01794 };
01795 
01796 
01809 template<class _E, class _Tr = std::char_traits<_E>,  class _A = std::allocator<_E> >
01810 class XMLStackRawXML : public XMLStackNode<_E, _Tr, _A>
01811 {
01812 public:
01813   typedef XMLStackRawXML<_E, _Tr, _A> _XMLStackRawXML;
01814 
01822   XMLStackRawXML(_XMLStackDocument *     Doc,
01823                  const _XMLStackString & PushXML,
01824                  const _XMLStackString & PopXML)
01825    : _XMLStackNode(Doc, _XMLStackString()), m_PopXML(PopXML)
01826   {
01827     appendXML(PushXML);
01828   }
01829 
01831   virtual ~XMLStackRawXML() {}
01832 
01833 protected:
01834   _XMLStackString m_PopXML;
01835 
01836   virtual bool childNodePushed(void)
01837   {
01838     return true;
01839   }
01840 
01841   virtual void popped(void)
01842   {
01843     appendXML(m_PopXML);
01844   }
01845 
01846   virtual _XMLStackNode * clone(void) const
01847   { 
01848     return new _XMLStackRawXML(*this); 
01849   }
01850 };
01851 
01852 
01854 template<class _E, class _Tr = std::char_traits<_E>,  class _A = std::allocator<_E> >
01855 struct XMLStringConstants
01856 {
01857   typedef std::basic_string<_E, _Tr, _A> _XMLStackString;
01858 
01859   XMLStringConstants()
01860     : LT(_CE(L"<")),
01861       GT(_CE(L">")),
01862       SPACE(_CE(L" ")),
01863       XMLNS(_CE(L"xmlns")),
01864       S_XMLNS_C(_CE(L" xmlns:")),
01865       COLON(_CE(L":")),
01866       EQUAL(_CE(L"=")),
01867       QUOTE(_CE(L"\"")),
01868       AMP_REF(_CE(L"&amp;")),
01869       QUOTE_REF(_CE(L"&quot;")),
01870       LT_REF(_CE(L"&lt;")),
01871       SLASH(_CE(L"/")),
01872       CDATA_START(_CE(L"<![CDATA[")),
01873       CDATA_END(_CE(L"]]>")),
01874       COMMENT_START(_CE(L"<!--")),
01875       COMMENT_END(_CE(L"-->")),
01876       DASH2(_CE(L"--")),
01877       PI_START(_CE(L"<?")),
01878       PI_END(_CE(L"?>"))
01879   {
01880   }
01881 
01882   // These string declarations minimize the impact of constantly
01883   // converting to the correct string type
01884   const _XMLStackString LT;
01885   const _XMLStackString GT;
01886   const _XMLStackString SPACE;
01887   const _XMLStackString XMLNS;
01888   const _XMLStackString S_XMLNS_C;
01889   const _XMLStackString COLON;
01890   const _XMLStackString EQUAL;
01891   const _XMLStackString QUOTE;
01892   const _XMLStackString AMP_REF;
01893   const _XMLStackString QUOTE_REF;
01894   const _XMLStackString LT_REF;
01895   const _XMLStackString SLASH;
01896   const _XMLStackString CDATA_START;
01897   const _XMLStackString CDATA_END;
01898   const _XMLStackString COMMENT_START;
01899   const _XMLStackString COMMENT_END;
01900   const _XMLStackString DASH2;
01901   const _XMLStackString PI_START;
01902   const _XMLStackString PI_END;
01903 };
01904  
01999 template<class _E, class _Tr = std::char_traits<_E>,  class _A = std::allocator<_E> >
02000 class XMLStackDocument
02001 {
02002 public:
02003   typedef std::basic_string<_E, _Tr, _A> _XMLStackString;
02004   typedef XMLStackDocument<_E, _Tr, _A> _XMLStackDocument;
02005   typedef XMLStackNode<_E, _Tr, _A> _XMLStackNode;
02006   typedef XMLStackElement<_E, _Tr, _A> _XMLStackElement;
02007   typedef XMLStackText<_E, _Tr, _A> _XMLStackText;
02008   typedef XMLStackCDATASection<_E, _Tr, _A> _XMLStackCDATASection;
02009   typedef XMLStackComment<_E, _Tr, _A> _XMLStackComment;
02010   typedef XMLStackProcessingInstruction<_E, _Tr, _A> _XMLStackProcessingInstruction;
02011   typedef XMLStackRawXML<_E, _Tr, _A> _XMLStackRawXML;
02012   
02019   XMLStackDocument(unsigned long InitialBufferSize = 1024)
02020   {
02021     // Start us off with a decent size string to keep initial memory allocations
02022     // to a minimum.
02023     m_XML.reserve(InitialBufferSize);
02024   }
02025 
02027   XMLStackDocument(const _XMLStackDocument & Instance)
02028   {
02029     *this = Instance;
02030   }
02031 
02033   ~XMLStackDocument()
02034   {
02035     freeStack();
02036   }
02037 
02045   void pop(void)
02046   {
02047     if (m_Stack.size() == 0)
02048     {
02049       throw XMLStackException("ERROR: Pop() - XMLStackDocument is empty.");
02050     }
02051     m_Stack.back()->popped();
02052     delete m_Stack.back();
02053     m_Stack.pop_back();
02054   }
02055 
02060   void popAll(void)
02061   {
02062     while (m_Stack.size() > 0)
02063     {
02064       pop();
02065     }
02066   }
02067   
02083   _XMLStackElement & pushElement(const _XMLStackString & Name)
02084   {
02085     if (m_Stack.size() > 0)
02086     {
02087       if (!m_Stack.back()->childNodePushed())
02088       {
02089         throw XMLStackException("ERROR: Cannot create a child XMLStackElement"
02090           " node of the given parent node.");
02091       }
02092     }
02093     _XMLStackElement * Element = new _XMLStackElement(this, Name);
02094 
02095     m_Stack.push_back(Element);
02096     return *Element;
02097   }
02098   
02127   _XMLStackElement & pushElement(const _XMLStackString & Name,
02128                                  const _XMLStackString & NamespaceURI)
02129   {
02130     if (m_Stack.size() > 0)
02131     {
02132       if (!m_Stack.back()->childNodePushed())
02133       {
02134         throw XMLStackException("ERROR: Cannot create a child XMLStackElement"
02135           " node of the given parent node.");
02136       }
02137     }
02138     _XMLStackElement * Element = new _XMLStackElement(this, Name, NamespaceURI);
02139 
02140     m_Stack.push_back(Element);
02141     return *Element;
02142   }
02143   
02158   _XMLStackText & pushText(const _XMLStackString & Data)
02159   {
02160     if (m_Stack.size() > 0)
02161     {
02162       if (!m_Stack.back()->childNodePushed())
02163       {
02164         throw XMLStackException("ERROR: Cannot create a child XMLStackText"
02165           " node of the given parent node.");
02166       }
02167     }
02168     _XMLStackText * Text = new _XMLStackText(this, Data);
02169 
02170     m_Stack.push_back(Text);
02171     return *Text;
02172   }
02173   
02193   _XMLStackCDATASection & pushCDATASection(const _XMLStackString & Data)
02194   {
02195     if (m_Stack.size() > 0)
02196     {
02197       if (!m_Stack.back()->childNodePushed())
02198       {
02199         throw XMLStackException("ERROR: Cannot create a child XMLStackCDATASection"
02200           " node of the given parent node.");
02201       }
02202     }
02203     _XMLStackCDATASection * Text = new _XMLStackCDATASection(this, Data);
02204 
02205     m_Stack.push_back(Text);
02206     return *Text;
02207   }
02208   
02222   _XMLStackComment & pushComment(const _XMLStackString & Data)
02223   {
02224     if (m_Stack.size() > 0)
02225     {
02226       if (!m_Stack.back()->childNodePushed())
02227       {
02228         throw XMLStackException("ERROR: Cannot create a child XMLStackComment"
02229           " node of the given parent node.");
02230       }
02231     }
02232     _XMLStackComment * Comment = new _XMLStackComment(this, Data);
02233 
02234     m_Stack.push_back(Comment);
02235     return *Comment;
02236   }
02237   
02252   _XMLStackProcessingInstruction & pushProcessingInstruction
02253     (const _XMLStackString & Target)
02254   {
02255     if (m_Stack.size() > 0)
02256     {
02257       if (!m_Stack.back()->childNodePushed())
02258       {
02259         throw XMLStackException("ERROR: Cannot create a child XMLStackProcessingInstruction"
02260           " node of the given parent node.");
02261       }
02262     }
02263     _XMLStackProcessingInstruction * PI =
02264       new _XMLStackProcessingInstruction(this, Target);
02265 
02266     m_Stack.push_back(PI);
02267     return *PI;
02268   }
02269   
02287   _XMLStackRawXML & pushRawXML(const _XMLStackString & PushXML,
02288                                const _XMLStackString & PopXML)
02289   {
02290     if (m_Stack.size() > 0)
02291     {
02292       if (!m_Stack.back()->childNodePushed())
02293       {
02294         throw XMLStackException("ERROR: Cannot create a child XMLStackRawXML"
02295           " node of the given parent node.");
02296       }
02297     }
02298     _XMLStackRawXML * Node = new _XMLStackRawXML(this, PushXML, PopXML);
02299 
02300     m_Stack.push_back(Node);
02301     return *Node;
02302   }
02303 
02308   _XMLStackNode & top(void)
02309   {
02310     if (stackSize() > 0)
02311     {
02312       return *m_Stack.back();
02313     }
02314     throw XMLStackException("ERROR: top() called on empty stack.");
02315   }
02316 
02321   const _XMLStackNode & top(void) const
02322   {
02323     if (stackSize() > 0)
02324     {
02325       return *m_Stack.back();
02326     }
02327     throw XMLStackException("ERROR: top() called on empty stack.");
02328   }
02329 
02335   const _XMLStackString & xml(void) const { return m_XML; }
02336 
02343   void clear(void)
02344   {
02345     freeStack();
02346     m_XML.erase();
02347   }
02348 
02350   unsigned long stackSize(void) const { return m_Stack.size(); }
02351 
02362   void reserveXMLBufferSize(unsigned long Capacity)
02363   {
02364     if (m_XML.capacity() < Capacity)
02365     {
02366       m_XML.reserve(Capacity);
02367     }
02368   }
02369 
02371   _XMLStackDocument & operator=(const _XMLStackDocument & Instance)
02372   {
02373     m_XML = Instance.m_XML;
02374     freeStack();
02375 
02376     for (int i = 0; i < Instance.m_Stack.size(); ++i)
02377     {
02378       m_Stack.push_back(Instance.m_Stack[i]->clone());
02379       m_Stack.back()->m_Doc = this;
02380     }
02381     return *this;
02382   }
02383 
02384 private:
02385   typedef std::vector<_XMLStackNode *> NodeStack;
02386 
02387   _XMLStackString                    m_XML;
02388   NodeStack                          m_Stack;
02389   const XMLStringConstants<_E, _Tr, _A> VALS;
02390 
02391   void appendXML(const _XMLStackString & XML)
02392   {
02393     if (XML.size() + m_XML.size() > m_XML.capacity())
02394     {
02395       // Microsoft's STL basic_string has a fixed sized increments implementation
02396       // of memory management.  This gets around that problem and provides
02397       // an enormous performance boost.
02398       m_XML.reserve(m_XML.capacity() * 2 + XML.size());
02399     }
02400     m_XML += XML;
02401   }
02402 
02403   void freeStack(void)
02404   {
02405     for (int i = 0; i < m_Stack.size(); ++i)
02406     {
02407       delete m_Stack[i];
02408     }
02409     m_Stack.clear();
02410   }
02411 
02412   friend class XMLStackNode<_E, _Tr, _A>;
02413   friend class XMLStackElement<_E, _Tr, _A>;
02414   friend class XMLStackAttribute<_E, _Tr, _A>;
02415   friend class XMLStackProcessingInstruction<_E, _Tr, _A>;
02416   friend class XMLStackText<_E, _Tr, _A>;
02417   friend class XMLStackCDATASection<_E, _Tr, _A>;
02418   friend class XMLStackRawXML<_E, _Tr, _A>;
02419   friend class XMLStackComment<_E, _Tr, _A>;
02420 };
02421 
02422 
02424 template<>
02425 struct XMLStringConstants<char, std::char_traits<char>, std::allocator<char> >
02426 {
02427   typedef std::basic_string<char, std::char_traits<char>, std::allocator<char> > _XMLStackString;
02428 
02429   XMLStringConstants()
02430     : LT("<"),
02431       GT(">"),
02432       SPACE(" "),
02433       XMLNS("xmlns"),
02434       S_XMLNS_C(" xmlns:"),
02435       COLON(":"),
02436       EQUAL("="),
02437       QUOTE("\""),
02438       AMP_REF("&amp;"),
02439       QUOTE_REF("&quot;"),
02440       LT_REF("&lt;"),
02441       SLASH("/"),
02442       CDATA_START("<![CDATA["),
02443       CDATA_END("]]>"),
02444       COMMENT_START("<!--"),
02445       COMMENT_END("-->"),
02446       DASH2("--"),
02447       PI_START("<?"),
02448       PI_END("?>")
02449   {
02450   }
02451 
02452   // These string declarations minimize the impact of constantly
02453   // converting to the correct string type
02454   const _XMLStackString LT;
02455   const _XMLStackString GT;
02456   const _XMLStackString SPACE;
02457   const _XMLStackString XMLNS;
02458   const _XMLStackString S_XMLNS_C;
02459   const _XMLStackString COLON;
02460   const _XMLStackString EQUAL;
02461   const _XMLStackString QUOTE;
02462   const _XMLStackString AMP_REF;
02463   const _XMLStackString QUOTE_REF;
02464   const _XMLStackString LT_REF;
02465   const _XMLStackString SLASH;
02466   const _XMLStackString CDATA_START;
02467   const _XMLStackString CDATA_END;
02468   const _XMLStackString COMMENT_START;
02469   const _XMLStackString COMMENT_END;
02470   const _XMLStackString DASH2;
02471   const _XMLStackString PI_START;
02472   const _XMLStackString PI_END;
02473 };
02474 
02475 
02477 template<>
02478 struct XMLStringConstants<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >
02479 {
02480   typedef std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > _XMLStackString;
02481 
02482   XMLStringConstants()
02483     : LT(L"<"),
02484       GT(L">"),
02485       SPACE(L" "),
02486       XMLNS(L"xmlns"),
02487       S_XMLNS_C(L" xmlns:"),
02488       COLON(L":"),
02489       EQUAL(L"="),
02490       QUOTE(L"\""),
02491       AMP_REF(L"&amp;"),
02492       QUOTE_REF(L"&quot;"),
02493       LT_REF(L"&lt;"),
02494       SLASH(L"/"),
02495       CDATA_START(L"<![CDATA["),
02496       CDATA_END(L"]]>"),
02497       COMMENT_START(L"<!--"),
02498       COMMENT_END(L"-->"),
02499       DASH2(L"--"),
02500       PI_START(L"<?"),
02501       PI_END(L"?>")
02502   {
02503   }
02504 
02505   // These string declarations minimize the impact of constantly
02506   // converting to the correct string type
02507   const _XMLStackString LT;
02508   const _XMLStackString GT;
02509   const _XMLStackString SPACE;
02510   const _XMLStackString XMLNS;
02511   const _XMLStackString S_XMLNS_C;
02512   const _XMLStackString COLON;
02513   const _XMLStackString EQUAL;
02514   const _XMLStackString QUOTE;
02515   const _XMLStackString AMP_REF;
02516   const _XMLStackString QUOTE_REF;
02517   const _XMLStackString LT_REF;
02518   const _XMLStackString SLASH;
02519   const _XMLStackString CDATA_START;
02520   const _XMLStackString CDATA_END;
02521   const _XMLStackString COMMENT_START;
02522   const _XMLStackString COMMENT_END;
02523   const _XMLStackString DASH2;
02524   const _XMLStackString PI_START;
02525   const _XMLStackString PI_END;
02526 };
02527 
02528 
02529 typedef XMLStackDocument<wchar_t, std::char_traits<wchar_t>,
02530   std::allocator<wchar_t> > WXMLStackDocument;
02531 typedef XMLStackDocument<char, std::char_traits<char>,
02532   std::allocator<char> > AXMLStackDocument;
02533 
02534 #endif // _XMLSTACK_H

Generated at Mon Aug 6 11:54:20 2001 for XMLStack by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001