CMS 3D CMS Logo

XMLDocument.cc

Go to the documentation of this file.
00001 #include <assert.h>
00002 #include <iostream>
00003 #include <iomanip>
00004 #include <sstream>
00005 #include <memory>
00006 #include <string>
00007 
00008 #include <xercesc/util/PlatformUtils.hpp>
00009 #include <xercesc/util/XMLString.hpp>
00010 #include <xercesc/util/XMLUni.hpp>
00011 #include <xercesc/dom/DOM.hpp>
00012 #include <xercesc/dom/DOMImplementationLS.hpp>
00013 #include <xercesc/dom/DOMWriter.hpp>
00014 #include <xercesc/framework/LocalFileFormatTarget.hpp>
00015 #include <xercesc/parsers/XercesDOMParser.hpp>
00016 #include <xercesc/sax/HandlerBase.hpp>
00017 
00018 #include "FWCore/Utilities/interface/Exception.h"
00019 
00020 #include "PhysicsTools/MVATrainer/interface/XMLSimpleStr.h"
00021 #include "PhysicsTools/MVATrainer/interface/XMLUniStr.h"
00022 #include "PhysicsTools/MVATrainer/interface/XMLDocument.h"
00023 
00024 XERCES_CPP_NAMESPACE_USE
00025 
00026 unsigned int XMLDocument::XercesPlatform::instances = 0;
00027 
00028 namespace { // anonymous
00029         struct DocReleaser {
00030                 inline DocReleaser(DOMDocument *doc) : doc(doc) {}
00031                 inline ~DocReleaser() { doc->release(); }
00032 
00033                 DOMDocument *doc;
00034         };
00035 } // anonymous namespace
00036 
00037 XMLDocument::XercesPlatform::XercesPlatform()
00038 {
00039         if (!instances++) {
00040                 try {
00041                         XMLPlatformUtils::Initialize();
00042                 } catch(const XMLException &e) {
00043                         throw cms::Exception("XMLDocument")
00044                                 << "XMLPlatformUtils::Initialize failed "
00045                                    "because of: "
00046                                 << XMLSimpleStr(e.getMessage()) << std::endl;
00047                 }
00048         }
00049 }
00050 
00051 XMLDocument::XercesPlatform::~XercesPlatform()
00052 {
00053         if (!--instances)
00054                 XMLPlatformUtils::Terminate();
00055 }
00056 
00057 XMLDocument::XMLDocument(const std::string &fileName, bool write) :
00058         platform(new XercesPlatform()), fileName(fileName),
00059         write(write), impl(0), doc(0), rootNode(0)
00060 {
00061         if (write)
00062                 openForWrite(fileName);
00063         else
00064                 openForRead(fileName);
00065 }
00066 
00067 XMLDocument::~XMLDocument()
00068 {
00069         if (!write)
00070                 return;
00071 
00072         std::auto_ptr<DocReleaser> docReleaser(new DocReleaser(doc));
00073 
00074         std::auto_ptr<DOMWriter> writer(static_cast<DOMImplementationLS*>(
00075                                                 impl)->createDOMWriter());
00076         assert(writer.get());
00077 
00078         writer->setEncoding(XMLUniStr("UTF-8"));
00079         if (writer->canSetFeature(XMLUni::fgDOMWRTDiscardDefaultContent, true))
00080                 writer->setFeature(XMLUni::fgDOMWRTDiscardDefaultContent, true);
00081         if (writer->canSetFeature(XMLUni::fgDOMWRTFormatPrettyPrint, true))
00082                 writer->setFeature(XMLUni::fgDOMWRTFormatPrettyPrint, true);
00083 
00084         try {
00085                 std::auto_ptr<XMLFormatTarget> target(
00086                                 new LocalFileFormatTarget(fileName.c_str()));
00087 
00088                 writer->writeNode(target.get(), *doc);
00089         } catch(...) {
00090                 std::remove(fileName.c_str());
00091                 throw;
00092         }
00093 }
00094 
00095 void XMLDocument::openForRead(const std::string &fileName)
00096 {
00097         parser = std::auto_ptr<XercesDOMParser>(new XercesDOMParser());
00098         parser->setValidationScheme(XercesDOMParser::Val_Auto);
00099         parser->setDoNamespaces(false);
00100         parser->setDoSchema(false);
00101         parser->setValidationSchemaFullChecking(false);
00102 
00103         errHandler = std::auto_ptr<HandlerBase>(new HandlerBase());
00104         parser->setErrorHandler(errHandler.operator -> ());
00105         parser->setCreateEntityReferenceNodes(false);
00106 
00107         try {
00108                 parser->parse(fileName.c_str());
00109                 if (parser->getErrorCount())
00110                         throw cms::Exception("XMLDocument")
00111                                 << "XML parser reported errors."
00112                                 << std::endl;
00113         } catch(const XMLException &e) {
00114                 throw cms::Exception("XMLDocument")
00115                         << "XML parser reported DOM error no. "
00116                         << (unsigned long)e.getCode()
00117                         << ": " << XMLSimpleStr(e.getMessage()) << "."
00118                         << std::endl;
00119         } catch(const SAXException &e) {
00120                 throw cms::Exception("XMLDocument")
00121                         << "XML parser reported: "
00122                         << XMLSimpleStr(e.getMessage()) << "."
00123                         << std::endl;
00124         }
00125 
00126         doc = parser->getDocument();
00127 
00128         DOMNode *node = doc->getFirstChild();
00129         while(node && node->getNodeType() != DOMNode::ELEMENT_NODE)
00130                 node = node->getNextSibling();
00131 
00132         if (!node)
00133                 throw cms::Exception("XMLDocument")
00134                         << "XML document didn't contain a valid "
00135                         << "root node." << std::endl;
00136 
00137         rootNode = static_cast<DOMElement*>(node);
00138 }
00139 
00140 void XMLDocument::openForWrite(const std::string &fileName)
00141 {
00142         impl = DOMImplementationRegistry::getDOMImplementation(
00143                                                         XMLUniStr("LS"));
00144         assert(impl);
00145 }
00146 
00147 DOMDocument *XMLDocument::createDocument(const std::string &root)
00148 {
00149         if (doc)
00150                 throw cms::Exception("XMLDocument")
00151                         << "Document already exists in createDocument."
00152                         << std::endl;
00153 
00154         doc = impl->createDocument(0, XMLUniStr(root.c_str()), 0);
00155         rootNode = doc->getDocumentElement();
00156 
00157         return doc;
00158 }
00159 
00160 // specialization of read/write method templates for bool
00161 
00162 static bool isBool(std::string value)
00163 {
00164         for(unsigned int i = 0; i < value.size(); i++)
00165                 if (value[i] >= 'A' && value[i] <= 'Z')
00166                         value[i] += 'a' - 'A';
00167 
00168         if (value == "1" || value == "y" || value == "yes" ||
00169             value == "true" || value == "ok")
00170                 return true;
00171 
00172         if (value == "0" || value == "n" || value == "no" || value == "false")
00173                 return false;
00174 
00175         throw cms::Exception("XMLDocument")
00176                 << "Invalid boolean value in XML document" << std::endl;
00177 }
00178 
00179 static const char *makeBool(bool value)
00180 {
00181         return value ? "true" : "false";
00182 }
00183 
00184 bool XMLDocument::hasAttribute(XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *elem,
00185                                const char *name)
00186 {
00187         XMLUniStr uniName(name);
00188         return elem->hasAttribute(uniName);
00189 }
00190 
00191 template<>
00192 bool XMLDocument::readAttribute(
00193                         XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *elem,
00194                         const char *name)
00195 {
00196         XMLUniStr uniName(name);
00197         if (!elem->hasAttribute(uniName))
00198                 throw cms::Exception("MVAComputer")
00199                         << "Missing attribute " << name << " in tag "
00200                         << XMLSimpleStr(elem->getNodeName())
00201                         << "." << std::endl;
00202         const XMLCh *attribute = elem->getAttribute(uniName);
00203         return isBool(XMLSimpleStr(attribute));
00204 }
00205 
00206 template<>
00207 bool XMLDocument::readAttribute(
00208                         XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *elem,
00209                         const char *name, const bool &defValue)
00210 {
00211         XMLUniStr uniName(name);
00212         if (!elem->hasAttribute(uniName))
00213                 return defValue;
00214         const XMLCh *attribute = elem->getAttribute(uniName);
00215         return isBool(XMLSimpleStr(attribute));
00216 }
00217 
00218 template<>
00219 void XMLDocument::writeAttribute(
00220                         XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *elem,
00221                         const char *name, const bool &value)
00222 {
00223         elem->setAttribute(XMLUniStr(name), XMLUniStr(makeBool(value)));
00224 }
00225 
00226 template<>
00227 bool XMLDocument::readContent(
00228                         XERCES_CPP_NAMESPACE_QUALIFIER DOMNode *node)
00229 {
00230         const XMLCh *content = node->getTextContent();
00231         return isBool(XMLSimpleStr(content));
00232 }
00233 
00234 template<>
00235 void XMLDocument::writeContent(
00236                         XERCES_CPP_NAMESPACE_QUALIFIER DOMNode *node,
00237                         XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *doc,
00238                         const bool &value)
00239 {
00240         node->appendChild(doc->createTextNode(XMLUniStr(makeBool(value))));
00241 }

Generated on Tue Jun 9 17:41:33 2009 for CMSSW by  doxygen 1.5.4