00001
00002
00003
00004 #include <iostream>
00005 #include "xmlBase/XmlParser.h"
00006 #include "xmlBase/EResolver.h"
00007 #include "xmlBase/Dom.h"
00008 #include "facilities/Util.h"
00009 #include <xercesc/framework/LocalFileInputSource.hpp>
00010 #include <xercesc/framework/MemBufInputSource.hpp>
00011 #include <xercesc/util/XMLString.hpp>
00012 #include <xercesc/framework/XMLValidator.hpp>
00013 #include <xercesc/util/PlatformUtils.hpp>
00014
00015 namespace {
00016 XERCES_CPP_NAMESPACE_USE
00017 bool checkDocType(const DOMDocument* doc, const std::string docType) {
00018 bool ret = false;
00019 const DOMDocumentType* typeDecl = doc->getDoctype();
00020 if (typeDecl != 0) {
00021 const XMLCh* name = typeDecl->getName();
00022 XMLCh* transDocType = XMLString::transcode(docType.c_str());
00023 ret = XMLString::equals(name, transDocType);
00024 XMLString::release(&transDocType);
00025
00026 }
00027 return ret;
00028 }
00029 }
00030
00031
00032
00033 namespace xmlBase {
00034 XERCES_CPP_NAMESPACE_USE
00035 int XmlParser::didInit = 0;
00036
00037
00038
00039 XmlParser::XmlParser(bool throwErrors) : m_throwErrors(throwErrors),
00040 m_doSchema(false) {
00041 if (!didInit) {
00042 try {
00043 XMLPlatformUtils::Initialize();
00044 }
00045 catch(const XMLException& toCatch)
00046 {
00047 char* charMsg = XMLString::transcode(toCatch.getMessage());
00048 std::string msg = std::string(charMsg);
00049 XMLString::release(&charMsg);
00050
00051 std::string errMsg("Error during Xerces-c Initialization: \n");
00052 errMsg += " Exception message: ";
00053 errMsg += msg;
00054 if (m_throwErrors) {
00055 throw ParseException(msg);
00056 } else {
00057 std::cerr << errMsg << std::endl;
00058 return;
00059 }
00060 }
00061 didInit = 1;
00062 }
00063 m_parser = new XercesDOMParser();
00064
00065 m_errorHandler = new XmlErrorHandler(throwErrors);
00066
00067
00068
00069 m_parser->setValidationScheme(AbstractDOMParser::Val_Auto);
00070
00071
00072
00073
00074
00075
00076 m_resolver = new EResolver();
00077 m_parser->setXMLEntityResolver(m_resolver);
00078 m_parser->setErrorHandler(m_errorHandler);
00079
00080
00081
00082
00083
00084 m_parser->setCreateEntityReferenceNodes(false);
00085
00086
00087
00088
00089
00090 m_parser->setIncludeIgnorableWhitespace(false);
00091 }
00092 void XmlParser::doSchema(bool doit) {
00093 m_doSchema = doit;
00094
00095
00096 m_parser->setDoNamespaces(doit);
00097 m_parser->setDoSchema(doit);
00098 m_parser->setValidationSchemaFullChecking(doit);
00099 }
00100
00101 XmlParser::~XmlParser() {
00102 delete m_errorHandler;
00103 delete m_resolver;
00104
00105
00106 }
00107
00108 DOMDocument* XmlParser::parse(const char* const filename,
00109 const std::string& docType) {
00110 XERCES_CPP_NAMESPACE_USE
00111
00112 m_errorsOccurred = false;
00113 m_resolver->clean();
00114
00115
00116 std::string fname(filename);
00117 int nExpand = facilities::Util::expandEnvVar(&fname);
00118 if (nExpand < 0) {
00119 std::string errMsg("xmlBase::XmlParser::parse ");
00120 errMsg += "Filename arg. contained untranslatable env. variables";
00121 if (m_throwErrors) {
00122 throw
00123 ParseException(errMsg);
00124 } else {
00125 std::cerr << errMsg << std::endl;
00126 return 0;
00127 }
00128 }
00129
00130
00131 try {
00132
00133 XMLCh* filenameXMLCh = XMLString::transcode(fname.c_str());
00134 LocalFileInputSource fileSource(filenameXMLCh);
00135 m_parser->parse(fileSource);
00136 XMLString::release(&filenameXMLCh);
00137 }
00138 catch (const XMLException& e) {
00139 char* charMsg = XMLString::transcode(e.getMessage());
00140 std::string msg = std::string(charMsg);
00141 XMLString::release(&charMsg);
00142 std::string errMsg("xmlBase::XmlParser::parse ");
00143 errMsg += "Error occurred while parsing file ";
00144 errMsg += fname;
00145 m_errorsOccurred = true;
00146 m_parser->reset();
00147 if (m_throwErrors) {
00148 errMsg += " ";
00149 errMsg += msg;
00150 throw ParseException(errMsg);
00151 }
00152 else {
00153 std::cerr << errMsg << std::endl
00154 << "Message: " << msg << std::endl;
00155 return 0;
00156 }
00157
00158 }
00159
00160 if (m_errorHandler->getFatalCount() + m_errorHandler->getErrorCount()) {
00161
00162 m_parser->reset();
00163 return 0;
00164 }
00165 if (docType != std::string("")) {
00166 bool ok = checkDocType(m_parser->getDocument(), docType);
00167
00168 if (ok) return m_parser->getDocument();
00169
00170
00171 m_parser->reset();
00172 return 0;
00173 }
00174
00175 return m_parser->getDocument();
00176
00177 }
00178
00179
00180 DOMDocument* XmlParser::parse(const std::string& input,
00181 const std::string& docType) {
00182 XERCES_CPP_NAMESPACE_USE
00183
00184
00185 m_errorsOccurred = false;
00186 try {
00187 char fakeid =99;
00188 XMLCh* buffer = XMLString::transcode(input.c_str());
00189
00190
00191 unsigned int byteCount = sizeof(XMLCh) * input.length();
00192
00193 MemBufInputSource source((const unsigned char*)buffer, byteCount,
00194 &fakeid, false);
00195 m_parser->parse(source);
00196 XMLString::release(&buffer);
00197 }
00198 catch (const XMLException& e) {
00199 char* charMsg = XMLString::transcode(e.getMessage());
00200 std::string msg = std::string(charMsg);
00201 XMLString::release(&charMsg);
00202 m_errorsOccurred = true;
00203 m_parser->reset();
00204
00205 std::string errMsg("xmlBase::XmlParser::parse ");
00206 errMsg +=
00207 "An error occurred while parsing MemBufInputSource\n Message: ";
00208 if (m_throwErrors) {
00209 throw ParseException(errMsg);
00210 } else {
00211 std::cerr << errMsg << std::endl;
00212 return 0;
00213 }
00214
00215 std::cerr <<
00216 "An error occurred while parsing MemBufInputSource\n Message: " <<
00217 msg << std::endl;
00218 return 0;
00219 }
00220
00221 if (m_errorHandler->getFatalCount() + m_errorHandler->getErrorCount()) {
00222
00223 m_parser->reset();
00224 return 0;
00225 }
00226
00227 if (docType != std::string("")) {
00228 bool ok = checkDocType(m_parser->getDocument(), docType);
00229
00230 if (ok) return m_parser->getDocument();
00231
00232
00233 m_parser->reset();
00234 return 0;
00235 }
00236
00237 return m_parser->getDocument();
00238
00239
00240
00241 }
00242
00243 }