]> git.saurik.com Git - wxWidgets.git/blame - contrib/src/xml/xmlpars.cpp
added XML resources library
[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);
46
47static struct
48{
49 wxDllType Handle;
50
51 type_xmlCreatePushParserCtxt xmlCreatePushParserCtxt;
52 type_xmlNewText xmlNewText;
53 type_xmlSetProp xmlSetProp;
54 type_xmlParseChunk xmlParseChunk;
55 type_xmlFreeParserCtxt xmlFreeParserCtxt;
56 type_xmlNewDoc xmlNewDoc;
57 type_xmlFreeDoc xmlFreeDoc;
58 type_xmlNewDocNode xmlNewDocNode;
59 type_xmlDocDumpMemory xmlDocDumpMemory;
60 type_xmlAddChild xmlAddChild;
61 type_xmlNewChild xmlNewChild;
62 type_xmlNodeListGetString xmlNodeListGetString;
63 type_xmlDocGetRootElement xmlDocGetRootElement;
64 type_xmlDocSetRootElement xmlDocSetRootElement;
65} gs_libxmlDLL;
66
67static bool gs_libxmlLoaded = FALSE;
68static bool gs_libxmlLoadFailed = FALSE;
69
70
71
72static void ReleaseLibxml()
73{
74 if (gs_libxmlLoaded)
75 {
76 wxLogDebug("Releasing libxml.so.2");
77 wxDllLoader::UnloadLibrary(gs_libxmlDLL.Handle);
78 }
79 gs_libxmlLoaded = FALSE;
80 gs_libxmlLoadFailed = FALSE;
81}
82
83
84static bool LoadLibxml()
85{
86 if (gs_libxmlLoaded) return TRUE;
87 if (gs_libxmlLoadFailed) return FALSE;
88 gs_libxmlLoadFailed = TRUE;
89
90 wxLogDebug("Loading libxml.so.2...");
91#ifdef __UNIX__
92 gs_libxmlDLL.Handle =
93 wxDllLoader::LoadLibrary(_T("libxml.so.2"), &gs_libxmlLoaded);
94#endif
95
96 if (!gs_libxmlLoaded) return FALSE;
97
98#define LOAD_SYMBOL(sym) \
99 gs_libxmlDLL.sym = \
100 (type_##sym)wxDllLoader::GetSymbol(gs_libxmlDLL.Handle, _T(#sym)); \
101 if (!gs_libxmlDLL.sym) { ReleaseLibxml(); return FALSE; }
102
103 LOAD_SYMBOL(xmlCreatePushParserCtxt)
104 LOAD_SYMBOL(xmlNewText)
105 LOAD_SYMBOL(xmlSetProp)
106 LOAD_SYMBOL(xmlParseChunk)
107 LOAD_SYMBOL(xmlFreeParserCtxt)
108 LOAD_SYMBOL(xmlNewDoc)
109 LOAD_SYMBOL(xmlFreeDoc)
110 LOAD_SYMBOL(xmlNewDocNode)
111 LOAD_SYMBOL(xmlDocDumpMemory)
112 LOAD_SYMBOL(xmlAddChild)
113 LOAD_SYMBOL(xmlNewChild)
114 LOAD_SYMBOL(xmlNodeListGetString)
115 LOAD_SYMBOL(xmlDocGetRootElement)
116 LOAD_SYMBOL(xmlDocSetRootElement)
117
118#undef LOAD_SYMBOL
119
120 gs_libxmlLoadFailed = FALSE;
121
122 wxLogDebug("...succeed");
123 return TRUE;
124}
125
126
127
128
129bool wxXmlIOHandlerLibxml::CanLoad(wxInputStream& stream)
130{
131 if (!LoadLibxml()) return FALSE;
132 char cheader[7];
133 cheader[6] = 0;
134 stream.Read(cheader, 6);
135 stream.SeekI(-6, wxFromCurrent);
136 return strcmp(cheader, "<?xml ") == 0;
137}
138
139
140
141bool wxXmlIOHandlerLibxml::CanSave()
142{
143 return LoadLibxml();
144}
145
146
147
148static wxXmlProperty *CreateWXProperty(xmlDocPtr doc, xmlAttrPtr attr)
149{
150 if (attr == NULL) return NULL;
151
152 unsigned char *val =
153 gs_libxmlDLL.xmlNodeListGetString(doc, attr->children, 1);
154 wxXmlProperty *prop =
155 new wxXmlProperty(attr->name, val, CreateWXProperty(doc, attr->next));
156 free(val);
157 return prop;
158}
159
160
161
162static wxXmlNode *CreateWXNode(xmlDocPtr doc, wxXmlNode *parent, xmlNodePtr node)
163{
164 if (node == NULL) return NULL;
165
166 wxXmlNode *nd = new wxXmlNode(parent, (wxXmlNodeType)node->type,
167 node->name, node->content,
168 CreateWXProperty(doc, node->properties),
169 CreateWXNode(doc, parent, node->next));
170 CreateWXNode(doc, nd, node->children);
171 return nd;
172}
173
174
175
176bool wxXmlIOHandlerLibxml::Load(wxInputStream& stream, wxXmlDocument& doc)
177{
178 if (!LoadLibxml()) return FALSE;
179
180 xmlDocPtr dc;
181 xmlParserCtxtPtr ctxt;
182
183 char buffer[1024];
184 int res;
185
186 res = stream.Read(buffer, 4).LastRead();
187 if (res > 0)
188 {
189 bool okay = TRUE;
190 ctxt = gs_libxmlDLL.xmlCreatePushParserCtxt(NULL, NULL,
191 buffer, res, ""/*docname*/);
192 while ((res = stream.Read(buffer, 1024).LastRead()) > 0)
193 if (gs_libxmlDLL.xmlParseChunk(ctxt, buffer, res, 0) != 0)
194 okay = FALSE;
195 if (gs_libxmlDLL.xmlParseChunk(ctxt, buffer, 0, 1) != 0) okay = FALSE;
196 dc = ctxt->myDoc;
197 gs_libxmlDLL.xmlFreeParserCtxt(ctxt);
198
199 doc.SetVersion(dc->version);
200 doc.SetEncoding(dc->encoding);
201 doc.SetRoot(CreateWXNode(dc, NULL, gs_libxmlDLL.xmlDocGetRootElement(dc)));
202
203 gs_libxmlDLL.xmlFreeDoc(dc);
204
205 return okay;
206 }
207 else return FALSE;
208}
209
210
211
212static void CreateLibxmlNode(xmlNodePtr node, wxXmlNode *wxnode)
213{
214 node->type = (xmlElementType)wxnode->GetType();
215
216 wxXmlProperty *prop = wxnode->GetProperties();
217 while (prop)
218 {
219 gs_libxmlDLL.xmlSetProp(node, (xmlChar*)prop->GetName().mb_str(),
220 (xmlChar*)prop->GetValue().mb_str());
221 prop = prop->GetNext();
222 }
223
224 wxXmlNode *child = wxnode->GetChildren();
225 xmlNodePtr n;
226 xmlChar *content, *name;
227
228 while (child)
229 {
230 name = (xmlChar*)child->GetName().mb_str();
231 if (!child->GetContent()) content = NULL;
232 else content = (xmlChar*)child->GetContent().mb_str();
233 if (child->GetType() == wxXML_TEXT_NODE)
234 gs_libxmlDLL.xmlAddChild(node, n = gs_libxmlDLL.xmlNewText(content));
235 else
236 n = gs_libxmlDLL.xmlNewChild(node, NULL, name, content);
237 CreateLibxmlNode(n, child);
238 child = child->GetNext();
239 }
240}
241
242
243
244bool wxXmlIOHandlerLibxml::Save(wxOutputStream& stream, const wxXmlDocument& doc)
245{
246 if (!LoadLibxml()) return FALSE;
247
248 xmlDocPtr dc;
249
250 wxASSERT_MSG(doc.GetRoot() != NULL, _("Trying to save empty document!"));
251
252 dc = gs_libxmlDLL.xmlNewDoc((xmlChar*)doc.GetVersion().mb_str());
253
254 gs_libxmlDLL.xmlDocSetRootElement(dc,
255 gs_libxmlDLL.xmlNewDocNode(dc, NULL,
256 (xmlChar*)doc.GetRoot()->GetName().mb_str(), NULL));
257 CreateLibxmlNode(gs_libxmlDLL.xmlDocGetRootElement(dc), doc.GetRoot());
258
259 xmlChar *buffer;
260 int size;
261
262 gs_libxmlDLL.xmlDocDumpMemory(dc, &buffer, &size);
263 gs_libxmlDLL.xmlFreeDoc(dc);
264 stream.Write(buffer, size);
265 free(buffer);
266 return stream.LastWrite() == (unsigned)size;
267}
268
269
270
271
272#include "wx/module.h"
273
274class wxXmlLibxmlModule: public wxModule
275{
276 DECLARE_DYNAMIC_CLASS(wxXmlLibxmlModule)
277 public:
278 wxXmlLibxmlModule() {}
279 bool OnInit() { return TRUE; }
280 void OnExit() { ReleaseLibxml(); }
281};
282
283IMPLEMENT_DYNAMIC_CLASS(wxXmlLibxmlModule, wxModule)