MyGUI  3.2.1
MyGUI_XmlDocument.h
Go to the documentation of this file.
00001 /*
00002  * This source file is part of MyGUI. For the latest info, see http://mygui.info/
00003  * Distributed under the MIT License
00004  * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT)
00005  */
00006 
00007 #ifndef __MYGUI_XML_DOCUMENT_H__
00008 #define __MYGUI_XML_DOCUMENT_H__
00009 
00010 #include "MyGUI_Prerequest.h"
00011 #include "MyGUI_UString.h"
00012 #include "MyGUI_Diagnostic.h"
00013 #include "MyGUI_DataStream.h"
00014 
00015 #include <vector>
00016 #include <string>
00017 #include <iostream>
00018 #include <fstream>
00019 #include <sstream>
00020 #include <assert.h>
00021 
00022 namespace MyGUI
00023 {
00024     namespace xml
00025     {
00026 
00027         struct ElementType
00028         {
00029             enum Enum
00030             {
00031                 Comment,
00032                 Declaration,
00033                 Normal,
00034                 MAX
00035             };
00036 
00037             ElementType(Enum _value = MAX) : mValue(_value) { }
00038             friend bool operator == (ElementType const& a, ElementType const& b)
00039             {
00040                 return a.mValue == b.mValue;
00041             }
00042             friend bool operator != (ElementType const& a, ElementType const& b)
00043             {
00044                 return a.mValue != b.mValue;
00045             }
00046 
00047             int getValue() const
00048             {
00049                 return mValue;
00050             }
00051 
00052         private:
00053             Enum mValue;
00054         };
00055 
00056         struct ErrorType
00057         {
00058             enum Enum
00059             {
00060                 OpenFileFail,
00061                 CreateFileFail,
00062                 IncorrectContent,
00063                 NotClosedElements,
00064                 NoXMLDeclaration,
00065                 CloseNotOpenedElement,
00066                 InconsistentOpenCloseElements,
00067                 MoreThanOneXMLDeclaration,
00068                 MoreThanOneRootElement,
00069                 IncorrectAttribute,
00070                 MAX
00071             };
00072 
00073             ErrorType(Enum _value = MAX) : mValue(_value) { }
00074 
00075             std::string print() const
00076             {
00077                 return getValueName(mValue);
00078             }
00079 
00080         private:
00081             const char* getValueName(int _index) const
00082             {
00083                 static const char* values[MAX + 1] =
00084                 {
00085                     "Failed to open XML file",
00086                     "Failed to ceate XML file",
00087                     "XML file contain incorrect content",
00088                     "XML file contain not closed elements",
00089                     "XML file without declaration",
00090                     "XML file contain closed but not opened element",
00091                     "XML file contain inconsistent elements",
00092                     "XML file contain more than one declaration",
00093                     "XML file contain more than one root element",
00094                     "XML file contain incorrect attribute",
00095                     ""
00096                 };
00097                 return values[(_index < MAX && _index >= 0) ? _index : MAX];
00098             }
00099         private:
00100             Enum mValue;
00101         };
00102 
00103         class Element;
00104         class Document;
00105 
00106         typedef Element* ElementPtr;
00107         typedef std::pair<std::string, std::string> PairAttribute;
00108         typedef std::vector<PairAttribute> VectorAttributes;
00109         typedef std::vector<ElementPtr> VectorElement;
00110 
00111         //----------------------------------------------------------------------//
00112         // class ElementEnumerator
00113         //----------------------------------------------------------------------//
00114         class MYGUI_EXPORT ElementEnumerator
00115         {
00116             friend class Element;
00117 
00118         private:
00119             ElementEnumerator(VectorElement::iterator _begin, VectorElement::iterator _end);
00120 
00121         public:
00122             bool next();
00123             bool next(const std::string& _name);
00124 
00125             ElementPtr operator->() const;
00126             ElementPtr current();
00127 
00128             /*obsolete:*/
00129 #ifndef MYGUI_DONT_USE_OBSOLETE
00130 
00131             MYGUI_OBSOLETE("use : bool ElementEnumerator::next()")
00132             bool nextNode()
00133             {
00134                 return next();
00135             }
00136             MYGUI_OBSOLETE("use : bool ElementEnumerator::next(const std::string& _name)")
00137             bool nextNode(const std::string& _name)
00138             {
00139                 return next(_name);
00140             }
00141             MYGUI_OBSOLETE("use : ElementPtr ElementEnumerator::current()")
00142             ElementPtr currentNode()
00143             {
00144                 return current();
00145             }
00146 
00147 #endif // MYGUI_DONT_USE_OBSOLETE
00148 
00149         private:
00150             bool m_first;
00151             VectorElement::iterator m_current, m_end;
00152         };
00153 
00154 
00155         //----------------------------------------------------------------------//
00156         // class Element
00157         //----------------------------------------------------------------------//
00158         class MYGUI_EXPORT Element
00159         {
00160             friend class Document;
00161 
00162         public:
00163             ~Element();
00164 
00165         private:
00166             Element(const std::string& _name, ElementPtr _parent, ElementType _type = ElementType::Normal, const std::string& _content = "");
00167             void save(std::ostream& _stream, size_t _level);
00168 
00169         public:
00170             ElementPtr createChild(const std::string& _name, const std::string& _content = "", ElementType _type = ElementType::Normal);
00171             void removeChild(ElementPtr _child);
00172 
00173             template <typename T>
00174             void addAttribute(const std::string& _key, const T& _value)
00175             {
00176                 addAttribute(_key, utility::toString(_value));
00177             }
00178 
00179             void addAttribute(const std::string& _key, const std::string& _value);
00180 
00181             void removeAttribute(const std::string& _key);
00182 
00183             void setAttribute(const std::string& _key, const std::string& _value);
00184 
00185             template <typename T>
00186             void addContent(const T& _content)
00187             {
00188                 addContent(utility::toString(_content));
00189             }
00190 
00191             void addContent(const std::string& _content);
00192 
00193             template <typename T>
00194             void setContent(const T& _content)
00195             {
00196                 setContent(utility::toString(_content));
00197             }
00198 
00199             void setContent(const std::string& _content);
00200 
00201             void clear();
00202 
00203             bool findAttribute(const std::string& _name, std::string& _value);
00204             std::string findAttribute(const std::string& _name);
00205 
00206             const std::string& getName() const;
00207 
00208             const std::string& getContent() const;
00209 
00210             const VectorAttributes& getAttributes() const;
00211 
00212             ElementPtr getParent() const;
00213 
00214             ElementEnumerator getElementEnumerator();
00215 
00216             ElementType getType() const;
00217 
00218             ElementPtr createCopy();
00219 
00220             /*obsolete:*/
00221 #ifndef MYGUI_DONT_USE_OBSOLETE
00222 
00223             template <typename T>
00224             MYGUI_OBSOLETE("use : template <typename T> void Element::addAttribute(const std::string &_key, const T& _value)")
00225             void addAttributes(const std::string& _key, const T& _value)
00226             {
00227                 addAttribute<T>(_key, _value);
00228             }
00229             MYGUI_OBSOLETE("use : void Element::addAttribute(const std::string& _key, const std::string& _value)")
00230             void addAttributes(const std::string& _key, const std::string& _value)
00231             {
00232                 addAttribute(_key, _value);
00233             }
00234 
00235             template <typename T>
00236             MYGUI_OBSOLETE("use : template <typename T> void Element::addContent(const T& _content)")
00237             void addBody(const T& _content)
00238             {
00239                 addContent<T>(_content);
00240             }
00241             MYGUI_OBSOLETE("use : void Element::addContent(const std::string& _content)")
00242             void addBody(const std::string& _content)
00243             {
00244                 addContent(_content);
00245             }
00246             template <typename T>
00247             MYGUI_OBSOLETE("use : template <typename T> void Element::setContent(const T& _content)")
00248             void setBody(const T& _content)
00249             {
00250                 setContent<T>(_content);
00251             }
00252             MYGUI_OBSOLETE("use : void Element::setContent(const std::string& _content)")
00253             void setBody(const std::string& _content)
00254             {
00255                 setContent(_content);
00256             }
00257 
00258             MYGUI_OBSOLETE("use : const std::string& Element::getContent()")
00259             const std::string& getBody() const
00260             {
00261                 return getContent();
00262             }
00263             MYGUI_OBSOLETE("use : ElementEnumerator Element::getElementEnumerator()")
00264             ElementEnumerator getNodeIterator()
00265             {
00266                 return getElementEnumerator();
00267             }
00268 
00269 #endif // MYGUI_DONT_USE_OBSOLETE
00270 
00271         private:
00272             std::string mName;
00273             std::string mContent;
00274             VectorAttributes mAttributes;
00275             VectorElement mChilds;
00276             ElementPtr mParent;
00277             ElementType mType;
00278         };
00279 
00280         //----------------------------------------------------------------------//
00281         // class Document
00282         //----------------------------------------------------------------------//
00283         class MYGUI_EXPORT Document
00284         {
00285         public:
00286             Document();
00287             ~Document();
00288 
00289             // открывает обычным файлом, имя файла в utf8
00290             bool open(const std::string& _filename);
00291 
00292             // открывает обычным файлом, имя файла в utf16 или utf32
00293             bool open(const std::wstring& _filename);
00294 
00295             // открывает обычным потоком
00296             bool open(std::istream& _stream);
00297 
00298             bool open(const UString& _filename);
00299 
00300             bool open(IDataStream* _data);
00301 
00302             // сохраняет файл
00303             bool save(const std::string& _filename);
00304 
00305             // сохраняет файл
00306             bool save(const std::wstring& _filename);
00307 
00308             bool save(std::ostream& _stream);
00309 
00310             bool save(const UString& _filename);
00311 
00312             void clear();
00313 
00314             std::string getLastError();
00315 
00316             void clearLastError();
00317 
00318             ElementPtr createDeclaration(const std::string& _version = "1.0", const std::string& _encoding = "UTF-8");
00319             ElementPtr createRoot(const std::string& _name);
00320 
00321             ElementPtr getRoot() const;
00322 
00323             /*obsolete:*/
00324 #ifndef MYGUI_DONT_USE_OBSOLETE
00325 
00326             MYGUI_OBSOLETE("use : ElementPtr Document::createDeclaration(const std::string& _version, const std::string& _encoding)")
00327             ElementPtr createInfo(const std::string& _version = "1.0", const std::string& _encoding = "UTF-8")
00328             {
00329                 return createDeclaration(_version, _encoding);
00330             }
00331 
00332 #endif // MYGUI_DONT_USE_OBSOLETE
00333 
00334         private:
00335             void setLastFileError(const std::string& _filename);
00336             void setLastFileError(const std::wstring& _filename);
00337 
00338             bool parseTag(ElementPtr& _currentNode, std::string _content);
00339 
00340             bool checkPair(std::string& _key, std::string& _value);
00341 
00342             bool parseLine(std::string& _line, ElementPtr& _element);
00343 
00344             // ищет символ без учета ковычек
00345             size_t find(const std::string& _text, char _char, size_t _start = 0);
00346 
00347             void clearDeclaration();
00348             void clearRoot();
00349 
00350         private:
00351             ElementPtr mRoot;
00352             ElementPtr mDeclaration;
00353             ErrorType mLastError;
00354             std::string mLastErrorFile;
00355             size_t mLine;
00356             size_t mCol;
00357 
00358         }; // class Document
00359 
00360         MYGUI_OBSOLETE("use : class MyGUI::xml::ElementEnumerator")
00361         typedef ElementEnumerator xmlNodeIterator;
00362         MYGUI_OBSOLETE("use : class MyGUI::xml::ElementPtr")
00363         typedef ElementPtr xmlNodePtr;
00364         MYGUI_OBSOLETE("use : class MyGUI::xml::Document")
00365         typedef Document xmlDocument;
00366 
00367     } // namespace xml
00368 
00369 } // namespace MyGUI
00370 
00371 #endif // __MYGUI_XML_DOCUMENT_H__