| #ifndef XML_H | 
 | #define XML_H | 
 |  | 
 | #include "SourcePos.h" | 
 |  | 
 | #include <algorithm> | 
 | #include <string> | 
 | #include <vector> | 
 | #include <map> | 
 |  | 
 | #define XMLNS_XMLNS "http://www.w3.org/XML/1998/namespace" | 
 |  | 
 | using namespace std; | 
 |  | 
 | string trim_string(const string& str); | 
 |  | 
 | struct XMLAttribute | 
 | { | 
 |     string ns; | 
 |     string name; | 
 |     string value; | 
 |  | 
 |     XMLAttribute(); | 
 |     XMLAttribute(const XMLAttribute& that); | 
 |     XMLAttribute(string ns, string name, string value); | 
 |     ~XMLAttribute(); | 
 |  | 
 |     int Compare(const XMLAttribute& that) const; | 
 |  | 
 |     inline bool operator<(const XMLAttribute& that) const { return Compare(that) < 0; } | 
 |     inline bool operator<=(const XMLAttribute& that) const { return Compare(that) <= 0; } | 
 |     inline bool operator==(const XMLAttribute& that) const { return Compare(that) == 0; } | 
 |     inline bool operator!=(const XMLAttribute& that) const { return Compare(that) != 0; } | 
 |     inline bool operator>=(const XMLAttribute& that) const { return Compare(that) >= 0; } | 
 |     inline bool operator>(const XMLAttribute& that) const { return Compare(that) > 0; } | 
 |  | 
 |     static string Find(const vector<XMLAttribute>& list, | 
 |                                 const string& ns, const string& name, const string& def); | 
 | }; | 
 |  | 
 | class XMLNamespaceMap | 
 | { | 
 | public: | 
 |     XMLNamespaceMap(); | 
 |     XMLNamespaceMap(char const*const* nspaces); | 
 |     string Get(const string& ns) const; | 
 |     string GetPrefix(const string& ns) const; | 
 |     void AddToAttributes(vector<XMLAttribute>* attrs) const; | 
 | private: | 
 |     map<string,string> m_map; | 
 | }; | 
 |  | 
 | struct XMLNode | 
 | { | 
 | public: | 
 |     enum { | 
 |         EXACT = 0, | 
 |         PRETTY = 1 | 
 |     }; | 
 |  | 
 |     enum { | 
 |         ELEMENT = 0, | 
 |         TEXT = 1 | 
 |     }; | 
 |  | 
 |     static XMLNode* NewElement(const SourcePos& pos, const string& ns, const string& name, | 
 |                         const vector<XMLAttribute>& attrs, int pretty); | 
 |     static XMLNode* NewText(const SourcePos& pos, const string& text, int pretty); | 
 |  | 
 |     ~XMLNode(); | 
 |  | 
 |     // a deep copy | 
 |     XMLNode* Clone() const; | 
 |  | 
 |     inline int Type() const                                     { return m_type; } | 
 |     inline int Pretty() const                                   { return m_pretty; } | 
 |     void SetPrettyRecursive(int value); | 
 |     string ContentsToString(const XMLNamespaceMap& nspaces) const; | 
 |     string ToString(const XMLNamespaceMap& nspaces) const; | 
 |     string OpenTagToString(const XMLNamespaceMap& nspaces, int pretty) const; | 
 |  | 
 |     string CollapseTextContents() const; | 
 |  | 
 |     inline const SourcePos& Position() const                    { return m_pos; } | 
 |  | 
 |     // element | 
 |     inline string Namespace() const                             { return m_ns; } | 
 |     inline string Name() const                                  { return m_name; } | 
 |     inline void SetName(const string& ns, const string& n)      { m_ns = ns; m_name = n; } | 
 |     inline const vector<XMLAttribute>& Attributes() const       { return m_attrs; } | 
 |     inline vector<XMLAttribute>& EditAttributes()               { return m_attrs; } | 
 |     inline const vector<XMLNode*>& Children() const             { return m_children; } | 
 |     inline vector<XMLNode*>& EditChildren()                     { return m_children; } | 
 |     vector<XMLNode*> GetElementsByName(const string& ns, const string& name) const; | 
 |     XMLNode* GetElementByNameAt(const string& ns, const string& name, size_t index) const; | 
 |     size_t CountElementsByName(const string& ns, const string& name) const; | 
 |     string GetAttribute(const string& ns, const string& name, const string& def) const; | 
 |  | 
 |     // text | 
 |     inline string Text() const                                  { return m_text; } | 
 |  | 
 | private: | 
 |     XMLNode(); | 
 |     XMLNode(const XMLNode&); | 
 |  | 
 |     string contents_to_string(const XMLNamespaceMap& nspaces, const string& indent) const; | 
 |     string to_string(const XMLNamespaceMap& nspaces, const string& indent) const; | 
 |     string open_tag_to_string(const XMLNamespaceMap& nspaces, const string& indent, | 
 |             int pretty) const; | 
 |  | 
 |     int m_type; | 
 |     int m_pretty; | 
 |     SourcePos m_pos; | 
 |  | 
 |     // element | 
 |     string m_ns; | 
 |     string m_name; | 
 |     vector<XMLAttribute> m_attrs; | 
 |     vector<XMLNode*> m_children; | 
 |  | 
 |     // text | 
 |     string m_text; | 
 | }; | 
 |  | 
 | class XMLHandler | 
 | { | 
 | public: | 
 |     // information about the element that started us | 
 |     SourcePos elementPos; | 
 |     string elementNamespace; | 
 |     string elementName; | 
 |     vector<XMLAttribute> elementAttributes; | 
 |  | 
 |     XMLHandler(); | 
 |     virtual ~XMLHandler(); | 
 |  | 
 |     XMLHandler* parent; | 
 |  | 
 |     virtual int OnStartElement(const SourcePos& pos, const string& ns, const string& name, | 
 |                                 const vector<XMLAttribute>& attrs, XMLHandler** next); | 
 |     virtual int OnEndElement(const SourcePos& pos, const string& ns, const string& name); | 
 |     virtual int OnText(const SourcePos& pos, const string& text); | 
 |     virtual int OnComment(const SourcePos& pos, const string& text); | 
 |     virtual int OnDone(const SourcePos& pos); | 
 |  | 
 |     static bool ParseFile(const string& filename, XMLHandler* handler); | 
 |     static bool ParseString(const string& filename, const string& text, XMLHandler* handler); | 
 | }; | 
 |  | 
 | class TopElementHandler : public XMLHandler | 
 | { | 
 | public: | 
 |     TopElementHandler(const string& ns, const string& name, XMLHandler* next); | 
 |  | 
 |     virtual int OnStartElement(const SourcePos& pos, const string& ns, const string& name, | 
 |                                 const vector<XMLAttribute>& attrs, XMLHandler** next); | 
 |     virtual int OnEndElement(const SourcePos& pos, const string& ns, const string& name); | 
 |     virtual int OnText(const SourcePos& pos, const string& text); | 
 |     virtual int OnDone(const SourcePos& endPos); | 
 |  | 
 | private: | 
 |     string m_ns; | 
 |     string m_name; | 
 |     XMLHandler* m_next; | 
 | }; | 
 |  | 
 | class NodeHandler : public XMLHandler | 
 | { | 
 | public: | 
 |     // after it's done, you own everything created and added to root | 
 |     NodeHandler(XMLNode* root, int pretty); | 
 |     ~NodeHandler(); | 
 |  | 
 |     virtual int OnStartElement(const SourcePos& pos, const string& ns, const string& name, | 
 |                                 const vector<XMLAttribute>& attrs, XMLHandler** next); | 
 |     virtual int OnEndElement(const SourcePos& pos, const string& ns, const string& name); | 
 |     virtual int OnText(const SourcePos& pos, const string& text); | 
 |     virtual int OnComment(const SourcePos& pos, const string& text); | 
 |     virtual int OnDone(const SourcePos& endPos); | 
 |  | 
 |     inline XMLNode* Root() const                { return m_root; } | 
 |  | 
 |     static XMLNode* ParseFile(const string& filename, int pretty); | 
 |     static XMLNode* ParseString(const string& filename, const string& text, int pretty); | 
 |  | 
 | private: | 
 |     XMLNode* m_root; | 
 |     int m_pretty; | 
 |     vector<XMLNode*> m_nodes; | 
 | }; | 
 |  | 
 | template <class T> | 
 | static void delete_object(T* obj) | 
 | { | 
 |     delete obj; | 
 | } | 
 |  | 
 | #endif // XML_H |