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
);
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
;
67 static bool gs_libxmlLoaded
= FALSE
;
68 static bool gs_libxmlLoadFailed
= FALSE
;
72 static void ReleaseLibxml()
76 wxLogDebug("Releasing libxml.so.2");
77 wxDllLoader::UnloadLibrary(gs_libxmlDLL
.Handle
);
79 gs_libxmlLoaded
= FALSE
;
80 gs_libxmlLoadFailed
= FALSE
;
84 static bool LoadLibxml()
86 if (gs_libxmlLoaded
) return TRUE
;
87 if (gs_libxmlLoadFailed
) return FALSE
;
88 gs_libxmlLoadFailed
= TRUE
;
90 wxLogDebug("Loading libxml.so.2...");
93 wxDllLoader::LoadLibrary(_T("libxml.so.2"), &gs_libxmlLoaded
);
96 if (!gs_libxmlLoaded
) return FALSE
;
98 #define LOAD_SYMBOL(sym) \
100 (type_##sym)wxDllLoader::GetSymbol(gs_libxmlDLL.Handle, _T(#sym)); \
101 if (!gs_libxmlDLL.sym) { ReleaseLibxml(); return FALSE; }
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
)
120 gs_libxmlLoadFailed
= FALSE
;
122 wxLogDebug("...succeed");
129 bool wxXmlIOHandlerLibxml::CanLoad(wxInputStream
& stream
)
131 if (!LoadLibxml()) return FALSE
;
134 stream
.Read(cheader
, 6);
135 stream
.SeekI(-6, wxFromCurrent
);
136 return strcmp(cheader
, "<?xml ") == 0;
141 bool wxXmlIOHandlerLibxml::CanSave()
148 static wxXmlProperty
*CreateWXProperty(xmlDocPtr doc
, xmlAttrPtr attr
)
150 if (attr
== NULL
) return NULL
;
153 gs_libxmlDLL
.xmlNodeListGetString(doc
, attr
->children
, 1);
154 wxXmlProperty
*prop
=
155 new wxXmlProperty(attr
->name
, val
, CreateWXProperty(doc
, attr
->next
));
162 static wxXmlNode
*CreateWXNode(xmlDocPtr doc
, wxXmlNode
*parent
, xmlNodePtr node
)
164 if (node
== NULL
) return NULL
;
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
);
176 bool wxXmlIOHandlerLibxml::Load(wxInputStream
& stream
, wxXmlDocument
& doc
)
178 if (!LoadLibxml()) return FALSE
;
181 xmlParserCtxtPtr ctxt
;
186 res
= stream
.Read(buffer
, 4).LastRead();
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)
195 if (gs_libxmlDLL
.xmlParseChunk(ctxt
, buffer
, 0, 1) != 0) okay
= FALSE
;
197 gs_libxmlDLL
.xmlFreeParserCtxt(ctxt
);
199 doc
.SetVersion(dc
->version
);
200 doc
.SetEncoding(dc
->encoding
);
201 doc
.SetRoot(CreateWXNode(dc
, NULL
, gs_libxmlDLL
.xmlDocGetRootElement(dc
)));
203 gs_libxmlDLL
.xmlFreeDoc(dc
);
212 static void CreateLibxmlNode(xmlNodePtr node
, wxXmlNode
*wxnode
)
214 node
->type
= (xmlElementType
)wxnode
->GetType();
216 wxXmlProperty
*prop
= wxnode
->GetProperties();
219 gs_libxmlDLL
.xmlSetProp(node
, (xmlChar
*)prop
->GetName().mb_str(),
220 (xmlChar
*)prop
->GetValue().mb_str());
221 prop
= prop
->GetNext();
224 wxXmlNode
*child
= wxnode
->GetChildren();
226 xmlChar
*content
, *name
;
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
));
236 n
= gs_libxmlDLL
.xmlNewChild(node
, NULL
, name
, content
);
237 CreateLibxmlNode(n
, child
);
238 child
= child
->GetNext();
244 bool wxXmlIOHandlerLibxml::Save(wxOutputStream
& stream
, const wxXmlDocument
& doc
)
246 if (!LoadLibxml()) return FALSE
;
250 wxASSERT_MSG(doc
.GetRoot() != NULL
, _("Trying to save empty document!"));
252 dc
= gs_libxmlDLL
.xmlNewDoc((xmlChar
*)doc
.GetVersion().mb_str());
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());
262 gs_libxmlDLL
.xmlDocDumpMemory(dc
, &buffer
, &size
);
263 gs_libxmlDLL
.xmlFreeDoc(dc
);
264 stream
.Write(buffer
, size
);
266 return stream
.LastWrite() == (unsigned)size
;
272 #include "wx/module.h"
274 class wxXmlLibxmlModule
: public wxModule
276 DECLARE_DYNAMIC_CLASS(wxXmlLibxmlModule
)
278 wxXmlLibxmlModule() {}
279 bool OnInit() { return TRUE
; }
280 void OnExit() { ReleaseLibxml(); }
283 IMPLEMENT_DYNAMIC_CLASS(wxXmlLibxmlModule
, wxModule
)