xmlparser.h

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2001-2006, William Joseph.
00003 All Rights Reserved.
00004 
00005 This file is part of GtkRadiant.
00006 
00007 GtkRadiant is free software; you can redistribute it and/or modify
00008 it under the terms of the GNU General Public License as published by
00009 the Free Software Foundation; either version 2 of the License, or
00010 (at your option) any later version.
00011 
00012 GtkRadiant is distributed in the hope that it will be useful,
00013 but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with GtkRadiant; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 */
00021 
00022 #if !defined(INCLUDED_XML_XMLPARSER_H)
00023 #define INCLUDED_XML_XMLPARSER_H
00024 
00025 #include <cstdio>
00026 #include <string.h>
00027 #include "ixml.h"
00028 #include <libxml/parser.h>
00029 #include "convert.h"
00030 
00031 class TextInputStream;
00032 
00033 class SAXElement : public XMLElement {
00034 public:
00035     SAXElement(const std::string& name, const char** atts)
00036             : m_name(name), m_atts(atts) {
00037     }
00038     const std::string name() const {
00039         return m_name;
00040     }
00041     const std::string attribute(const std::string& name) const {
00042         if (m_atts != 0) {
00043             for (const char** att = m_atts; *att != 0; att += 2) {
00044                 if (strcmp(*att, name.c_str()) == 0) {
00045                     return *(++att);
00046                 }
00047             }
00048         }
00049         return "";
00050     }
00051     void forEachAttribute(XMLAttrVisitor& visitor) const {
00052         if (m_atts != 0) {
00053             for (const char** att = m_atts; *att != 0; att += 2) {
00054                 visitor.visit(*att, *(att + 1));
00055             }
00056         }
00057     }
00058 private:
00059     const std::string m_name;
00060     const char** m_atts;
00061 };
00062 
00063 #include <stdarg.h>
00064 
00065 class FormattedVA {
00066 public:
00067     const char* m_format;
00068     va_list& m_arguments;
00069     FormattedVA(const char* format, va_list& m_arguments)
00070             : m_format(format), m_arguments(m_arguments) {
00071     }
00072 };
00073 
00074 class Formatted {
00075 public:
00076     const char* m_format;
00077     va_list m_arguments;
00078     Formatted(const char* format, ...)
00079             : m_format(format) {
00080         va_start(m_arguments, format);
00081     }
00082     ~Formatted() {
00083         va_end(m_arguments);
00084     }
00085 };
00086 
00087 template<typename TextOutputStreamType>
00088 inline TextOutputStreamType& ostream_write(TextOutputStreamType& ostream, const FormattedVA& formatted) {
00089     char buffer[1024];
00090     ostream.write(buffer, vsnprintf(buffer, 1023, formatted.m_format, formatted.m_arguments));
00091     return ostream;
00092 }
00093 
00094 template<typename TextOutputStreamType>
00095 inline TextOutputStreamType& ostream_write(TextOutputStreamType& ostream, const Formatted& formatted) {
00096     char buffer[1024];
00097     ostream.write(buffer, vsnprintf(buffer, 1023, formatted.m_format, formatted.m_arguments));
00098     return ostream;
00099 }
00100 
00101 class XMLSAXImporter {
00102     XMLImporter& m_importer;
00103     xmlSAXHandler m_sax;
00104 
00105     static void startElement(void *user_data, const xmlChar *name, const xmlChar **atts) {
00106         SAXElement element(reinterpret_cast<const char*>(name), reinterpret_cast<const char**>(atts));
00107         reinterpret_cast<XMLSAXImporter*>(user_data)->m_importer.pushElement(element);
00108     }
00109     static void endElement(void *user_data, const xmlChar *name) {
00110         reinterpret_cast<XMLSAXImporter*>(user_data)->m_importer.popElement(reinterpret_cast<const char*>(name));
00111     }
00112     static void characters(void *user_data, const xmlChar *ch, int len) {
00113         reinterpret_cast<XMLSAXImporter*>(user_data)->m_importer
00114         << ConvertUTF8ToLocale(StringRange(reinterpret_cast<const char*>(ch), reinterpret_cast<const char*>(ch + len)));
00115     }
00116 
00117     static void warning(void *user_data, const char *msg, ...) {
00118         va_list args;
00119         va_start(args, msg);
00120         globalWarningStream() << "XML WARNING: " << FormattedVA(msg, args);
00121         va_end(args);
00122     }
00123     static void error(void *user_data, const char *msg, ...) {
00124         va_list args;
00125         va_start(args, msg);
00126         globalErrorStream() << "XML ERROR: " << FormattedVA(msg, args);
00127         va_end(args);
00128     }
00129 
00130 public:
00131     XMLSAXImporter(XMLImporter& importer) : m_importer(importer) {
00132         m_sax.internalSubset = 0;
00133         m_sax.isStandalone = 0;
00134         m_sax.hasInternalSubset = 0;
00135         m_sax.hasExternalSubset = 0;
00136         m_sax.resolveEntity = 0;
00137         m_sax.getEntity = 0;
00138         m_sax.entityDecl = 0;
00139         m_sax.notationDecl = 0;
00140         m_sax.attributeDecl = 0;
00141         m_sax.elementDecl = 0;
00142         m_sax.unparsedEntityDecl = 0;
00143         m_sax.setDocumentLocator = 0;
00144         m_sax.startDocument = 0;
00145         m_sax.endDocument = 0;
00146         m_sax.startElement = startElement;
00147         m_sax.endElement = endElement;
00148         m_sax.reference = 0;
00149         m_sax.characters = characters;
00150         m_sax.ignorableWhitespace = 0;
00151         m_sax.processingInstruction = 0;
00152         m_sax.comment = 0;
00153         m_sax.warning = warning;
00154         m_sax.error = error;
00155         m_sax.fatalError = 0;
00156         m_sax.getParameterEntity = 0;
00157         m_sax.cdataBlock = 0;
00158         m_sax.externalSubset = 0;
00159         m_sax.initialized = 1;
00160     }
00161 
00162     xmlSAXHandler* callbacks() {
00163         return &m_sax;
00164     }
00165     void* context() {
00166         return this;
00167     }
00168 };
00169 
00170 class XMLStreamParser : public XMLExporter {
00171     enum unnamed0 { BUFSIZE = 1024 };
00172 public:
00173     XMLStreamParser(TextInputStream& istream)
00174             : m_istream(istream) {
00175     }
00176     virtual void exportXML(XMLImporter& importer) {
00177         bool wellFormed = false;
00178 
00179         char chars[BUFSIZE];
00180         std::size_t res = m_istream.read(chars, 4);
00181         if (res > 0) {
00182             XMLSAXImporter sax(importer);
00183 
00184             xmlParserCtxtPtr ctxt = xmlCreatePushParserCtxt(sax.callbacks(), sax.context(), chars, static_cast<int>(res), 0);
00185             ctxt->replaceEntities = 1;
00186 
00187             while ((res = m_istream.read(chars, BUFSIZE)) > 0) {
00188                 xmlParseChunk(ctxt, chars, static_cast<int>(res), 0);
00189             }
00190             xmlParseChunk(ctxt, chars, 0, 1);
00191 
00192             wellFormed = (ctxt->wellFormed == 1);
00193 
00194             xmlFreeParserCtxt(ctxt);
00195         }
00196 
00197         //return wellFormed;
00198     }
00199 private:
00200     TextInputStream& m_istream;
00201 };
00202 
00203 
00204 
00205 #endif

Generated by  doxygen 1.6.2