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 gs_libxmlDLL
.xmlCleanupParser();
125 wxDllLoader::UnloadLibrary(gs_libxmlDLL
.Handle
);
127 gs_libxmlLoaded
= FALSE
;
128 gs_libxmlLoadFailed
= FALSE
;
132 static bool LoadLibxml()
134 if (gs_libxmlLoaded
) return TRUE
;
135 if (gs_libxmlLoadFailed
) return FALSE
;
136 gs_libxmlLoadFailed
= TRUE
;
141 gs_libxmlDLL
.Handle
=
142 wxDllLoader::LoadLibrary(_T("wxlibxml.so.2"), &gs_libxmlLoaded
);
143 if (!gs_libxmlLoaded
) gs_libxmlDLL
.Handle
=
144 wxDllLoader::LoadLibrary(_T("libxml.so.2"), &gs_libxmlLoaded
);
147 gs_libxmlDLL
.Handle
=
148 wxDllLoader::LoadLibrary(_T("wxlibxml2.dll"), &gs_libxmlLoaded
);
149 if (!gs_libxmlLoaded
) gs_libxmlDLL
.Handle
=
150 wxDllLoader::LoadLibrary(_T("libxml2.dll"), &gs_libxmlLoaded
);
154 if (!gs_libxmlLoaded
)
156 wxLogError(_("Failed to load libxml shared library."));
160 #define LOAD_SYMBOL(sym) \
162 (type_##sym)wxDllLoader::GetSymbol(gs_libxmlDLL.Handle, _T(#sym)); \
163 if (!gs_libxmlDLL.sym) \
166 wxLogError(_("Failed to load libxml shared library.")); \
170 LOAD_SYMBOL(xmlCreatePushParserCtxt
)
171 LOAD_SYMBOL(xmlNewText
)
172 LOAD_SYMBOL(xmlSetProp
)
173 LOAD_SYMBOL(xmlParseChunk
)
174 LOAD_SYMBOL(xmlFreeParserCtxt
)
175 LOAD_SYMBOL(xmlNewDoc
)
176 LOAD_SYMBOL(xmlFreeDoc
)
177 LOAD_SYMBOL(xmlNewDocNode
)
178 LOAD_SYMBOL(xmlDocDumpMemory
)
179 LOAD_SYMBOL(xmlAddChild
)
180 LOAD_SYMBOL(xmlNewChild
)
181 LOAD_SYMBOL(xmlNodeListGetString
)
182 LOAD_SYMBOL(xmlDocGetRootElement
)
183 LOAD_SYMBOL(xmlDocSetRootElement
)
185 LOAD_SYMBOL(xmlKeepBlanksDefault
)
186 LOAD_SYMBOL(xmlInitParser
)
187 LOAD_SYMBOL(xmlCleanupParser
)
188 LOAD_SYMBOL(xmlDefaultSAXHandler
)
192 gs_libxmlLoadFailed
= FALSE
;
194 gs_libxmlDLL
.xmlInitParser();
195 memcpy(&gs_wxXmlSAXHandler
, gs_libxmlDLL
.xmlDefaultSAXHandler
,
196 sizeof(xmlSAXHandler
));
197 gs_wxXmlSAXHandler
.error
= wxXmlParserError
;
198 gs_wxXmlSAXHandler
.fatalError
= wxXmlParserError
;
199 gs_wxXmlSAXHandler
.warning
= wxXmlParserWarning
;
207 bool wxXmlIOHandlerLibxml::CanLoad(wxInputStream
& stream
)
209 if (!LoadLibxml()) return FALSE
;
212 stream
.Read(cheader
, 6);
213 stream
.SeekI(-6, wxFromCurrent
);
214 return strcmp(cheader
, "<?xml ") == 0;
219 bool wxXmlIOHandlerLibxml::CanSave()
226 static wxXmlProperty
*CreateWXProperty(xmlDocPtr doc
, xmlAttrPtr attr
)
228 if (attr
== NULL
) return NULL
;
231 gs_libxmlDLL
.xmlNodeListGetString(doc
, attr
->children
, 1);
232 wxXmlProperty
*prop
=
233 new wxXmlProperty(attr
->name
, val
, CreateWXProperty(doc
, attr
->next
));
234 (*gs_libxmlDLL
.xmlFree
)(val
);
240 static wxXmlNode
*CreateWXNode(xmlDocPtr doc
, wxXmlNode
*parent
, xmlNodePtr node
)
242 if (node
== NULL
) return NULL
;
244 wxXmlNode
*nd
= new wxXmlNode(parent
, (wxXmlNodeType
)node
->type
,
245 node
->name
, node
->content
,
246 CreateWXProperty(doc
, node
->properties
),
247 CreateWXNode(doc
, parent
, node
->next
));
248 CreateWXNode(doc
, nd
, node
->children
);
254 bool wxXmlIOHandlerLibxml::Load(wxInputStream
& stream
, wxXmlDocument
& doc
)
256 if (!LoadLibxml()) return FALSE
;
259 xmlParserCtxtPtr ctxt
;
264 res
= stream
.Read(buffer
, 4).LastRead();
268 gs_libxmlDLL
.xmlKeepBlanksDefault(0);
269 ctxt
= gs_libxmlDLL
.xmlCreatePushParserCtxt(&gs_wxXmlSAXHandler
,
270 NULL
, buffer
, res
, ""/*docname*/);
271 while ((res
= stream
.Read(buffer
, 1024).LastRead()) > 0)
272 if (gs_libxmlDLL
.xmlParseChunk(ctxt
, buffer
, res
, 0) != 0)
274 if (gs_libxmlDLL
.xmlParseChunk(ctxt
, buffer
, 0, 1) != 0) okay
= FALSE
;
276 gs_libxmlDLL
.xmlFreeParserCtxt(ctxt
);
278 doc
.SetVersion(dc
->version
);
279 doc
.SetEncoding(dc
->encoding
);
280 doc
.SetRoot(CreateWXNode(dc
, NULL
, gs_libxmlDLL
.xmlDocGetRootElement(dc
)));
282 gs_libxmlDLL
.xmlFreeDoc(dc
);
291 static void CreateLibxmlNode(xmlNodePtr node
, wxXmlNode
*wxnode
)
293 node
->type
= (xmlElementType
)wxnode
->GetType();
295 wxXmlProperty
*prop
= wxnode
->GetProperties();
298 gs_libxmlDLL
.xmlSetProp(node
, (xmlChar
*)prop
->GetName().mb_str(),
299 (xmlChar
*)prop
->GetValue().mb_str());
300 prop
= prop
->GetNext();
303 wxXmlNode
*child
= wxnode
->GetChildren();
305 xmlChar
*content
, *name
;
309 name
= (xmlChar
*)child
->GetName().mb_str();
310 if (!child
->GetContent()) content
= NULL
;
311 else content
= (xmlChar
*)child
->GetContent().mb_str();
312 if (child
->GetType() == wxXML_TEXT_NODE
)
313 gs_libxmlDLL
.xmlAddChild(node
, n
= gs_libxmlDLL
.xmlNewText(content
));
315 n
= gs_libxmlDLL
.xmlNewChild(node
, NULL
, name
, content
);
316 CreateLibxmlNode(n
, child
);
317 child
= child
->GetNext();
323 bool wxXmlIOHandlerLibxml::Save(wxOutputStream
& stream
, const wxXmlDocument
& doc
)
325 if (!LoadLibxml()) return FALSE
;
329 wxASSERT_MSG(doc
.GetRoot() != NULL
, _("Trying to save empty document!"));
331 gs_libxmlDLL
.xmlKeepBlanksDefault(0);
332 dc
= gs_libxmlDLL
.xmlNewDoc((xmlChar
*)doc
.GetVersion().mb_str());
334 gs_libxmlDLL
.xmlDocSetRootElement(dc
,
335 gs_libxmlDLL
.xmlNewDocNode(dc
, NULL
,
336 (xmlChar
*)doc
.GetRoot()->GetName().mb_str(), NULL
));
337 CreateLibxmlNode(gs_libxmlDLL
.xmlDocGetRootElement(dc
), doc
.GetRoot());
342 gs_libxmlDLL
.xmlDocDumpMemory(dc
, &buffer
, &size
);
343 gs_libxmlDLL
.xmlFreeDoc(dc
);
344 stream
.Write(buffer
, size
);
345 (*gs_libxmlDLL
.xmlFree
)(buffer
);
346 return stream
.LastWrite() == (unsigned)size
;
352 #include "wx/module.h"
354 class wxXmlLibxmlModule
: public wxModule
356 DECLARE_DYNAMIC_CLASS(wxXmlLibxmlModule
)
358 wxXmlLibxmlModule() {}
359 bool OnInit() { return TRUE
; }
360 void OnExit() { ReleaseLibxml(); }
363 IMPLEMENT_DYNAMIC_CLASS(wxXmlLibxmlModule
, wxModule
)