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>
29 #include <libxml/SAX.h>
32 // wxWindows SAX handlers for bugs reporting:
34 static void wxXmlParserError(void *ctx
, const char *msg
, ...)
37 xmlParserCtxtPtr ctxt
= (xmlParserCtxtPtr
) ctx
;
39 text
.Printf( _("XML parser error at line %d: "), ctxt
->input
->line
);
43 tmp
.PrintfV( msg
, args
);
46 wxLogError( text
.c_str() );
49 static void wxXmlParserWarning(void *ctx
, const char *msg
, ...)
52 xmlParserCtxtPtr ctxt
= (xmlParserCtxtPtr
) ctx
;
54 text
.Printf( _("XML parser warning at line %d: "), ctxt
->input
->line
);
58 tmp
.PrintfV( msg
, args
);
61 wxLogWarning( text
.c_str() );
64 static xmlSAXHandler gs_wxXmlSAXHandler
;
68 // dynamically loaded functions from libxml:
69 typedef xmlParserCtxtPtr (*type_xmlCreatePushParserCtxt
)
70 (xmlSAXHandlerPtr sax
, void *, const char *, int, const char *);
71 typedef xmlNodePtr (*type_xmlNewText
)(const xmlChar
*);
72 typedef xmlAttrPtr (*type_xmlSetProp
)(xmlNodePtr
, const xmlChar
*, const xmlChar
*);
73 typedef int (*type_xmlParseChunk
)(xmlParserCtxtPtr
, const char *, int, int);
74 typedef void (*type_xmlFreeParserCtxt
)(xmlParserCtxtPtr
);
75 typedef xmlDocPtr (*type_xmlNewDoc
)(const xmlChar
*);
76 typedef void (*type_xmlFreeDoc
)(xmlDocPtr
);
77 typedef xmlNodePtr (*type_xmlNewDocNode
)(xmlDocPtr
, xmlNsPtr
, const xmlChar
*, const xmlChar
*);
78 typedef void (*type_xmlDocDumpMemory
)(xmlDocPtr
, xmlChar
**, int *);
79 typedef xmlNodePtr (*type_xmlAddChild
)(xmlNodePtr
, xmlNodePtr
);
80 typedef xmlNodePtr (*type_xmlNewChild
)(xmlNodePtr
, xmlNsPtr
, const xmlChar
*, const xmlChar
*);
81 typedef xmlChar
* (*type_xmlNodeListGetString
)(xmlDocPtr
, xmlNodePtr
, int);
82 typedef xmlNodePtr (*type_xmlDocGetRootElement
)(xmlDocPtr
);
83 typedef xmlNodePtr (*type_xmlDocSetRootElement
)(xmlDocPtr doc
, xmlNodePtr root
);
84 typedef void (*(*type_xmlFree
))(void *);
85 typedef int (*type_xmlKeepBlanksDefault
)(int);
86 typedef void (*type_xmlInitParser
)(void);
87 typedef void (*type_xmlCleanupParser
)(void);
88 typedef xmlSAXHandler
*type_xmlDefaultSAXHandler
;
94 type_xmlCreatePushParserCtxt xmlCreatePushParserCtxt
;
95 type_xmlNewText xmlNewText
;
96 type_xmlSetProp xmlSetProp
;
97 type_xmlParseChunk xmlParseChunk
;
98 type_xmlFreeParserCtxt xmlFreeParserCtxt
;
99 type_xmlNewDoc xmlNewDoc
;
100 type_xmlFreeDoc xmlFreeDoc
;
101 type_xmlNewDocNode xmlNewDocNode
;
102 type_xmlDocDumpMemory xmlDocDumpMemory
;
103 type_xmlAddChild xmlAddChild
;
104 type_xmlNewChild xmlNewChild
;
105 type_xmlNodeListGetString xmlNodeListGetString
;
106 type_xmlDocGetRootElement xmlDocGetRootElement
;
107 type_xmlDocSetRootElement xmlDocSetRootElement
;
108 type_xmlFree xmlFree
;
109 type_xmlKeepBlanksDefault xmlKeepBlanksDefault
;
110 type_xmlInitParser xmlInitParser
;
111 type_xmlCleanupParser xmlCleanupParser
;
112 type_xmlDefaultSAXHandler xmlDefaultSAXHandler
;
115 static bool gs_libxmlLoaded
= FALSE
;
116 static bool gs_libxmlLoadFailed
= FALSE
;
120 static void ReleaseLibxml()
124 // Check for CleanupParser ..may have failed before initialised
125 // during LOAD_SYMBOL in LoadLibxml()
126 if (gs_libxmlDLL
.xmlCleanupParser
)
127 gs_libxmlDLL
.xmlCleanupParser();
128 wxDllLoader::UnloadLibrary(gs_libxmlDLL
.Handle
);
130 gs_libxmlLoaded
= FALSE
;
131 gs_libxmlLoadFailed
= FALSE
;
135 static bool LoadLibxml()
137 if (gs_libxmlLoaded
) return TRUE
;
138 if (gs_libxmlLoadFailed
) return FALSE
;
139 gs_libxmlLoadFailed
= TRUE
;
144 gs_libxmlDLL
.Handle
=
145 wxDllLoader::LoadLibrary(wxT("wxlibxml.so.2"), &gs_libxmlLoaded
);
146 if (!gs_libxmlLoaded
) gs_libxmlDLL
.Handle
=
147 wxDllLoader::LoadLibrary(wxT("libxml.so.2"), &gs_libxmlLoaded
);
150 gs_libxmlDLL
.Handle
=
151 wxDllLoader::LoadLibrary(wxT("wxlibxml2.dll"), &gs_libxmlLoaded
);
152 if (!gs_libxmlLoaded
) gs_libxmlDLL
.Handle
=
153 wxDllLoader::LoadLibrary(wxT("libxml2.dll"), &gs_libxmlLoaded
);
157 if (!gs_libxmlLoaded
)
159 wxLogError(_("Failed to load libxml shared library."));
163 #define LOAD_SYMBOL(sym) \
165 (type_##sym)wxDllLoader::GetSymbol(gs_libxmlDLL.Handle, wxT(#sym)); \
166 if (!gs_libxmlDLL.sym) \
169 wxLogError(_("Failed to load libxml shared library.")); \
173 LOAD_SYMBOL(xmlCreatePushParserCtxt
)
174 LOAD_SYMBOL(xmlNewText
)
175 LOAD_SYMBOL(xmlSetProp
)
176 LOAD_SYMBOL(xmlParseChunk
)
177 LOAD_SYMBOL(xmlFreeParserCtxt
)
178 LOAD_SYMBOL(xmlNewDoc
)
179 LOAD_SYMBOL(xmlFreeDoc
)
180 LOAD_SYMBOL(xmlNewDocNode
)
181 LOAD_SYMBOL(xmlDocDumpMemory
)
182 LOAD_SYMBOL(xmlAddChild
)
183 LOAD_SYMBOL(xmlNewChild
)
184 LOAD_SYMBOL(xmlNodeListGetString
)
185 LOAD_SYMBOL(xmlDocGetRootElement
)
186 LOAD_SYMBOL(xmlDocSetRootElement
)
188 LOAD_SYMBOL(xmlKeepBlanksDefault
)
189 LOAD_SYMBOL(xmlInitParser
)
190 LOAD_SYMBOL(xmlCleanupParser
)
191 LOAD_SYMBOL(xmlDefaultSAXHandler
)
195 gs_libxmlLoadFailed
= FALSE
;
197 gs_libxmlDLL
.xmlInitParser();
198 memcpy(&gs_wxXmlSAXHandler
, gs_libxmlDLL
.xmlDefaultSAXHandler
,
199 sizeof(xmlSAXHandler
));
200 gs_wxXmlSAXHandler
.error
= wxXmlParserError
;
201 gs_wxXmlSAXHandler
.fatalError
= wxXmlParserError
;
202 gs_wxXmlSAXHandler
.warning
= wxXmlParserWarning
;
210 bool wxXmlIOHandlerLibxml::CanLoad(wxInputStream
& stream
)
212 if (!LoadLibxml()) return FALSE
;
215 stream
.Read(cheader
, 6);
216 stream
.SeekI(-6, wxFromCurrent
);
217 return strcmp(cheader
, "<?xml ") == 0;
222 bool wxXmlIOHandlerLibxml::CanSave()
229 static wxXmlProperty
*CreateWXProperty(xmlDocPtr doc
, xmlAttrPtr attr
)
231 if (attr
== NULL
) return NULL
;
234 gs_libxmlDLL
.xmlNodeListGetString(doc
, attr
->children
, 1);
235 wxXmlProperty
*prop
=
236 new wxXmlProperty(attr
->name
, val
, CreateWXProperty(doc
, attr
->next
));
237 (*gs_libxmlDLL
.xmlFree
)(val
);
243 static wxXmlNode
*CreateWXNode(xmlDocPtr doc
, wxXmlNode
*parent
, xmlNodePtr node
)
245 if (node
== NULL
) return NULL
;
247 wxXmlNode
*nd
= new wxXmlNode(parent
, (wxXmlNodeType
)node
->type
,
248 node
->name
, node
->content
,
249 CreateWXProperty(doc
, node
->properties
),
250 CreateWXNode(doc
, parent
, node
->next
));
251 CreateWXNode(doc
, nd
, node
->children
);
257 bool wxXmlIOHandlerLibxml::Load(wxInputStream
& stream
, wxXmlDocument
& doc
)
259 if (!LoadLibxml()) return FALSE
;
262 xmlParserCtxtPtr ctxt
;
267 res
= stream
.Read(buffer
, 4).LastRead();
271 gs_libxmlDLL
.xmlKeepBlanksDefault(0);
272 ctxt
= gs_libxmlDLL
.xmlCreatePushParserCtxt(&gs_wxXmlSAXHandler
,
273 NULL
, buffer
, res
, ""/*docname*/);
274 while ((res
= stream
.Read(buffer
, 1024).LastRead()) > 0)
275 if (gs_libxmlDLL
.xmlParseChunk(ctxt
, buffer
, res
, 0) != 0)
277 if (gs_libxmlDLL
.xmlParseChunk(ctxt
, buffer
, 0, 1) != 0) okay
= FALSE
;
279 gs_libxmlDLL
.xmlFreeParserCtxt(ctxt
);
281 doc
.SetVersion(dc
->version
);
282 doc
.SetEncoding(dc
->encoding
);
283 doc
.SetRoot(CreateWXNode(dc
, NULL
, gs_libxmlDLL
.xmlDocGetRootElement(dc
)));
285 gs_libxmlDLL
.xmlFreeDoc(dc
);
294 static void CreateLibxmlNode(xmlNodePtr node
, wxXmlNode
*wxnode
)
296 node
->type
= (xmlElementType
)wxnode
->GetType();
298 wxXmlProperty
*prop
= wxnode
->GetProperties();
301 gs_libxmlDLL
.xmlSetProp(node
, (xmlChar
*)prop
->GetName().mb_str(),
302 (xmlChar
*)prop
->GetValue().mb_str());
303 prop
= prop
->GetNext();
306 wxXmlNode
*child
= wxnode
->GetChildren();
308 xmlChar
*content
, *name
;
312 name
= (xmlChar
*)child
->GetName().mb_str();
313 if (!child
->GetContent()) content
= NULL
;
314 else content
= (xmlChar
*)child
->GetContent().mb_str();
315 if (child
->GetType() == wxXML_TEXT_NODE
)
316 gs_libxmlDLL
.xmlAddChild(node
, n
= gs_libxmlDLL
.xmlNewText(content
));
318 n
= gs_libxmlDLL
.xmlNewChild(node
, NULL
, name
, content
);
319 CreateLibxmlNode(n
, child
);
320 child
= child
->GetNext();
326 bool wxXmlIOHandlerLibxml::Save(wxOutputStream
& stream
, const wxXmlDocument
& doc
)
328 if (!LoadLibxml()) return FALSE
;
332 wxASSERT_MSG(doc
.GetRoot() != NULL
, _("Trying to save empty document!"));
334 gs_libxmlDLL
.xmlKeepBlanksDefault(0);
335 dc
= gs_libxmlDLL
.xmlNewDoc((xmlChar
*)doc
.GetVersion().mb_str());
337 gs_libxmlDLL
.xmlDocSetRootElement(dc
,
338 gs_libxmlDLL
.xmlNewDocNode(dc
, NULL
,
339 (xmlChar
*)doc
.GetRoot()->GetName().mb_str(), NULL
));
340 CreateLibxmlNode(gs_libxmlDLL
.xmlDocGetRootElement(dc
), doc
.GetRoot());
345 gs_libxmlDLL
.xmlDocDumpMemory(dc
, &buffer
, &size
);
346 gs_libxmlDLL
.xmlFreeDoc(dc
);
347 stream
.Write(buffer
, size
);
348 (*gs_libxmlDLL
.xmlFree
)(buffer
);
349 return stream
.LastWrite() == (unsigned)size
;
355 #include "wx/module.h"
357 class wxXmlLibxmlModule
: public wxModule
359 DECLARE_DYNAMIC_CLASS(wxXmlLibxmlModule
)
361 wxXmlLibxmlModule() {}
362 bool OnInit() { return TRUE
; }
363 void OnExit() { ReleaseLibxml(); }
366 IMPLEMENT_DYNAMIC_CLASS(wxXmlLibxmlModule
, wxModule
)