#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