]> git.saurik.com Git - wxWidgets.git/blame - contrib/src/xml/xmlpars.cpp
standardized syntax of bool properties: '1' means true, anything else false
[wxWidgets.git] / contrib / src / xml / xmlpars.cpp
CommitLineData
56d2f750
VS
1/////////////////////////////////////////////////////////////////////////////
2// Name: xmlpars.cpp
3// Purpose: wxXmlDocument - XML parser
4// Author: Vaclav Slavik
5// Created: 2000/03/05
6// RCS-ID: $Id$
7// Copyright: (c) 2000 Vaclav Slavik
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11#ifdef __GNUG__
12// nothing - already in xml.cpp
13#endif
14
15// For compilers that support precompilation, includes "wx.h".
16#include "wx/wxprec.h"
17
18#ifdef __BORLANDC__
19 #pragma hdrstop
20#endif
21
22#include "wx/wfstream.h"
23#include "wx/intl.h"
24#include "wx/log.h"
25#include "wx/dynlib.h"
26#include "wx/xml/xmlio.h"
27
28#include <libxml/parser.h>
29
30// dynamically loaded functions from libxml:
31typedef xmlParserCtxtPtr (*type_xmlCreatePushParserCtxt)
32 (xmlSAXHandlerPtr sax, void *, const char *, int, const char *);
33typedef xmlNodePtr (*type_xmlNewText)(const xmlChar *);
34typedef xmlAttrPtr (*type_xmlSetProp)(xmlNodePtr, const xmlChar *, const xmlChar *);
35typedef int (*type_xmlParseChunk)(xmlParserCtxtPtr, const char *, int, int);
36typedef void (*type_xmlFreeParserCtxt)(xmlParserCtxtPtr);
37typedef xmlDocPtr (*type_xmlNewDoc)(const xmlChar *);
38typedef void (*type_xmlFreeDoc)(xmlDocPtr);
39typedef xmlNodePtr (*type_xmlNewDocNode)(xmlDocPtr, xmlNsPtr, const xmlChar *, const xmlChar *);
40typedef void (*type_xmlDocDumpMemory)(xmlDocPtr, xmlChar**, int *);
41typedef xmlNodePtr (*type_xmlAddChild)(xmlNodePtr, xmlNodePtr);
42typedef xmlNodePtr (*type_xmlNewChild)(xmlNodePtr, xmlNsPtr, const xmlChar *, const xmlChar *);
43typedef xmlChar * (*type_xmlNodeListGetString)(xmlDocPtr, xmlNodePtr, int);
44typedef xmlNodePtr (*type_xmlDocGetRootElement)(xmlDocPtr);
45typedef xmlNodePtr (*type_xmlDocSetRootElement)(xmlDocPtr doc, xmlNodePtr root);
dfc0e3fb
VS
46typedef void (*(*type_xmlFree))(void *);
47typedef int (*type_xmlKeepBlanksDefault)(int);
56d2f750
VS
48
49static struct
50{
51 wxDllType Handle;
52
53 type_xmlCreatePushParserCtxt xmlCreatePushParserCtxt;
54 type_xmlNewText xmlNewText;
55 type_xmlSetProp xmlSetProp;
56 type_xmlParseChunk xmlParseChunk;
57 type_xmlFreeParserCtxt xmlFreeParserCtxt;
58 type_xmlNewDoc xmlNewDoc;
59 type_xmlFreeDoc xmlFreeDoc;
60 type_xmlNewDocNode xmlNewDocNode;
61 type_xmlDocDumpMemory xmlDocDumpMemory;
62 type_xmlAddChild xmlAddChild;
63 type_xmlNewChild xmlNewChild;
64 type_xmlNodeListGetString xmlNodeListGetString;
65 type_xmlDocGetRootElement xmlDocGetRootElement;
66 type_xmlDocSetRootElement xmlDocSetRootElement;
dfc0e3fb
VS
67 type_xmlFree xmlFree;
68 type_xmlKeepBlanksDefault xmlKeepBlanksDefault;
56d2f750
VS
69} gs_libxmlDLL;
70
71static bool gs_libxmlLoaded = FALSE;
72static bool gs_libxmlLoadFailed = FALSE;
73
74
75
76static void ReleaseLibxml()
77{
78 if (gs_libxmlLoaded)
79 {
80 wxLogDebug("Releasing libxml.so.2");
81 wxDllLoader::UnloadLibrary(gs_libxmlDLL.Handle);
82 }
83 gs_libxmlLoaded = FALSE;
84 gs_libxmlLoadFailed = FALSE;
85}
86
87
88static bool LoadLibxml()
89{
90 if (gs_libxmlLoaded) return TRUE;
91 if (gs_libxmlLoadFailed) return FALSE;
92 gs_libxmlLoadFailed = TRUE;
93
94 wxLogDebug("Loading libxml.so.2...");
dfc0e3fb
VS
95 {
96 wxLogNull lg;
56d2f750
VS
97#ifdef __UNIX__
98 gs_libxmlDLL.Handle =
dfc0e3fb
VS
99 wxDllLoader::LoadLibrary(_T("wxlibxml.so.2"), &gs_libxmlLoaded);
100 if (!gs_libxmlLoaded) gs_libxmlDLL.Handle =
56d2f750
VS
101 wxDllLoader::LoadLibrary(_T("libxml.so.2"), &gs_libxmlLoaded);
102#endif
dfc0e3fb
VS
103#ifdef __WXMSW__
104 gs_libxmlDLL.Handle =
105 wxDllLoader::LoadLibrary(_T("wxlibxml2.dll"), &gs_libxmlLoaded);
106 if (!gs_libxmlLoaded) gs_libxmlDLL.Handle =
107 wxDllLoader::LoadLibrary(_T("libxml2.dll"), &gs_libxmlLoaded);
108#endif
109 }
56d2f750 110
dfc0e3fb
VS
111 if (!gs_libxmlLoaded)
112 {
113 wxLogError(_("Failed to load libxml shared library."));
114 return FALSE;
115 }
56d2f750
VS
116
117#define LOAD_SYMBOL(sym) \
118 gs_libxmlDLL.sym = \
119 (type_##sym)wxDllLoader::GetSymbol(gs_libxmlDLL.Handle, _T(#sym)); \
dfc0e3fb
VS
120 if (!gs_libxmlDLL.sym) \
121 { \
122 ReleaseLibxml(); \
123 wxLogError(_("Failed to load libxml shared library.")); \
124 return FALSE; \
125 }
56d2f750
VS
126
127 LOAD_SYMBOL(xmlCreatePushParserCtxt)
128 LOAD_SYMBOL(xmlNewText)
129 LOAD_SYMBOL(xmlSetProp)
130 LOAD_SYMBOL(xmlParseChunk)
131 LOAD_SYMBOL(xmlFreeParserCtxt)
132 LOAD_SYMBOL(xmlNewDoc)
133 LOAD_SYMBOL(xmlFreeDoc)
134 LOAD_SYMBOL(xmlNewDocNode)
135 LOAD_SYMBOL(xmlDocDumpMemory)
136 LOAD_SYMBOL(xmlAddChild)
137 LOAD_SYMBOL(xmlNewChild)
138 LOAD_SYMBOL(xmlNodeListGetString)
139 LOAD_SYMBOL(xmlDocGetRootElement)
140 LOAD_SYMBOL(xmlDocSetRootElement)
dfc0e3fb
VS
141 LOAD_SYMBOL(xmlFree)
142 LOAD_SYMBOL(xmlKeepBlanksDefault)
56d2f750
VS
143
144#undef LOAD_SYMBOL
145
146 gs_libxmlLoadFailed = FALSE;
147
148 wxLogDebug("...succeed");
149 return TRUE;
150}
151
152
153
154
155bool wxXmlIOHandlerLibxml::CanLoad(wxInputStream& stream)
156{
157 if (!LoadLibxml()) return FALSE;
158 char cheader[7];
159 cheader[6] = 0;
160 stream.Read(cheader, 6);
161 stream.SeekI(-6, wxFromCurrent);
162 return strcmp(cheader, "<?xml ") == 0;
163}
164
165
166
167bool wxXmlIOHandlerLibxml::CanSave()
168{
169 return LoadLibxml();
170}
171
172
173
174static wxXmlProperty *CreateWXProperty(xmlDocPtr doc, xmlAttrPtr attr)
175{
176 if (attr == NULL) return NULL;
177
178 unsigned char *val =
179 gs_libxmlDLL.xmlNodeListGetString(doc, attr->children, 1);
180 wxXmlProperty *prop =
181 new wxXmlProperty(attr->name, val, CreateWXProperty(doc, attr->next));
dfc0e3fb 182 (*gs_libxmlDLL.xmlFree)(val);
56d2f750
VS
183 return prop;
184}
185
186
187
188static wxXmlNode *CreateWXNode(xmlDocPtr doc, wxXmlNode *parent, xmlNodePtr node)
189{
190 if (node == NULL) return NULL;
191
192 wxXmlNode *nd = new wxXmlNode(parent, (wxXmlNodeType)node->type,
193 node->name, node->content,
194 CreateWXProperty(doc, node->properties),
195 CreateWXNode(doc, parent, node->next));
196 CreateWXNode(doc, nd, node->children);
197 return nd;
198}
199
200
201
202bool wxXmlIOHandlerLibxml::Load(wxInputStream& stream, wxXmlDocument& doc)
203{
204 if (!LoadLibxml()) return FALSE;
205
206 xmlDocPtr dc;
207 xmlParserCtxtPtr ctxt;
208
209 char buffer[1024];
210 int res;
211
212 res = stream.Read(buffer, 4).LastRead();
213 if (res > 0)
214 {
215 bool okay = TRUE;
dfc0e3fb 216 gs_libxmlDLL.xmlKeepBlanksDefault(0);
56d2f750
VS
217 ctxt = gs_libxmlDLL.xmlCreatePushParserCtxt(NULL, NULL,
218 buffer, res, ""/*docname*/);
219 while ((res = stream.Read(buffer, 1024).LastRead()) > 0)
220 if (gs_libxmlDLL.xmlParseChunk(ctxt, buffer, res, 0) != 0)
221 okay = FALSE;
222 if (gs_libxmlDLL.xmlParseChunk(ctxt, buffer, 0, 1) != 0) okay = FALSE;
223 dc = ctxt->myDoc;
224 gs_libxmlDLL.xmlFreeParserCtxt(ctxt);
225
226 doc.SetVersion(dc->version);
227 doc.SetEncoding(dc->encoding);
228 doc.SetRoot(CreateWXNode(dc, NULL, gs_libxmlDLL.xmlDocGetRootElement(dc)));
229
230 gs_libxmlDLL.xmlFreeDoc(dc);
231
232 return okay;
233 }
234 else return FALSE;
235}
236
237
238
239static void CreateLibxmlNode(xmlNodePtr node, wxXmlNode *wxnode)
240{
241 node->type = (xmlElementType)wxnode->GetType();
242
243 wxXmlProperty *prop = wxnode->GetProperties();
244 while (prop)
245 {
246 gs_libxmlDLL.xmlSetProp(node, (xmlChar*)prop->GetName().mb_str(),
247 (xmlChar*)prop->GetValue().mb_str());
248 prop = prop->GetNext();
249 }
250
251 wxXmlNode *child = wxnode->GetChildren();
252 xmlNodePtr n;
253 xmlChar *content, *name;
254
255 while (child)
256 {
257 name = (xmlChar*)child->GetName().mb_str();
258 if (!child->GetContent()) content = NULL;
259 else content = (xmlChar*)child->GetContent().mb_str();
260 if (child->GetType() == wxXML_TEXT_NODE)
261 gs_libxmlDLL.xmlAddChild(node, n = gs_libxmlDLL.xmlNewText(content));
262 else
263 n = gs_libxmlDLL.xmlNewChild(node, NULL, name, content);
264 CreateLibxmlNode(n, child);
265 child = child->GetNext();
266 }
267}
268
269
270
271bool wxXmlIOHandlerLibxml::Save(wxOutputStream& stream, const wxXmlDocument& doc)
272{
273 if (!LoadLibxml()) return FALSE;
274
275 xmlDocPtr dc;
276
277 wxASSERT_MSG(doc.GetRoot() != NULL, _("Trying to save empty document!"));
278
dfc0e3fb 279 gs_libxmlDLL.xmlKeepBlanksDefault(0);
56d2f750
VS
280 dc = gs_libxmlDLL.xmlNewDoc((xmlChar*)doc.GetVersion().mb_str());
281
282 gs_libxmlDLL.xmlDocSetRootElement(dc,
283 gs_libxmlDLL.xmlNewDocNode(dc, NULL,
284 (xmlChar*)doc.GetRoot()->GetName().mb_str(), NULL));
285 CreateLibxmlNode(gs_libxmlDLL.xmlDocGetRootElement(dc), doc.GetRoot());
286
287 xmlChar *buffer;
288 int size;
289
290 gs_libxmlDLL.xmlDocDumpMemory(dc, &buffer, &size);
291 gs_libxmlDLL.xmlFreeDoc(dc);
292 stream.Write(buffer, size);
dfc0e3fb 293 (*gs_libxmlDLL.xmlFree)(buffer);
56d2f750
VS
294 return stream.LastWrite() == (unsigned)size;
295}
296
297
298
299
300#include "wx/module.h"
301
302class wxXmlLibxmlModule: public wxModule
303{
304 DECLARE_DYNAMIC_CLASS(wxXmlLibxmlModule)
305 public:
306 wxXmlLibxmlModule() {}
307 bool OnInit() { return TRUE; }
308 void OnExit() { ReleaseLibxml(); }
309};
310
311IMPLEMENT_DYNAMIC_CLASS(wxXmlLibxmlModule, wxModule)