Home | History | Annotate | Download | only in localize
      1 #ifndef XML_H
      2 #define XML_H
      3 
      4 #include "SourcePos.h"
      5 
      6 #include <algorithm>
      7 #include <string>
      8 #include <vector>
      9 #include <map>
     10 
     11 #define XMLNS_XMLNS "http://www.w3.org/XML/1998/namespace"
     12 
     13 using namespace std;
     14 
     15 string trim_string(const string& str);
     16 
     17 struct XMLAttribute
     18 {
     19     string ns;
     20     string name;
     21     string value;
     22 
     23     XMLAttribute();
     24     XMLAttribute(const XMLAttribute& that);
     25     XMLAttribute(string ns, string name, string value);
     26     ~XMLAttribute();
     27 
     28     int Compare(const XMLAttribute& that) const;
     29 
     30     inline bool operator<(const XMLAttribute& that) const { return Compare(that) < 0; }
     31     inline bool operator<=(const XMLAttribute& that) const { return Compare(that) <= 0; }
     32     inline bool operator==(const XMLAttribute& that) const { return Compare(that) == 0; }
     33     inline bool operator!=(const XMLAttribute& that) const { return Compare(that) != 0; }
     34     inline bool operator>=(const XMLAttribute& that) const { return Compare(that) >= 0; }
     35     inline bool operator>(const XMLAttribute& that) const { return Compare(that) > 0; }
     36 
     37     static string Find(const vector<XMLAttribute>& list,
     38                                 const string& ns, const string& name, const string& def);
     39 };
     40 
     41 class XMLNamespaceMap
     42 {
     43 public:
     44     XMLNamespaceMap();
     45     XMLNamespaceMap(char const*const* nspaces);
     46     string Get(const string& ns) const;
     47     string GetPrefix(const string& ns) const;
     48     void AddToAttributes(vector<XMLAttribute>* attrs) const;
     49 private:
     50     map<string,string> m_map;
     51 };
     52 
     53 struct XMLNode
     54 {
     55 public:
     56     enum {
     57         EXACT = 0,
     58         PRETTY = 1
     59     };
     60 
     61     enum {
     62         ELEMENT = 0,
     63         TEXT = 1
     64     };
     65 
     66     static XMLNode* NewElement(const SourcePos& pos, const string& ns, const string& name,
     67                         const vector<XMLAttribute>& attrs, int pretty);
     68     static XMLNode* NewText(const SourcePos& pos, const string& text, int pretty);
     69 
     70     ~XMLNode();
     71 
     72     // a deep copy
     73     XMLNode* Clone() const;
     74 
     75     inline int Type() const                                     { return m_type; }
     76     inline int Pretty() const                                   { return m_pretty; }
     77     void SetPrettyRecursive(int value);
     78     string ContentsToString(const XMLNamespaceMap& nspaces) const;
     79     string ToString(const XMLNamespaceMap& nspaces) const;
     80     string OpenTagToString(const XMLNamespaceMap& nspaces, int pretty) const;
     81 
     82     string CollapseTextContents() const;
     83 
     84     inline const SourcePos& Position() const                    { return m_pos; }
     85 
     86     // element
     87     inline string Namespace() const                             { return m_ns; }
     88     inline string Name() const                                  { return m_name; }
     89     inline void SetName(const string& ns, const string& n)      { m_ns = ns; m_name = n; }
     90     inline const vector<XMLAttribute>& Attributes() const       { return m_attrs; }
     91     inline vector<XMLAttribute>& EditAttributes()               { return m_attrs; }
     92     inline const vector<XMLNode*>& Children() const             { return m_children; }
     93     inline vector<XMLNode*>& EditChildren()                     { return m_children; }
     94     vector<XMLNode*> GetElementsByName(const string& ns, const string& name) const;
     95     XMLNode* GetElementByNameAt(const string& ns, const string& name, size_t index) const;
     96     size_t CountElementsByName(const string& ns, const string& name) const;
     97     string GetAttribute(const string& ns, const string& name, const string& def) const;
     98 
     99     // text
    100     inline string Text() const                                  { return m_text; }
    101 
    102 private:
    103     XMLNode();
    104     XMLNode(const XMLNode&);
    105 
    106     string contents_to_string(const XMLNamespaceMap& nspaces, const string& indent) const;
    107     string to_string(const XMLNamespaceMap& nspaces, const string& indent) const;
    108     string open_tag_to_string(const XMLNamespaceMap& nspaces, const string& indent,
    109             int pretty) const;
    110 
    111     int m_type;
    112     int m_pretty;
    113     SourcePos m_pos;
    114 
    115     // element
    116     string m_ns;
    117     string m_name;
    118     vector<XMLAttribute> m_attrs;
    119     vector<XMLNode*> m_children;
    120 
    121     // text
    122     string m_text;
    123 };
    124 
    125 class XMLHandler
    126 {
    127 public:
    128     // information about the element that started us
    129     SourcePos elementPos;
    130     string elementNamespace;
    131     string elementName;
    132     vector<XMLAttribute> elementAttributes;
    133 
    134     XMLHandler();
    135     virtual ~XMLHandler();
    136 
    137     XMLHandler* parent;
    138 
    139     virtual int OnStartElement(const SourcePos& pos, const string& ns, const string& name,
    140                                 const vector<XMLAttribute>& attrs, XMLHandler** next);
    141     virtual int OnEndElement(const SourcePos& pos, const string& ns, const string& name);
    142     virtual int OnText(const SourcePos& pos, const string& text);
    143     virtual int OnComment(const SourcePos& pos, const string& text);
    144     virtual int OnDone(const SourcePos& pos);
    145 
    146     static bool ParseFile(const string& filename, XMLHandler* handler);
    147     static bool ParseString(const string& filename, const string& text, XMLHandler* handler);
    148 };
    149 
    150 class TopElementHandler : public XMLHandler
    151 {
    152 public:
    153     TopElementHandler(const string& ns, const string& name, XMLHandler* next);
    154 
    155     virtual int OnStartElement(const SourcePos& pos, const string& ns, const string& name,
    156                                 const vector<XMLAttribute>& attrs, XMLHandler** next);
    157     virtual int OnEndElement(const SourcePos& pos, const string& ns, const string& name);
    158     virtual int OnText(const SourcePos& pos, const string& text);
    159     virtual int OnDone(const SourcePos& endPos);
    160 
    161 private:
    162     string m_ns;
    163     string m_name;
    164     XMLHandler* m_next;
    165 };
    166 
    167 class NodeHandler : public XMLHandler
    168 {
    169 public:
    170     // after it's done, you own everything created and added to root
    171     NodeHandler(XMLNode* root, int pretty);
    172     ~NodeHandler();
    173 
    174     virtual int OnStartElement(const SourcePos& pos, const string& ns, const string& name,
    175                                 const vector<XMLAttribute>& attrs, XMLHandler** next);
    176     virtual int OnEndElement(const SourcePos& pos, const string& ns, const string& name);
    177     virtual int OnText(const SourcePos& pos, const string& text);
    178     virtual int OnComment(const SourcePos& pos, const string& text);
    179     virtual int OnDone(const SourcePos& endPos);
    180 
    181     inline XMLNode* Root() const                { return m_root; }
    182 
    183     static XMLNode* ParseFile(const string& filename, int pretty);
    184     static XMLNode* ParseString(const string& filename, const string& text, int pretty);
    185 
    186 private:
    187     XMLNode* m_root;
    188     int m_pretty;
    189     vector<XMLNode*> m_nodes;
    190 };
    191 
    192 template <class T>
    193 static void delete_object(T* obj)
    194 {
    195     delete obj;
    196 }
    197 
    198 #endif // XML_H
    199