summaryrefslogtreecommitdiff
path: root/src/base/XMLHelper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/base/XMLHelper.cpp')
-rw-r--r--src/base/XMLHelper.cpp225
1 files changed, 225 insertions, 0 deletions
diff --git a/src/base/XMLHelper.cpp b/src/base/XMLHelper.cpp
new file mode 100644
index 0000000..6f362e8
--- /dev/null
+++ b/src/base/XMLHelper.cpp
@@ -0,0 +1,225 @@
+//
+// libavg - Media Playback Engine.
+// Copyright (C) 2003-2014 Ulrich von Zadow
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// Current versions can be found at www.libavg.de
+//
+
+#include "XMLHelper.h"
+#include "Exception.h"
+#include "Logger.h"
+
+#include <libxml/parserInternals.h>
+#include <cstring>
+#include <iostream>
+
+using namespace std;
+
+namespace avg {
+
+string getXmlChildrenAsString(const xmlDocPtr xmlDoc, const xmlNodePtr& xmlNode)
+{
+ string s;
+ xmlBufferPtr pBuffer = xmlBufferCreate();
+ xmlNodeDump(pBuffer, xmlDoc, xmlNode, 0, 0);
+
+ s = (const char *)xmlBufferContent(pBuffer);
+ size_t StartPos = s.find('>')+1;
+ size_t EndPos = s.rfind('<')-1;
+ if (StartPos > EndPos) {
+ s = "";
+ } else {
+ s = s.substr(StartPos, EndPos-StartPos+1);
+ }
+ xmlBufferFree(pBuffer);
+ return s;
+}
+
+static xmlExternalEntityLoader DefaultLoaderProc = 0;
+static std::map<string, string> g_DTDMap;
+
+xmlParserInputPtr
+DTDExternalEntityLoader(const char *pURL, const char *pID, xmlParserCtxtPtr ctxt)
+{
+ xmlParserInputPtr ret;
+ /* lookup for the fileID depending on ID */
+ std::map<string, string>::iterator it = g_DTDMap.find(pURL);
+
+ if (it != g_DTDMap.end()) {
+ ret = xmlNewStringInputStream(ctxt, (const xmlChar *)(it->second.c_str()));
+ return(ret);
+ } else {
+ ret = DefaultLoaderProc(pURL, pID, ctxt);
+ return(ret);
+ }
+}
+
+void registerDTDEntityLoader(const string& sID, const string& sDTD)
+{
+ g_DTDMap[sID] = sDTD;
+ if (!DefaultLoaderProc) {
+ DefaultLoaderProc = xmlGetExternalEntityLoader();
+ }
+ xmlSetExternalEntityLoader(DTDExternalEntityLoader);
+}
+
+
+XMLParser::XMLParser()
+ : m_SchemaParserCtxt(0),
+ m_Schema(0),
+ m_SchemaValidCtxt(0),
+ m_DTD(0),
+ m_DTDValidCtxt(0),
+ m_Doc(0)
+{
+ xmlPedanticParserDefault(1);
+ xmlSetGenericErrorFunc(this, errorOutputFunc);
+ xmlDoValidityCheckingDefaultValue = 0;
+}
+
+XMLParser::~XMLParser()
+{
+ if (m_Schema) {
+ xmlSchemaFree(m_Schema);
+ }
+ if (m_SchemaParserCtxt) {
+ xmlSchemaFreeParserCtxt(m_SchemaParserCtxt);
+ }
+ if (m_SchemaValidCtxt) {
+ xmlSchemaFreeValidCtxt(m_SchemaValidCtxt);
+ }
+ if (m_DTD) {
+ xmlFreeDtd(m_DTD);
+ }
+ if (m_DTDValidCtxt) {
+ xmlFreeValidCtxt(m_DTDValidCtxt);
+ }
+ if (m_Doc) {
+ xmlFreeDoc(m_Doc);
+ }
+ xmlSetGenericErrorFunc(0, 0);
+}
+
+void XMLParser::setSchema(const string& sSchema, const string& sSchemaName)
+{
+ AVG_ASSERT(!m_SchemaParserCtxt);
+ AVG_ASSERT(!m_Schema);
+ AVG_ASSERT(!m_SchemaValidCtxt);
+ AVG_ASSERT(!m_DTD);
+ AVG_ASSERT(!m_DTDValidCtxt);
+
+ m_SchemaParserCtxt = xmlSchemaNewMemParserCtxt(sSchema.c_str(), sSchema.length());
+ checkError(!m_SchemaParserCtxt, sSchemaName);
+
+ m_Schema = xmlSchemaParse(m_SchemaParserCtxt);
+ checkError(!m_Schema, sSchemaName);
+
+ m_SchemaValidCtxt = xmlSchemaNewValidCtxt(m_Schema);
+ checkError(!m_SchemaValidCtxt, sSchemaName);
+}
+
+void XMLParser::setDTD(const std::string& sDTD, const std::string& sDTDName)
+{
+ AVG_ASSERT(!m_SchemaParserCtxt);
+ AVG_ASSERT(!m_Schema);
+ AVG_ASSERT(!m_SchemaValidCtxt);
+ AVG_ASSERT(!m_DTD);
+ AVG_ASSERT(!m_DTDValidCtxt);
+
+ registerDTDEntityLoader("memory.dtd", sDTD.c_str());
+ string sDTDFName = "memory.dtd";
+ m_DTD = xmlParseDTD(NULL, (const xmlChar*) sDTDFName.c_str());
+ checkError(!m_DTD, sDTDName);
+
+ m_DTDValidCtxt = xmlNewValidCtxt();
+ checkError(!m_DTDValidCtxt, sDTDName);
+ m_DTDValidCtxt->error = xmlParserValidityError;
+ m_DTDValidCtxt->warning = xmlParserValidityWarning;
+}
+
+void XMLParser::parse(const string& sXML, const string& sXMLName)
+{
+ if (m_Doc) {
+ xmlFreeDoc(m_Doc);
+ }
+ m_Doc = xmlParseMemory(sXML.c_str(), int(sXML.length()));
+ checkError(!m_Doc, sXMLName);
+
+ bool bOK = true;
+ if (m_SchemaValidCtxt) {
+ int err = xmlSchemaValidateDoc(m_SchemaValidCtxt, m_Doc);
+ AVG_ASSERT(err != -1);
+ bOK = (err == 0);
+ }
+ if (m_DTD) {
+ int err = xmlValidateDtd(m_DTDValidCtxt, m_Doc, m_DTD);
+ bOK = (err != 0);
+ }
+ if (!bOK) {
+ xmlFreeDoc(m_Doc);
+ m_Doc = 0;
+ checkError(true, sXMLName);
+ }
+}
+
+xmlDocPtr XMLParser::getDoc()
+{
+ AVG_ASSERT(m_Doc);
+ return m_Doc;
+}
+
+xmlNodePtr XMLParser::getRootNode()
+{
+ AVG_ASSERT(m_Doc);
+ return xmlDocGetRootElement(m_Doc);
+}
+
+void XMLParser::errorOutputFunc(void * ctx, const char * msg, ...)
+{
+ va_list args;
+ va_start(args, msg);
+ ((XMLParser*)ctx)->internalErrorHandler(msg, args);
+ va_end(args);
+}
+
+void XMLParser::internalErrorHandler(const char * msg, va_list args)
+{
+ char psz[1024];
+ vsnprintf(psz, 1024, msg, args);
+ m_sError += psz;
+}
+
+void XMLParser::checkError(bool bError, const string& sXMLName)
+{
+ if (bError) {
+ string sError = "Error parsing "+sXMLName+".\n";
+ sError += m_sError;
+ m_sError = "";
+ throw (Exception(AVG_ERR_XML_PARSE, sError));
+ }
+}
+
+void validateXml(const string& sXML, const string& sSchema, const string& sXMLName,
+ const string& sSchemaName)
+{
+ XMLParser parser;
+ parser.setSchema(sSchema, sSchemaName);
+
+ parser.parse(sXML, sXMLName);
+}
+
+}