CMS 3D CMS Logo

XMLDocument.cc
Go to the documentation of this file.
1 #include <cassert>
2 #include <iostream>
3 #include <iomanip>
4 #include <sstream>
5 #include <memory>
6 #include <string>
7 #include <cstdio>
8 #include <cstdio>
9 #include <ext/stdio_filebuf.h>
10 
12 #include <xercesc/util/XMLString.hpp>
13 #include <xercesc/util/XMLUni.hpp>
14 #include <xercesc/util/BinInputStream.hpp>
15 #include <xercesc/dom/DOM.hpp>
16 #include <xercesc/dom/DOMImplementationLS.hpp>
17 #include <xercesc/dom/DOMLSSerializer.hpp>
18 #include <xercesc/framework/LocalFileFormatTarget.hpp>
19 #include <xercesc/parsers/XercesDOMParser.hpp>
20 #include <xercesc/sax/InputSource.hpp>
21 #include <xercesc/sax/HandlerBase.hpp>
22 
23 
25 
29 
31 
33 
34 namespace { // anonymous
35  struct DocReleaser {
36  inline DocReleaser(DOMDocument *doc) : doc(doc) {}
37  inline ~DocReleaser() { doc->release(); }
38 
39  DOMDocument *doc;
40  };
41 
42  template<typename T>
43  class XMLInputSourceWrapper :
45  public:
46  typedef typename T::Stream_t Stream_t;
47 
48  XMLInputSourceWrapper(std::unique_ptr<Stream_t>& obj) : obj(obj) {}
49  ~XMLInputSourceWrapper() override {}
50 
51  XERCES_CPP_NAMESPACE_QUALIFIER BinInputStream*
52  makeStream() const override
53  { return new T(*obj); }
54 
55  private:
56  std::unique_ptr<Stream_t>& obj;
57  };
58 
59  class STLInputStream :
60  public XERCES_CPP_NAMESPACE_QUALIFIER BinInputStream {
61  public:
62  typedef std::istream Stream_t;
63 
64  STLInputStream(std::istream &in) : in(in) {}
65  ~STLInputStream() override {}
66 
67  XMLFilePos curPos() const override { return pos; }
68 
69  XMLSize_t readBytes(XMLByte *const buf,
70  const XMLSize_t size) override;
71 
72  const XMLCh* getContentType() const override { return nullptr; }
73 
74  private:
75  std::istream &in;
76  unsigned int pos;
77  };
78 
79  template<int (*close)(FILE*)>
80  class stdio_istream : public std::istream {
81  public:
82  typedef __gnu_cxx::stdio_filebuf<char> __filebuf_type;
83  typedef stdio_istream<close> __istream_type;
84 
85  stdio_istream(FILE *file) :
86  file_(file), filebuf_(file, std::ios_base::in)
87  { this->init(&filebuf_); }
88 
89  ~stdio_istream() override
90  { close(file_); }
91 
92  __filebuf_type *rdbuf() const
93  { return const_cast<__filebuf_type*>(&filebuf_); }
94 
95  private:
96  FILE *file_;
97  __filebuf_type filebuf_;
98  };
99 
100  typedef XMLInputSourceWrapper<STLInputStream> STLInputSource;
101 } // anonymous namespace
102 
103 XMLSize_t STLInputStream::readBytes(XMLByte* const buf,
104  const XMLSize_t size)
105 {
106  char *rawBuf = reinterpret_cast<char*>(buf);
107  unsigned int bytes = size * sizeof(XMLByte);
108  in.read(rawBuf, bytes);
109  unsigned int readBytes = in.gcount();
110 
111  if (in.bad())
112  throw cms::Exception("XMLDocument")
113  << "I/O stream bad in STLInputStream::readBytes()"
114  << std::endl;
115 
116  unsigned int read = (unsigned int)(readBytes / sizeof(XMLByte));
117  unsigned int rest = (unsigned int)(readBytes % sizeof(XMLByte));
118  for(unsigned int i = 1; i <= rest; i++)
119  in.putback(rawBuf[readBytes - i]);
120 
121  pos += read;
122  return read;
123 }
124 
126 {
127  if (!instances++) {
128  try {
130  } catch(const XMLException &e) {
131  throw cms::Exception("XMLDocument")
132  << "cms::concurrency::xercesInitialize failed "
133  "because of: "
134  << XMLSimpleStr(e.getMessage()) << std::endl;
135  }
136  }
137 }
138 
140 {
141  if (!--instances)
143 }
144 
146  platform(new XercesPlatform()), fileName(fileName),
147  write(write), impl(nullptr), doc(nullptr), rootNode(nullptr)
148 {
149  if (write)
150  openForWrite(fileName);
151  else {
152  std::unique_ptr<std::istream> inputStream(
153  new std::ifstream(fileName.c_str()));
154  if (!inputStream->good())
155  throw cms::Exception("XMLDocument")
156  << "XML input file \"" << fileName << "\" "
157  "could not be opened for reading."
158  << std::endl;
159  openForRead(inputStream);
160  }
161 }
162 
164  const std::string &command) :
165  platform(new XercesPlatform()), fileName(fileName),
167 {
168  FILE *file = popen(command.c_str(), "r");
169  if (!file)
170  throw cms::Exception("XMLDocument")
171  << "Could not execute XML preprocessing "
172  " command \"" << command << "\"."
173  << std::endl;
174 
175  std::unique_ptr<std::istream> inputStream(
176  new stdio_istream<pclose>(file));
177  if (!inputStream->good())
178  throw cms::Exception("XMLDocument")
179  << "XML preprocessing command \"" << fileName
180  << "\" stream could not be opened for reading."
181  << std::endl;
182 
183  openForRead(inputStream);
184 }
185 
187 {
188  if (!write)
189  return;
190 
191  std::unique_ptr<DocReleaser> docReleaser(new DocReleaser(doc));
192 
193  std::unique_ptr<DOMLSSerializer> writer(((DOMImplementationLS*)impl)->createLSSerializer());
194  assert(writer.get());
195 
196  if( writer->getDomConfig()->canSetParameter(XMLUni::fgDOMWRTDiscardDefaultContent,true))
197  writer->getDomConfig()->setParameter(XMLUni::fgDOMWRTDiscardDefaultContent,true);
198  if( writer->getDomConfig()->canSetParameter(XMLUni::fgDOMWRTFormatPrettyPrint, true))
199  writer->getDomConfig()->setParameter(XMLUni::fgDOMWRTFormatPrettyPrint, true);
200 
201  std::unique_ptr<DOMLSOutput> outputDesc(((DOMImplementationLS*)impl)->createLSOutput());
202  assert(outputDesc.get());
203  outputDesc->setEncoding(XMLUniStr("UTF-8"));
204 
205  try {
206  std::unique_ptr<XMLFormatTarget> target(
207  new LocalFileFormatTarget(fileName.c_str()));
208  outputDesc->setByteStream(target.get());
209  writer->write( doc, outputDesc.get());
210  } catch(...) {
211  std::remove(fileName.c_str());
212  }
213 }
214 
215 void XMLDocument::openForRead(std::unique_ptr<std::istream> &stream)
216 {
217  parser.reset(new XercesDOMParser());
218  parser->setValidationScheme(XercesDOMParser::Val_Auto);
219  parser->setDoNamespaces(false);
220  parser->setDoSchema(false);
221  parser->setValidationSchemaFullChecking(false);
222  errHandler.reset(new HandlerBase());
223  parser->setErrorHandler(errHandler.get());
224  parser->setCreateEntityReferenceNodes(false);
225 
226  inputSource.reset(new STLInputSource(stream));
227 
228  try {
229  parser->parse(*inputSource);
230  if (parser->getErrorCount())
231  throw cms::Exception("XMLDocument")
232  << "XML parser reported errors."
233  << std::endl;
234  } catch(const XMLException &e) {
235  throw cms::Exception("XMLDocument")
236  << "XML parser reported DOM error no. "
237  << (unsigned long)e.getCode()
238  << ": " << XMLSimpleStr(e.getMessage()) << "."
239  << std::endl;
240  } catch(const SAXException &e) {
241  throw cms::Exception("XMLDocument")
242  << "XML parser reported: "
243  << XMLSimpleStr(e.getMessage()) << "."
244  << std::endl;
245  }
246 
247  doc = parser->getDocument();
248 
249  DOMNode *node = doc->getFirstChild();
250  while(node && node->getNodeType() != DOMNode::ELEMENT_NODE)
251  node = node->getNextSibling();
252 
253  if (!node)
254  throw cms::Exception("XMLDocument")
255  << "XML document didn't contain a valid "
256  << "root node." << std::endl;
257 
258  rootNode = static_cast<DOMElement*>(node);
259 }
260 
262 {
263  impl = DOMImplementationRegistry::getDOMImplementation(
264  XMLUniStr("LS"));
265  assert(impl);
266 }
267 
269 {
270  if (doc)
271  throw cms::Exception("XMLDocument")
272  << "Document already exists in createDocument."
273  << std::endl;
274 
275  doc = impl->createDocument(nullptr, XMLUniStr(root.c_str()), nullptr);
276  rootNode = doc->getDocumentElement();
277 
278  return doc;
279 }
280 
281 // specialization of read/write method templates for bool
282 
284 {
285  for(unsigned int i = 0; i < value.size(); i++)
286  if (value[i] >= 'A' && value[i] <= 'Z')
287  value[i] += 'a' - 'A';
288 
289  if (value == "1" || value == "y" || value == "yes" ||
290  value == "true" || value == "ok")
291  return true;
292 
293  if (value == "0" || value == "n" || value == "no" || value == "false")
294  return false;
295 
296  throw cms::Exception("XMLDocument")
297  << "Invalid boolean value in XML document" << std::endl;
298 }
299 
300 static const char *makeBool(bool value)
301 {
302  return value ? "true" : "false";
303 }
304 
306  const char *name)
307 {
308  XMLUniStr uniName(name);
309  return elem->hasAttribute(uniName);
310 }
311 
312 template<>
315  const char *name)
316 {
317  XMLUniStr uniName(name);
318  if (!elem->hasAttribute(uniName))
319  throw cms::Exception("MVAComputer")
320  << "Missing attribute " << name << " in tag "
321  << XMLSimpleStr(elem->getNodeName())
322  << "." << std::endl;
323  const XMLCh *attribute = elem->getAttribute(uniName);
324  return isBool(XMLSimpleStr(attribute));
325 }
326 
327 template<>
330  const char *name, const bool &defValue)
331 {
332  XMLUniStr uniName(name);
333  if (!elem->hasAttribute(uniName))
334  return defValue;
335  const XMLCh *attribute = elem->getAttribute(uniName);
336  return isBool(XMLSimpleStr(attribute));
337 }
338 
339 template<>
342  const char *name, const bool &value)
343 {
344  elem->setAttribute(XMLUniStr(name), XMLUniStr(makeBool(value)));
345 }
346 
347 template<>
349  XERCES_CPP_NAMESPACE_QUALIFIER DOMNode *node)
350 {
351  const XMLCh *content = node->getTextContent();
352  return isBool(XMLSimpleStr(content));
353 }
354 
355 template<>
357  XERCES_CPP_NAMESPACE_QUALIFIER DOMNode *node,
358  XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *doc,
359  const bool &value)
360 {
361  node->appendChild(doc->createTextNode(XMLUniStr(makeBool(value))));
362 }
size
Write out results.
static const char * makeBool(bool value)
Definition: XMLDocument.cc:300
XMLInputSourceWrapper< STLInputStream > STLInputSource
Definition: XMLUtils.h:202
static T readContent(XERCES_CPP_NAMESPACE_QUALIFIER DOMNode *node)
void xercesTerminate()
Definition: Xerces.cc:23
std::unique_ptr< XercesPlatform > platform
Definition: XMLDocument.h:66
#define nullptr
int init
Definition: HydjetWrapper.h:67
#define XERCES_CPP_NAMESPACE_QUALIFIER
Definition: LHERunInfo.h:16
void xercesInitialize()
Definition: Xerces.cc:18
std::unique_ptr< XERCES_CPP_NAMESPACE_QUALIFIER InputSource > inputSource
Definition: XMLDocument.h:67
static bool hasAttribute(XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *elem, const char *name)
Definition: XMLDocument.cc:305
XERCES_CPP_NAMESPACE_QUALIFIER DOMElement * rootNode
Definition: XMLDocument.h:77
static T readAttribute(XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *elem, const char *name)
static void writeContent(XERCES_CPP_NAMESPACE_QUALIFIER DOMNode *node, XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *doc, const T &value)
XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument * doc
Definition: XMLDocument.h:76
Definition: value.py:1
void openForRead(std::unique_ptr< std::istream > &inputStream)
Definition: XMLDocument.cc:215
void openForWrite(const std::string &fileName)
Definition: XMLDocument.cc:261
static void writeAttribute(XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *elem, const char *name, const T &value)
def elem(elemtype, innerHTML='', html_class='', kwargs)
Definition: HTMLExport.py:19
std::unique_ptr< XERCES_CPP_NAMESPACE_QUALIFIER HandlerBase > errHandler
Definition: XMLDocument.h:73
std::string fileName
Definition: XMLDocument.h:69
std::unique_ptr< XERCES_CPP_NAMESPACE_QUALIFIER XercesDOMParser > parser
Definition: XMLDocument.h:72
def remove(d, key, TELL=False)
Definition: MatrixUtil.py:212
XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument * createDocument(const std::string &root)
Definition: XMLDocument.cc:268
list command
Definition: mps_check.py:25
def write(self, setup)
static unsigned int instances
Definition: XMLDocument.h:60
long double T
Helper class to handle FWLite file input sources.
static bool isBool(std::string value)
Definition: XMLDocument.cc:283