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 wxDllLoader::UnloadLibrary(gs_libxmlDLL
.Handle
);
82 gs_libxmlLoaded
= FALSE
;
83 gs_libxmlLoadFailed
= FALSE
;
87 static bool LoadLibxml()
89 if (gs_libxmlLoaded
) return TRUE
;
90 if (gs_libxmlLoadFailed
) return FALSE
;
91 gs_libxmlLoadFailed
= TRUE
;
97 wxDllLoader::LoadLibrary(_T("wxlibxml.so.2"), &gs_libxmlLoaded
);
98 if (!gs_libxmlLoaded
) gs_libxmlDLL
.Handle
=
99 wxDllLoader::LoadLibrary(_T("libxml.so.2"), &gs_libxmlLoaded
);
102 gs_libxmlDLL
.Handle
=
103 wxDllLoader::LoadLibrary(_T("wxlibxml2.dll"), &gs_libxmlLoaded
);
104 if (!gs_libxmlLoaded
) gs_libxmlDLL
.Handle
=
105 wxDllLoader::LoadLibrary(_T("libxml2.dll"), &gs_libxmlLoaded
);
109 if (!gs_libxmlLoaded
)
111 wxLogError(_("Failed to load libxml shared library."));
115 #define LOAD_SYMBOL(sym) \
117 (type_##sym)wxDllLoader::GetSymbol(gs_libxmlDLL.Handle, _T(#sym)); \
118 if (!gs_libxmlDLL.sym) \
121 wxLogError(_("Failed to load libxml shared library.")); \
125 LOAD_SYMBOL(xmlCreatePushParserCtxt
)
126 LOAD_SYMBOL(xmlNewText
)
127 LOAD_SYMBOL(xmlSetProp
)
128 LOAD_SYMBOL(xmlParseChunk
)
129 LOAD_SYMBOL(xmlFreeParserCtxt
)
130 LOAD_SYMBOL(xmlNewDoc
)
131 LOAD_SYMBOL(xmlFreeDoc
)
132 LOAD_SYMBOL(xmlNewDocNode
)
133 LOAD_SYMBOL(xmlDocDumpMemory
)
134 LOAD_SYMBOL(xmlAddChild
)
135 LOAD_SYMBOL(xmlNewChild
)
136 LOAD_SYMBOL(xmlNodeListGetString
)
137 LOAD_SYMBOL(xmlDocGetRootElement
)
138 LOAD_SYMBOL(xmlDocSetRootElement
)
140 LOAD_SYMBOL(xmlKeepBlanksDefault
)
144 gs_libxmlLoadFailed
= FALSE
;
152 bool wxXmlIOHandlerLibxml::CanLoad(wxInputStream
& stream
)
154 if (!LoadLibxml()) return FALSE
;
157 stream
.Read(cheader
, 6);
158 stream
.SeekI(-6, wxFromCurrent
);
159 return strcmp(cheader
, "<?xml ") == 0;
164 bool wxXmlIOHandlerLibxml::CanSave()
171 static wxXmlProperty
*CreateWXProperty(xmlDocPtr doc
, xmlAttrPtr attr
)
173 if (attr
== NULL
) return NULL
;
176 gs_libxmlDLL
.xmlNodeListGetString(doc
, attr
->children
, 1);
177 wxXmlProperty
*prop
=
178 new wxXmlProperty(attr
->name
, val
, CreateWXProperty(doc
, attr
->next
));
179 (*gs_libxmlDLL
.xmlFree
)(val
);
185 static wxXmlNode
*CreateWXNode(xmlDocPtr doc
, wxXmlNode
*parent
, xmlNodePtr node
)
187 if (node
== NULL
) return NULL
;
189 wxXmlNode
*nd
= new wxXmlNode(parent
, (wxXmlNodeType
)node
->type
,
190 node
->name
, node
->content
,
191 CreateWXProperty(doc
, node
->properties
),
192 CreateWXNode(doc
, parent
, node
->next
));
193 CreateWXNode(doc
, nd
, node
->children
);
199 bool wxXmlIOHandlerLibxml::Load(wxInputStream
& stream
, wxXmlDocument
& doc
)
201 if (!LoadLibxml()) return FALSE
;
204 xmlParserCtxtPtr ctxt
;
209 res
= stream
.Read(buffer
, 4).LastRead();
213 gs_libxmlDLL
.xmlKeepBlanksDefault(0);
214 ctxt
= gs_libxmlDLL
.xmlCreatePushParserCtxt(NULL
, NULL
,
215 buffer
, res
, ""/*docname*/);
216 while ((res
= stream
.Read(buffer
, 1024).LastRead()) > 0)
217 if (gs_libxmlDLL
.xmlParseChunk(ctxt
, buffer
, res
, 0) != 0)
219 if (gs_libxmlDLL
.xmlParseChunk(ctxt
, buffer
, 0, 1) != 0) okay
= FALSE
;
221 gs_libxmlDLL
.xmlFreeParserCtxt(ctxt
);
223 doc
.SetVersion(dc
->version
);
224 doc
.SetEncoding(dc
->encoding
);
225 doc
.SetRoot(CreateWXNode(dc
, NULL
, gs_libxmlDLL
.xmlDocGetRootElement(dc
)));
227 gs_libxmlDLL
.xmlFreeDoc(dc
);
236 static void CreateLibxmlNode(xmlNodePtr node
, wxXmlNode
*wxnode
)
238 node
->type
= (xmlElementType
)wxnode
->GetType();
240 wxXmlProperty
*prop
= wxnode
->GetProperties();
243 gs_libxmlDLL
.xmlSetProp(node
, (xmlChar
*)prop
->GetName().mb_str(),
244 (xmlChar
*)prop
->GetValue().mb_str());
245 prop
= prop
->GetNext();
248 wxXmlNode
*child
= wxnode
->GetChildren();
250 xmlChar
*content
, *name
;
254 name
= (xmlChar
*)child
->GetName().mb_str();
255 if (!child
->GetContent()) content
= NULL
;
256 else content
= (xmlChar
*)child
->GetContent().mb_str();
257 if (child
->GetType() == wxXML_TEXT_NODE
)
258 gs_libxmlDLL
.xmlAddChild(node
, n
= gs_libxmlDLL
.xmlNewText(content
));
260 n
= gs_libxmlDLL
.xmlNewChild(node
, NULL
, name
, content
);
261 CreateLibxmlNode(n
, child
);
262 child
= child
->GetNext();
268 bool wxXmlIOHandlerLibxml::Save(wxOutputStream
& stream
, const wxXmlDocument
& doc
)
270 if (!LoadLibxml()) return FALSE
;
274 wxASSERT_MSG(doc
.GetRoot() != NULL
, _("Trying to save empty document!"));
276 gs_libxmlDLL
.xmlKeepBlanksDefault(0);
277 dc
= gs_libxmlDLL
.xmlNewDoc((xmlChar
*)doc
.GetVersion().mb_str());
279 gs_libxmlDLL
.xmlDocSetRootElement(dc
,
280 gs_libxmlDLL
.xmlNewDocNode(dc
, NULL
,
281 (xmlChar
*)doc
.GetRoot()->GetName().mb_str(), NULL
));
282 CreateLibxmlNode(gs_libxmlDLL
.xmlDocGetRootElement(dc
), doc
.GetRoot());
287 gs_libxmlDLL
.xmlDocDumpMemory(dc
, &buffer
, &size
);
288 gs_libxmlDLL
.xmlFreeDoc(dc
);
289 stream
.Write(buffer
, size
);
290 (*gs_libxmlDLL
.xmlFree
)(buffer
);
291 return stream
.LastWrite() == (unsigned)size
;
297 #include "wx/module.h"
299 class wxXmlLibxmlModule
: public wxModule
301 DECLARE_DYNAMIC_CLASS(wxXmlLibxmlModule
)
303 wxXmlLibxmlModule() {}
304 bool OnInit() { return TRUE
; }
305 void OnExit() { ReleaseLibxml(); }
308 IMPLEMENT_DYNAMIC_CLASS(wxXmlLibxmlModule
, wxModule
)