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
TypeXMLNode75 inline int Type() const { return m_type; }
PrettyXMLNode76 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
PositionXMLNode84 inline const SourcePos& Position() const { return m_pos; }
85
86 // element
NamespaceXMLNode87 inline string Namespace() const { return m_ns; }
NameXMLNode88 inline string Name() const { return m_name; }
SetNameXMLNode89 inline void SetName(const string& ns, const string& n) { m_ns = ns; m_name = n; }
AttributesXMLNode90 inline const vector<XMLAttribute>& Attributes() const { return m_attrs; }
EditAttributesXMLNode91 inline vector<XMLAttribute>& EditAttributes() { return m_attrs; }
ChildrenXMLNode92 inline const vector<XMLNode*>& Children() const { return m_children; }
EditChildrenXMLNode93 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
TextXMLNode100 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
Root()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>
delete_object(T * obj)193 static void delete_object(T* obj)
194 {
195 delete obj;
196 }
197
198 #endif // XML_H
199