CMS 3D CMS Logo

XMLDocument.cc
Go to the documentation of this file.
1 #include <assert.h>
2 #include <iostream>
3 #include <iomanip>
4 #include <sstream>
5 #include <memory>
6 #include <string>
7 #include <cstdio>
8 #include <stdio.h>
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  virtual ~XMLInputSourceWrapper() {}
50 
51  virtual 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  virtual ~STLInputStream() {}
66 
67  virtual XMLFilePos curPos() const override { return pos; }
68 
69  virtual XMLSize_t readBytes(XMLByte *const buf,
70  const XMLSize_t size) override;
71 
72  virtual const XMLCh* getContentType() const override { return 0; }
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()
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(0), doc(0), rootNode(0)
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),
166  write(false), impl(0), doc(0), rootNode(0)
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  throw;
213  }
214 }
215 
216 void XMLDocument::openForRead(std::unique_ptr<std::istream> &stream)
217 {
218  parser.reset(new XercesDOMParser());
219  parser->setValidationScheme(XercesDOMParser::Val_Auto);
220  parser->setDoNamespaces(false);
221  parser->setDoSchema(false);
222  parser->setValidationSchemaFullChecking(false);
223  errHandler.reset(new HandlerBase());
224  parser->setErrorHandler(errHandler.get());
225  parser->setCreateEntityReferenceNodes(false);
226 
227  inputSource.reset(new STLInputSource(stream));
228 
229  try {
230  parser->parse(*inputSource);
231  if (parser->getErrorCount())
232  throw cms::Exception("XMLDocument")
233  << "XML parser reported errors."
234  << std::endl;
235  } catch(const XMLException &e) {
236  throw cms::Exception("XMLDocument")
237  << "XML parser reported DOM error no. "
238  << (unsigned long)e.getCode()
239  << ": " << XMLSimpleStr(e.getMessage()) << "."
240  << std::endl;
241  } catch(const SAXException &e) {
242  throw cms::Exception("XMLDocument")
243  << "XML parser reported: "
244  << XMLSimpleStr(e.getMessage()) << "."
245  << std::endl;
246  }
247 
248  doc = parser->getDocument();
249 
250  DOMNode *node = doc->getFirstChild();
251  while(node && node->getNodeType() != DOMNode::ELEMENT_NODE)
252  node = node->getNextSibling();
253 
254  if (!node)
255  throw cms::Exception("XMLDocument")
256  << "XML document didn't contain a valid "
257  << "root node." << std::endl;
258 
259  rootNode = static_cast<DOMElement*>(node);
260 }
261 
263 {
264  impl = DOMImplementationRegistry::getDOMImplementation(
265  XMLUniStr("LS"));
266  assert(impl);
267 }
268 
270 {
271  if (doc)
272  throw cms::Exception("XMLDocument")
273  << "Document already exists in createDocument."
274  << std::endl;
275 
276  doc = impl->createDocument(0, XMLUniStr(root.c_str()), 0);
277  rootNode = doc->getDocumentElement();
278 
279  return doc;
280 }
281 
282 // specialization of read/write method templates for bool
283 
285 {
286  for(unsigned int i = 0; i < value.size(); i++)
287  if (value[i] >= 'A' && value[i] <= 'Z')
288  value[i] += 'a' - 'A';
289 
290  if (value == "1" || value == "y" || value == "yes" ||
291  value == "true" || value == "ok")
292  return true;
293 
294  if (value == "0" || value == "n" || value == "no" || value == "false")
295  return false;
296 
297  throw cms::Exception("XMLDocument")
298  << "Invalid boolean value in XML document" << std::endl;
299 }
300 
301 static const char *makeBool(bool value)
302 {
303  return value ? "true" : "false";
304 }
305 
307  const char *name)
308 {
309  XMLUniStr uniName(name);
310  return elem->hasAttribute(uniName);
311 }
312 
313 template<>
316  const char *name)
317 {
318  XMLUniStr uniName(name);
319  if (!elem->hasAttribute(uniName))
320  throw cms::Exception("MVAComputer")
321  << "Missing attribute " << name << " in tag "
322  << XMLSimpleStr(elem->getNodeName())
323  << "." << std::endl;
324  const XMLCh *attribute = elem->getAttribute(uniName);
325  return isBool(XMLSimpleStr(attribute));
326 }
327 
328 template<>
331  const char *name, const bool &defValue)
332 {
333  XMLUniStr uniName(name);
334  if (!elem->hasAttribute(uniName))
335  return defValue;
336  const XMLCh *attribute = elem->getAttribute(uniName);
337  return isBool(XMLSimpleStr(attribute));
338 }
339 
340 template<>
343  const char *name, const bool &value)
344 {
345  elem->setAttribute(XMLUniStr(name), XMLUniStr(makeBool(value)));
346 }
347 
348 template<>
350  XERCES_CPP_NAMESPACE_QUALIFIER DOMNode *node)
351 {
352  const XMLCh *content = node->getTextContent();
353  return isBool(XMLSimpleStr(content));
354 }
355 
356 template<>
358  XERCES_CPP_NAMESPACE_QUALIFIER DOMNode *node,
359  XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *doc,
360  const bool &value)
361 {
362  node->appendChild(doc->createTextNode(XMLUniStr(makeBool(value))));
363 }
size
Write out results.
int i
Definition: DBlmapReader.cc:9
static const char * makeBool(bool value)
Definition: XMLDocument.cc:301
XMLInputSourceWrapper< STLInputStream > STLInputSource
Definition: XMLUtils.h:200
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 XERCES_CPP_NAMESPACE_QUALIFIER
Definition: LHERunInfo.h:16
void xercesInitialize()
Definition: Xerces.cc:18
string command
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:306
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:216
void openForWrite(const std::string &fileName)
Definition: XMLDocument.cc:262
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:18
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:209
XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument * createDocument(const std::string &root)
Definition: XMLDocument.cc:269
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:284