1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        xml.h
3 // Purpose:     wxXmlDocument - XML parser & data holder class
4 // Author:      Vaclav Slavik
5 // Created:     2000/03/05
6 // RCS-ID:      $Id: xml.h 59768 2009-03-23 12:35:12Z VZ $
7 // Copyright:   (c) 2000 Vaclav Slavik
8 // Licence:     wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10 
11 
12 #ifndef _WX_XML_H_
13 #define _WX_XML_H_
14 
15 #include "wx/defs.h"
16 
17 #if wxUSE_XML
18 
19 #include "wx/string.h"
20 #include "wx/object.h"
21 #include "wx/list.h"
22 
23 #ifdef WXMAKINGDLL_XML
24     #define WXDLLIMPEXP_XML WXEXPORT
25 #elif defined(WXUSINGDLL)
26     #define WXDLLIMPEXP_XML WXIMPORT
27 #else // not making nor using DLL
28     #define WXDLLIMPEXP_XML
29 #endif
30 
31 class WXDLLIMPEXP_FWD_XML wxXmlNode;
32 class WXDLLIMPEXP_FWD_XML wxXmlProperty;
33 class WXDLLIMPEXP_FWD_XML wxXmlDocument;
34 class WXDLLIMPEXP_FWD_XML wxXmlIOHandler;
35 class WXDLLIMPEXP_FWD_BASE wxInputStream;
36 class WXDLLIMPEXP_FWD_BASE wxOutputStream;
37 
38 
39 // Represents XML node type.
40 enum wxXmlNodeType
41 {
42     // note: values are synchronized with xmlElementType from libxml
43     wxXML_ELEMENT_NODE       =  1,
44     wxXML_ATTRIBUTE_NODE     =  2,
45     wxXML_TEXT_NODE          =  3,
46     wxXML_CDATA_SECTION_NODE =  4,
47     wxXML_ENTITY_REF_NODE    =  5,
48     wxXML_ENTITY_NODE        =  6,
49     wxXML_PI_NODE            =  7,
50     wxXML_COMMENT_NODE       =  8,
51     wxXML_DOCUMENT_NODE      =  9,
52     wxXML_DOCUMENT_TYPE_NODE = 10,
53     wxXML_DOCUMENT_FRAG_NODE = 11,
54     wxXML_NOTATION_NODE      = 12,
55     wxXML_HTML_DOCUMENT_NODE = 13
56 };
57 
58 
59 // Represents node property(ies).
60 // Example: in <img src="hello.gif" id="3"/> "src" is property with value
61 //          "hello.gif" and "id" is prop. with value "3".
62 
63 class WXDLLIMPEXP_XML wxXmlProperty
64 {
65 public:
wxXmlProperty()66     wxXmlProperty() : m_next(NULL) {}
67     wxXmlProperty(const wxString& name, const wxString& value,
68                   wxXmlProperty *next = NULL)
m_name(name)69             : m_name(name), m_value(value), m_next(next) {}
~wxXmlProperty()70     virtual ~wxXmlProperty() {}
71 
GetName()72     wxString GetName() const { return m_name; }
GetValue()73     wxString GetValue() const { return m_value; }
GetNext()74     wxXmlProperty *GetNext() const { return m_next; }
75 
SetName(const wxString & name)76     void SetName(const wxString& name) { m_name = name; }
SetValue(const wxString & value)77     void SetValue(const wxString& value) { m_value = value; }
SetNext(wxXmlProperty * next)78     void SetNext(wxXmlProperty *next) { m_next = next; }
79 
80 private:
81     wxString m_name;
82     wxString m_value;
83     wxXmlProperty *m_next;
84 };
85 
86 
87 
88 // Represents node in XML document. Node has name and may have content
89 // and properties. Most common node types are wxXML_TEXT_NODE (name and props
90 // are irrelevant) and wxXML_ELEMENT_NODE (e.g. in <title>hi</title> there is
91 // element with name="title", irrelevant content and one child (wxXML_TEXT_NODE
92 // with content="hi").
93 //
94 // If wxUSE_UNICODE is 0, all strings are encoded in the encoding given to Load
95 // (default is UTF-8).
96 
97 class WXDLLIMPEXP_XML wxXmlNode
98 {
99 public:
wxXmlNode()100     wxXmlNode() : m_properties(NULL), m_parent(NULL),
101                   m_children(NULL), m_next(NULL) {}
102     wxXmlNode(wxXmlNode *parent, wxXmlNodeType type,
103               const wxString& name, const wxString& content = wxEmptyString,
104               wxXmlProperty *props = NULL, wxXmlNode *next = NULL);
105     virtual ~wxXmlNode();
106 
107     // copy ctor & operator=. Note that this does NOT copy syblings
108     // and parent pointer, i.e. m_parent and m_next will be NULL
109     // after using copy ctor and are never unmodified by operator=.
110     // On the other hand, it DOES copy children and properties.
111     wxXmlNode(const wxXmlNode& node);
112     wxXmlNode& operator=(const wxXmlNode& node);
113 
114     // user-friendly creation:
115     wxXmlNode(wxXmlNodeType type, const wxString& name,
116               const wxString& content = wxEmptyString);
117     virtual void AddChild(wxXmlNode *child);
118     virtual bool InsertChild(wxXmlNode *child, wxXmlNode *followingNode);
119 #if wxABI_VERSION >= 20808
120     bool InsertChildAfter(wxXmlNode *child, wxXmlNode *precedingNode);
121 #endif
122     virtual bool RemoveChild(wxXmlNode *child);
123     virtual void AddProperty(const wxString& name, const wxString& value);
124     virtual bool DeleteProperty(const wxString& name);
125 
126     // access methods:
GetType()127     wxXmlNodeType GetType() const { return m_type; }
GetName()128     wxString GetName() const { return m_name; }
GetContent()129     wxString GetContent() const { return m_content; }
130 
131     bool IsWhitespaceOnly() const;
132     int GetDepth(wxXmlNode *grandparent = NULL) const;
133 
134     // Gets node content from wxXML_ENTITY_NODE
135     // The problem is, <tag>content<tag> is represented as
136     // wxXML_ENTITY_NODE name="tag", content=""
137     //    |-- wxXML_TEXT_NODE or
138     //        wxXML_CDATA_SECTION_NODE name="" content="content"
139     wxString GetNodeContent() const;
140 
GetParent()141     wxXmlNode *GetParent() const { return m_parent; }
GetNext()142     wxXmlNode *GetNext() const { return m_next; }
GetChildren()143     wxXmlNode *GetChildren() const { return m_children; }
144 
GetProperties()145     wxXmlProperty *GetProperties() const { return m_properties; }
146     bool GetPropVal(const wxString& propName, wxString *value) const;
147     wxString GetPropVal(const wxString& propName,
148                         const wxString& defaultVal) const;
149     bool HasProp(const wxString& propName) const;
150 
SetType(wxXmlNodeType type)151     void SetType(wxXmlNodeType type) { m_type = type; }
SetName(const wxString & name)152     void SetName(const wxString& name) { m_name = name; }
SetContent(const wxString & con)153     void SetContent(const wxString& con) { m_content = con; }
154 
SetParent(wxXmlNode * parent)155     void SetParent(wxXmlNode *parent) { m_parent = parent; }
SetNext(wxXmlNode * next)156     void SetNext(wxXmlNode *next) { m_next = next; }
SetChildren(wxXmlNode * child)157     void SetChildren(wxXmlNode *child) { m_children = child; }
158 
SetProperties(wxXmlProperty * prop)159     void SetProperties(wxXmlProperty *prop) { m_properties = prop; }
160     virtual void AddProperty(wxXmlProperty *prop);
161 
162 #if wxABI_VERSION >= 20811
GetAttribute(const wxString & attrName,const wxString & defaultVal)163     wxString GetAttribute(const wxString& attrName,
164                          const wxString& defaultVal) const
165     {
166         return GetPropVal(attrName, defaultVal);
167     }
GetAttribute(const wxString & attrName,wxString * value)168     bool GetAttribute(const wxString& attrName, wxString *value) const
169     {
170         return GetPropVal(attrName, value);
171     }
AddAttribute(const wxString & attrName,const wxString & value)172     void AddAttribute(const wxString& attrName, const wxString& value)
173     {
174         AddProperty(attrName, value);
175     }
GetAttributes()176     wxXmlProperty* GetAttributes() const
177     {
178         return GetProperties();
179     }
180 #endif // wx >= 2.8.11
181 
182 private:
183     wxXmlNodeType m_type;
184     wxString m_name;
185     wxString m_content;
186     wxXmlProperty *m_properties;
187     wxXmlNode *m_parent, *m_children, *m_next;
188 
189     void DoCopy(const wxXmlNode& node);
190 };
191 
192 
193 
194 // special indentation value for wxXmlDocument::Save
195 #define wxXML_NO_INDENTATION           (-1)
196 
197 // flags for wxXmlDocument::Load
198 enum wxXmlDocumentLoadFlag
199 {
200     wxXMLDOC_NONE = 0,
201     wxXMLDOC_KEEP_WHITESPACE_NODES = 1
202 };
203 
204 
205 // This class holds XML data/document as parsed by XML parser.
206 
207 class WXDLLIMPEXP_XML wxXmlDocument : public wxObject
208 {
209 public:
210     wxXmlDocument();
211     wxXmlDocument(const wxString& filename,
212                   const wxString& encoding = wxT("UTF-8"));
213     wxXmlDocument(wxInputStream& stream,
214                   const wxString& encoding = wxT("UTF-8"));
~wxXmlDocument()215     virtual ~wxXmlDocument() { wxDELETE(m_root); }
216 
217     wxXmlDocument(const wxXmlDocument& doc);
218     wxXmlDocument& operator=(const wxXmlDocument& doc);
219 
220     // Parses .xml file and loads data. Returns TRUE on success, FALSE
221     // otherwise.
222     virtual bool Load(const wxString& filename,
223                       const wxString& encoding = wxT("UTF-8"), int flags = wxXMLDOC_NONE);
224     virtual bool Load(wxInputStream& stream,
225                       const wxString& encoding = wxT("UTF-8"), int flags = wxXMLDOC_NONE);
226 
227     // Saves document as .xml file.
228     virtual bool Save(const wxString& filename, int indentstep = 1) const;
229     virtual bool Save(wxOutputStream& stream, int indentstep = 1) const;
230 
IsOk()231     bool IsOk() const { return m_root != NULL; }
232 
233     // Returns root node of the document.
GetRoot()234     wxXmlNode *GetRoot() const { return m_root; }
235 
236     // Returns version of document (may be empty).
GetVersion()237     wxString GetVersion() const { return m_version; }
238     // Returns encoding of document (may be empty).
239     // Note: this is the encoding original file was saved in, *not* the
240     // encoding of in-memory representation!
GetFileEncoding()241     wxString GetFileEncoding() const { return m_fileEncoding; }
242 
243     // Write-access methods:
DetachRoot()244     wxXmlNode *DetachRoot() { wxXmlNode *old=m_root; m_root=NULL; return old; }
SetRoot(wxXmlNode * node)245     void SetRoot(wxXmlNode *node) { wxDELETE(m_root); m_root = node; }
SetVersion(const wxString & version)246     void SetVersion(const wxString& version) { m_version = version; }
SetFileEncoding(const wxString & encoding)247     void SetFileEncoding(const wxString& encoding) { m_fileEncoding = encoding; }
248 
249 #if !wxUSE_UNICODE
250     // Returns encoding of in-memory representation of the document
251     // (same as passed to Load or ctor, defaults to UTF-8).
252     // NB: this is meaningless in Unicode build where data are stored as wchar_t*
GetEncoding()253     wxString GetEncoding() const { return m_encoding; }
SetEncoding(const wxString & enc)254     void SetEncoding(const wxString& enc) { m_encoding = enc; }
255 #endif
256 
257 private:
258     wxString   m_version;
259     wxString   m_fileEncoding;
260 #if !wxUSE_UNICODE
261     wxString   m_encoding;
262 #endif
263     wxXmlNode *m_root;
264 
265     void DoCopy(const wxXmlDocument& doc);
266 
267     DECLARE_CLASS(wxXmlDocument)
268 };
269 
270 #endif // wxUSE_XML
271 
272 #endif // _WX_XML_H_
273