1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxXmlDocument - XML parser
4 // Author: Vaclav Slavik
7 // Copyright: (c) 2000 Vaclav Slavik
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
12 // nothing - already in xml.cpp
15 // For compilers that support precompilation, includes "wx.h".
16 #include "wx/wxprec.h"
22 #include "wx/wfstream.h"
25 #include "wx/dynlib.h"
26 #include "wx/xml/xmlio.h"
28 #include <libxml/parser.h>
30 // dynamically loaded functions from libxml:
31 typedef xmlParserCtxtPtr (*type_xmlCreatePushParserCtxt
)
32 (xmlSAXHandlerPtr sax
, void *, const char *, int, const char *);
33 typedef xmlNodePtr (*type_xmlNewText
)(const xmlChar
*);
34 typedef xmlAttrPtr (*type_xmlSetProp
)(xmlNodePtr
, const xmlChar
*, const xmlChar
*);
35 typedef int (*type_xmlParseChunk
)(xmlParserCtxtPtr
, const char *, int, int);
36 typedef void (*type_xmlFreeParserCtxt
)(xmlParserCtxtPtr
);
37 typedef xmlDocPtr (*type_xmlNewDoc
)(const xmlChar
*);
38 typedef void (*type_xmlFreeDoc
)(xmlDocPtr
);
39 typedef xmlNodePtr (*type_xmlNewDocNode
)(xmlDocPtr
, xmlNsPtr
, const xmlChar
*, const xmlChar
*);
40 typedef void (*type_xmlDocDumpMemory
)(xmlDocPtr
, xmlChar
**, int *);
41 typedef xmlNodePtr (*type_xmlAddChild
)(xmlNodePtr
, xmlNodePtr
);
42 typedef xmlNodePtr (*type_xmlNewChild
)(xmlNodePtr
, xmlNsPtr
, const xmlChar
*, const xmlChar
*);
43 typedef xmlChar
* (*type_xmlNodeListGetString
)(xmlDocPtr
, xmlNodePtr
, int);
44 typedef xmlNodePtr (*type_xmlDocGetRootElement
)(xmlDocPtr
);
45 typedef xmlNodePtr (*type_xmlDocSetRootElement
)(xmlDocPtr doc
, xmlNodePtr root
);
46 typedef void (*(*type_xmlFree
))(void *);
47 typedef int (*type_xmlKeepBlanksDefault
)(int);
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
;
68 type_xmlKeepBlanksDefault xmlKeepBlanksDefault
;
71 static bool gs_libxmlLoaded
= FALSE
;
72 static bool gs_libxmlLoadFailed
= FALSE
;
76 static void ReleaseLibxml()
80 wxLogDebug("Releasing libxml.so.2");
81 wxDllLoader::UnloadLibrary(gs_libxmlDLL
.Handle
);
83 gs_libxmlLoaded
= FALSE
;
84 gs_libxmlLoadFailed
= FALSE
;
88 static bool LoadLibxml()
90 if (gs_libxmlLoaded
) return TRUE
;
91 if (gs_libxmlLoadFailed
) return FALSE
;
92 gs_libxmlLoadFailed
= TRUE
;
94 wxLogDebug("Loading libxml.so.2...");
99 wxDllLoader::LoadLibrary(_T("wxlibxml.so.2"), &gs_libxmlLoaded
);
100 if (!gs_libxmlLoaded
) gs_libxmlDLL
.Handle
=
101 wxDllLoader::LoadLibrary(_T("libxml.so.2"), &gs_libxmlLoaded
);
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
);
111 if (!gs_libxmlLoaded
)
113 wxLogError(_("Failed to load libxml shared library."));
117 #define LOAD_SYMBOL(sym) \
119 (type_##sym)wxDllLoader::GetSymbol(gs_libxmlDLL.Handle, _T(#sym)); \
120 if (!gs_libxmlDLL.sym) \
123 wxLogError(_("Failed to load libxml shared library.")); \
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
)
142 LOAD_SYMBOL(xmlKeepBlanksDefault
)
146 gs_libxmlLoadFailed
= FALSE
;
148 wxLogDebug("...succeed");
155 bool wxXmlIOHandlerLibxml::CanLoad(wxInputStream
& stream
)
157 if (!LoadLibxml()) return FALSE
;
160 stream
.Read(cheader
, 6);
161 stream
.SeekI(-6, wxFromCurrent
);
162 return strcmp(cheader
, "<?xml ") == 0;
167 bool wxXmlIOHandlerLibxml::CanSave()
174 static wxXmlProperty
*CreateWXProperty(xmlDocPtr doc
, xmlAttrPtr attr
)
176 if (attr
== NULL
) return NULL
;
179 gs_libxmlDLL
.xmlNodeListGetString(doc
, attr
->children
, 1);
180 wxXmlProperty
*prop
=
181 new wxXmlProperty(attr
->name
, val
, CreateWXProperty(doc
, attr
->next
));
182 (*gs_libxmlDLL
.xmlFree
)(val
);
188 static wxXmlNode
*CreateWXNode(xmlDocPtr doc
, wxXmlNode
*parent
, xmlNodePtr node
)
190 if (node
== NULL
) return NULL
;
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
);
202 bool wxXmlIOHandlerLibxml::Load(wxInputStream
& stream
, wxXmlDocument
& doc
)
204 if (!LoadLibxml()) return FALSE
;
207 xmlParserCtxtPtr ctxt
;
212 res
= stream
.Read(buffer
, 4).LastRead();
216 gs_libxmlDLL
.xmlKeepBlanksDefault(0);
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)
222 if (gs_libxmlDLL
.xmlParseChunk(ctxt
, buffer
, 0, 1) != 0) okay
= FALSE
;
224 gs_libxmlDLL
.xmlFreeParserCtxt(ctxt
);
226 doc
.SetVersion(dc
->version
);
227 doc
.SetEncoding(dc
->encoding
);
228 doc
.SetRoot(CreateWXNode(dc
, NULL
, gs_libxmlDLL
.xmlDocGetRootElement(dc
)));
230 gs_libxmlDLL
.xmlFreeDoc(dc
);
239 static void CreateLibxmlNode(xmlNodePtr node
, wxXmlNode
*wxnode
)
241 node
->type
= (xmlElementType
)wxnode
->GetType();
243 wxXmlProperty
*prop
= wxnode
->GetProperties();
246 gs_libxmlDLL
.xmlSetProp(node
, (xmlChar
*)prop
->GetName().mb_str(),
247 (xmlChar
*)prop
->GetValue().mb_str());
248 prop
= prop
->GetNext();
251 wxXmlNode
*child
= wxnode
->GetChildren();
253 xmlChar
*content
, *name
;
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
));
263 n
= gs_libxmlDLL
.xmlNewChild(node
, NULL
, name
, content
);
264 CreateLibxmlNode(n
, child
);
265 child
= child
->GetNext();
271 bool wxXmlIOHandlerLibxml::Save(wxOutputStream
& stream
, const wxXmlDocument
& doc
)
273 if (!LoadLibxml()) return FALSE
;
277 wxASSERT_MSG(doc
.GetRoot() != NULL
, _("Trying to save empty document!"));
279 gs_libxmlDLL
.xmlKeepBlanksDefault(0);
280 dc
= gs_libxmlDLL
.xmlNewDoc((xmlChar
*)doc
.GetVersion().mb_str());
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());
290 gs_libxmlDLL
.xmlDocDumpMemory(dc
, &buffer
, &size
);
291 gs_libxmlDLL
.xmlFreeDoc(dc
);
292 stream
.Write(buffer
, size
);
293 (*gs_libxmlDLL
.xmlFree
)(buffer
);
294 return stream
.LastWrite() == (unsigned)size
;
300 #include "wx/module.h"
302 class wxXmlLibxmlModule
: public wxModule
304 DECLARE_DYNAMIC_CLASS(wxXmlLibxmlModule
)
306 wxXmlLibxmlModule() {}
307 bool OnInit() { return TRUE
; }
308 void OnExit() { ReleaseLibxml(); }
311 IMPLEMENT_DYNAMIC_CLASS(wxXmlLibxmlModule
, wxModule
)