]> git.saurik.com Git - wxWidgets.git/blobdiff - contrib/src/xml/xmlpars.cpp
added XML resources library
[wxWidgets.git] / contrib / src / xml / xmlpars.cpp
diff --git a/contrib/src/xml/xmlpars.cpp b/contrib/src/xml/xmlpars.cpp
new file mode 100644 (file)
index 0000000..797c76d
--- /dev/null
@@ -0,0 +1,283 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        xmlpars.cpp
+// Purpose:     wxXmlDocument - XML parser 
+// Author:      Vaclav Slavik
+// Created:     2000/03/05
+// RCS-ID:      $Id$
+// Copyright:   (c) 2000 Vaclav Slavik
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+#ifdef __GNUG__
+// nothing - already in xml.cpp
+#endif
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+    #pragma hdrstop
+#endif
+
+#include "wx/wfstream.h"
+#include "wx/intl.h"
+#include "wx/log.h"
+#include "wx/dynlib.h"
+#include "wx/xml/xmlio.h"
+
+#include <libxml/parser.h>
+
+// dynamically loaded functions from libxml:
+typedef xmlParserCtxtPtr (*type_xmlCreatePushParserCtxt)
+             (xmlSAXHandlerPtr sax, void *, const char *, int, const char *);
+typedef xmlNodePtr (*type_xmlNewText)(const xmlChar *);
+typedef xmlAttrPtr (*type_xmlSetProp)(xmlNodePtr, const xmlChar *, const xmlChar *);
+typedef int (*type_xmlParseChunk)(xmlParserCtxtPtr, const char *, int, int);
+typedef void (*type_xmlFreeParserCtxt)(xmlParserCtxtPtr);
+typedef xmlDocPtr (*type_xmlNewDoc)(const xmlChar *);
+typedef void (*type_xmlFreeDoc)(xmlDocPtr);
+typedef xmlNodePtr (*type_xmlNewDocNode)(xmlDocPtr, xmlNsPtr, const xmlChar *, const xmlChar *);
+typedef void (*type_xmlDocDumpMemory)(xmlDocPtr, xmlChar**, int *);
+typedef xmlNodePtr (*type_xmlAddChild)(xmlNodePtr, xmlNodePtr);
+typedef xmlNodePtr (*type_xmlNewChild)(xmlNodePtr, xmlNsPtr, const xmlChar *, const xmlChar *);
+typedef xmlChar * (*type_xmlNodeListGetString)(xmlDocPtr, xmlNodePtr, int);
+typedef xmlNodePtr (*type_xmlDocGetRootElement)(xmlDocPtr);
+typedef xmlNodePtr (*type_xmlDocSetRootElement)(xmlDocPtr doc, xmlNodePtr root);
+
+static struct
+{
+    wxDllType Handle;
+
+    type_xmlCreatePushParserCtxt xmlCreatePushParserCtxt;
+    type_xmlNewText xmlNewText;
+    type_xmlSetProp xmlSetProp;
+    type_xmlParseChunk xmlParseChunk;
+    type_xmlFreeParserCtxt xmlFreeParserCtxt;
+    type_xmlNewDoc xmlNewDoc;
+    type_xmlFreeDoc xmlFreeDoc;
+    type_xmlNewDocNode xmlNewDocNode;
+    type_xmlDocDumpMemory xmlDocDumpMemory;
+    type_xmlAddChild xmlAddChild;
+    type_xmlNewChild xmlNewChild;
+    type_xmlNodeListGetString xmlNodeListGetString;
+    type_xmlDocGetRootElement xmlDocGetRootElement;
+    type_xmlDocSetRootElement xmlDocSetRootElement;
+} gs_libxmlDLL;
+
+static bool gs_libxmlLoaded = FALSE;
+static bool gs_libxmlLoadFailed = FALSE;
+
+
+
+static void ReleaseLibxml()
+{
+    if (gs_libxmlLoaded)
+    {
+        wxLogDebug("Releasing libxml.so.2");
+        wxDllLoader::UnloadLibrary(gs_libxmlDLL.Handle);
+    }
+    gs_libxmlLoaded = FALSE;
+    gs_libxmlLoadFailed = FALSE;
+}
+
+
+static bool LoadLibxml()
+{
+    if (gs_libxmlLoaded) return TRUE;
+    if (gs_libxmlLoadFailed) return FALSE;
+    gs_libxmlLoadFailed = TRUE;
+
+    wxLogDebug("Loading libxml.so.2...");
+#ifdef __UNIX__
+    gs_libxmlDLL.Handle = 
+        wxDllLoader::LoadLibrary(_T("libxml.so.2"), &gs_libxmlLoaded);
+#endif
+    
+    if (!gs_libxmlLoaded) return FALSE;
+    
+#define LOAD_SYMBOL(sym) \
+    gs_libxmlDLL.sym = \
+        (type_##sym)wxDllLoader::GetSymbol(gs_libxmlDLL.Handle, _T(#sym)); \
+    if (!gs_libxmlDLL.sym) { ReleaseLibxml(); return FALSE; }
+
+    LOAD_SYMBOL(xmlCreatePushParserCtxt)
+    LOAD_SYMBOL(xmlNewText)
+    LOAD_SYMBOL(xmlSetProp)
+    LOAD_SYMBOL(xmlParseChunk)
+    LOAD_SYMBOL(xmlFreeParserCtxt)
+    LOAD_SYMBOL(xmlNewDoc)
+    LOAD_SYMBOL(xmlFreeDoc)
+    LOAD_SYMBOL(xmlNewDocNode)
+    LOAD_SYMBOL(xmlDocDumpMemory)
+    LOAD_SYMBOL(xmlAddChild)
+    LOAD_SYMBOL(xmlNewChild)
+    LOAD_SYMBOL(xmlNodeListGetString)
+    LOAD_SYMBOL(xmlDocGetRootElement)
+    LOAD_SYMBOL(xmlDocSetRootElement)
+
+#undef LOAD_SYMBOL    
+
+    gs_libxmlLoadFailed = FALSE;
+
+    wxLogDebug("...succeed");
+    return TRUE;
+}
+
+
+
+
+bool wxXmlIOHandlerLibxml::CanLoad(wxInputStream& stream)
+{
+    if (!LoadLibxml()) return FALSE;
+    char cheader[7];
+    cheader[6] = 0;
+    stream.Read(cheader, 6);
+    stream.SeekI(-6, wxFromCurrent);
+    return strcmp(cheader, "<?xml ") == 0;
+}
+
+
+
+bool wxXmlIOHandlerLibxml::CanSave()
+{
+    return LoadLibxml();
+}
+
+
+
+static wxXmlProperty *CreateWXProperty(xmlDocPtr doc, xmlAttrPtr attr)
+{
+    if (attr == NULL) return NULL;
+    
+    unsigned char *val = 
+        gs_libxmlDLL.xmlNodeListGetString(doc, attr->children, 1);
+    wxXmlProperty *prop = 
+        new wxXmlProperty(attr->name, val, CreateWXProperty(doc, attr->next));
+    free(val);
+    return prop;
+}
+
+
+
+static wxXmlNode *CreateWXNode(xmlDocPtr doc, wxXmlNode *parent, xmlNodePtr node)
+{
+    if (node == NULL) return NULL;
+    
+    wxXmlNode *nd = new wxXmlNode(parent, (wxXmlNodeType)node->type,
+                          node->name, node->content, 
+                          CreateWXProperty(doc, node->properties),
+                          CreateWXNode(doc, parent, node->next));
+    CreateWXNode(doc, nd, node->children);
+    return nd;
+}
+
+
+
+bool wxXmlIOHandlerLibxml::Load(wxInputStream& stream, wxXmlDocument& doc)
+{
+    if (!LoadLibxml()) return FALSE;
+
+    xmlDocPtr dc;
+    xmlParserCtxtPtr ctxt;
+    
+    char buffer[1024];
+    int  res;
+    
+    res = stream.Read(buffer, 4).LastRead();
+    if (res > 0)
+    {
+        bool okay = TRUE;
+        ctxt = gs_libxmlDLL.xmlCreatePushParserCtxt(NULL, NULL, 
+                                               buffer, res, ""/*docname*/);
+        while ((res = stream.Read(buffer, 1024).LastRead()) > 0) 
+            if (gs_libxmlDLL.xmlParseChunk(ctxt, buffer, res, 0) != 0) 
+               okay = FALSE;
+        if (gs_libxmlDLL.xmlParseChunk(ctxt, buffer, 0, 1) != 0) okay = FALSE;
+        dc = ctxt->myDoc;
+        gs_libxmlDLL.xmlFreeParserCtxt(ctxt);
+
+        doc.SetVersion(dc->version);
+        doc.SetEncoding(dc->encoding);
+        doc.SetRoot(CreateWXNode(dc, NULL, gs_libxmlDLL.xmlDocGetRootElement(dc)));
+
+        gs_libxmlDLL.xmlFreeDoc(dc);
+        
+        return okay;
+    }
+    else return FALSE;
+}
+
+
+
+static void CreateLibxmlNode(xmlNodePtr node, wxXmlNode *wxnode)
+{
+    node->type = (xmlElementType)wxnode->GetType();
+
+    wxXmlProperty *prop = wxnode->GetProperties();  
+    while (prop)
+    {
+        gs_libxmlDLL.xmlSetProp(node, (xmlChar*)prop->GetName().mb_str(), 
+                         (xmlChar*)prop->GetValue().mb_str());
+        prop = prop->GetNext();
+    }
+    
+    wxXmlNode *child = wxnode->GetChildren();
+    xmlNodePtr n;
+    xmlChar *content, *name;
+    
+    while (child)
+    {
+        name = (xmlChar*)child->GetName().mb_str();
+        if (!child->GetContent()) content = NULL;
+        else content = (xmlChar*)child->GetContent().mb_str();
+        if (child->GetType() == wxXML_TEXT_NODE)
+            gs_libxmlDLL.xmlAddChild(node, n = gs_libxmlDLL.xmlNewText(content));
+        else
+            n = gs_libxmlDLL.xmlNewChild(node, NULL, name, content);
+        CreateLibxmlNode(n, child);
+        child = child->GetNext();
+    }
+}
+
+
+
+bool wxXmlIOHandlerLibxml::Save(wxOutputStream& stream, const wxXmlDocument& doc)
+{
+    if (!LoadLibxml()) return FALSE;
+
+    xmlDocPtr dc;
+
+    wxASSERT_MSG(doc.GetRoot() != NULL, _("Trying to save empty document!"));
+    
+    dc = gs_libxmlDLL.xmlNewDoc((xmlChar*)doc.GetVersion().mb_str());
+    
+    gs_libxmlDLL.xmlDocSetRootElement(dc, 
+         gs_libxmlDLL.xmlNewDocNode(dc, NULL, 
+                        (xmlChar*)doc.GetRoot()->GetName().mb_str(), NULL));
+    CreateLibxmlNode(gs_libxmlDLL.xmlDocGetRootElement(dc), doc.GetRoot());
+
+    xmlChar *buffer;
+    int size;
+
+    gs_libxmlDLL.xmlDocDumpMemory(dc, &buffer, &size);
+    gs_libxmlDLL.xmlFreeDoc(dc);
+    stream.Write(buffer, size);
+    free(buffer);
+    return stream.LastWrite() == (unsigned)size;
+}
+
+
+
+
+#include "wx/module.h"
+
+class wxXmlLibxmlModule: public wxModule
+{
+    DECLARE_DYNAMIC_CLASS(wxXmlLibxmlModule)
+    public:
+        wxXmlLibxmlModule() {}
+        bool OnInit() { return TRUE; }
+        void OnExit() { ReleaseLibxml(); }
+};
+
+IMPLEMENT_DYNAMIC_CLASS(wxXmlLibxmlModule, wxModule)