CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
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/DOMWriter.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 
30 XERCES_CPP_NAMESPACE_USE
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::auto_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::auto_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 unsigned int curPos() const override { return pos; }
68 
69  virtual unsigned int readBytes(XMLByte *const buf,
70  const unsigned int size) override;
71 
72  private:
73  std::istream &in;
74  unsigned int pos;
75  };
76 
77  template<int (*close)(FILE*)>
78  class stdio_istream : public std::istream {
79  public:
80  typedef __gnu_cxx::stdio_filebuf<char> __filebuf_type;
81  typedef stdio_istream<close> __istream_type;
82 
83  stdio_istream(FILE *file) :
84  file_(file), filebuf_(file, std::ios_base::in)
85  { this->init(&filebuf_); }
86 
87  ~stdio_istream()
88  { close(file_); }
89 
90  __filebuf_type *rdbuf() const
91  { return const_cast<__filebuf_type*>(&filebuf_); }
92 
93  private:
94  FILE *file_;
95  __filebuf_type filebuf_;
96  };
97 
98  typedef XMLInputSourceWrapper<STLInputStream> STLInputSource;
99 } // anonymous namespace
100 
101 unsigned int STLInputStream::readBytes(XMLByte* const buf,
102  const unsigned int size)
103 {
104  char *rawBuf = reinterpret_cast<char*>(buf);
105  unsigned int bytes = size * sizeof(XMLByte);
106  in.read(rawBuf, bytes);
107  unsigned int readBytes = in.gcount();
108 
109  if (in.bad())
110  throw cms::Exception("XMLDocument")
111  << "I/O stream bad in STLInputStream::readBytes()"
112  << std::endl;
113 
114  unsigned int read = (unsigned int)(readBytes / sizeof(XMLByte));
115  unsigned int rest = (unsigned int)(readBytes % sizeof(XMLByte));
116  for(unsigned int i = 1; i <= rest; i++)
117  in.putback(rawBuf[readBytes - i]);
118 
119  pos += read;
120  return read;
121 }
122 
124 {
125  if (!instances++) {
126  try {
128  } catch(const XMLException &e) {
129  throw cms::Exception("XMLDocument")
130  << "cms::concurrency::xercesInitialize failed "
131  "because of: "
132  << XMLSimpleStr(e.getMessage()) << std::endl;
133  }
134  }
135 }
136 
138 {
139  if (!--instances)
141 }
142 
144  platform(new XercesPlatform()), fileName(fileName),
145  write(write), impl(0), doc(0), rootNode(0)
146 {
147  if (write)
148  openForWrite(fileName);
149  else {
150  std::auto_ptr<std::istream> inputStream(
151  new std::ifstream(fileName.c_str()));
152  if (!inputStream->good())
153  throw cms::Exception("XMLDocument")
154  << "XML input file \"" << fileName << "\" "
155  "could not be opened for reading."
156  << std::endl;
157  openForRead(inputStream);
158  }
159 }
160 
162  const std::string &command) :
163  platform(new XercesPlatform()), fileName(fileName),
164  write(false), impl(0), doc(0), rootNode(0)
165 {
166  FILE *file = popen(command.c_str(), "r");
167  if (!file)
168  throw cms::Exception("XMLDocument")
169  << "Could not execute XML preprocessing "
170  " command \"" << command << "\"."
171  << std::endl;
172 
173  std::auto_ptr<std::istream> inputStream(
174  new stdio_istream<pclose>(file));
175  if (!inputStream->good())
176  throw cms::Exception("XMLDocument")
177  << "XML preprocessing command \"" << fileName
178  << "\" stream could not be opened for reading."
179  << std::endl;
180 
181  openForRead(inputStream);
182 }
183 
185 {
186  if (!write)
187  return;
188 
189  std::auto_ptr<DocReleaser> docReleaser(new DocReleaser(doc));
190 
191  std::auto_ptr<DOMWriter> writer(static_cast<DOMImplementationLS*>(
192  impl)->createDOMWriter());
193  assert(writer.get());
194 
195  writer->setEncoding(XMLUniStr("UTF-8"));
196  if (writer->canSetFeature(XMLUni::fgDOMWRTDiscardDefaultContent, true))
197  writer->setFeature(XMLUni::fgDOMWRTDiscardDefaultContent, true);
198  if (writer->canSetFeature(XMLUni::fgDOMWRTFormatPrettyPrint, true))
199  writer->setFeature(XMLUni::fgDOMWRTFormatPrettyPrint, true);
200 
201  try {
202  std::auto_ptr<XMLFormatTarget> target(
203  new LocalFileFormatTarget(fileName.c_str()));
204 
205  writer->writeNode(target.get(), *doc);
206  } catch(...) {
207  std::remove(fileName.c_str());
208  throw;
209  }
210 }
211 
212 void XMLDocument::openForRead(std::auto_ptr<std::istream> &stream)
213 {
214  parser.reset(new XercesDOMParser());
215  parser->setValidationScheme(XercesDOMParser::Val_Auto);
216  parser->setDoNamespaces(false);
217  parser->setDoSchema(false);
218  parser->setValidationSchemaFullChecking(false);
219 
220  errHandler.reset(new HandlerBase());
221  parser->setErrorHandler(errHandler.get());
222  parser->setCreateEntityReferenceNodes(false);
223 
224  inputSource.reset(new STLInputSource(stream));
225 
226  try {
227  parser->parse(*inputSource);
228  if (parser->getErrorCount())
229  throw cms::Exception("XMLDocument")
230  << "XML parser reported errors."
231  << std::endl;
232  } catch(const XMLException &e) {
233  throw cms::Exception("XMLDocument")
234  << "XML parser reported DOM error no. "
235  << (unsigned long)e.getCode()
236  << ": " << XMLSimpleStr(e.getMessage()) << "."
237  << std::endl;
238  } catch(const SAXException &e) {
239  throw cms::Exception("XMLDocument")
240  << "XML parser reported: "
241  << XMLSimpleStr(e.getMessage()) << "."
242  << std::endl;
243  }
244 
245  doc = parser->getDocument();
246 
247  DOMNode *node = doc->getFirstChild();
248  while(node && node->getNodeType() != DOMNode::ELEMENT_NODE)
249  node = node->getNextSibling();
250 
251  if (!node)
252  throw cms::Exception("XMLDocument")
253  << "XML document didn't contain a valid "
254  << "root node." << std::endl;
255 
256  rootNode = static_cast<DOMElement*>(node);
257 }
258 
260 {
261  impl = DOMImplementationRegistry::getDOMImplementation(
262  XMLUniStr("LS"));
263  assert(impl);
264 }
265 
267 {
268  if (doc)
269  throw cms::Exception("XMLDocument")
270  << "Document already exists in createDocument."
271  << std::endl;
272 
273  doc = impl->createDocument(0, XMLUniStr(root.c_str()), 0);
274  rootNode = doc->getDocumentElement();
275 
276  return doc;
277 }
278 
279 // specialization of read/write method templates for bool
280 
282 {
283  for(unsigned int i = 0; i < value.size(); i++)
284  if (value[i] >= 'A' && value[i] <= 'Z')
285  value[i] += 'a' - 'A';
286 
287  if (value == "1" || value == "y" || value == "yes" ||
288  value == "true" || value == "ok")
289  return true;
290 
291  if (value == "0" || value == "n" || value == "no" || value == "false")
292  return false;
293 
294  throw cms::Exception("XMLDocument")
295  << "Invalid boolean value in XML document" << std::endl;
296 }
297 
298 static const char *makeBool(bool value)
299 {
300  return value ? "true" : "false";
301 }
302 
304  const char *name)
305 {
306  XMLUniStr uniName(name);
307  return elem->hasAttribute(uniName);
308 }
309 
310 template<>
313  const char *name)
314 {
315  XMLUniStr uniName(name);
316  if (!elem->hasAttribute(uniName))
317  throw cms::Exception("MVAComputer")
318  << "Missing attribute " << name << " in tag "
319  << XMLSimpleStr(elem->getNodeName())
320  << "." << std::endl;
321  const XMLCh *attribute = elem->getAttribute(uniName);
322  return isBool(XMLSimpleStr(attribute));
323 }
324 
325 template<>
328  const char *name, const bool &defValue)
329 {
330  XMLUniStr uniName(name);
331  if (!elem->hasAttribute(uniName))
332  return defValue;
333  const XMLCh *attribute = elem->getAttribute(uniName);
334  return isBool(XMLSimpleStr(attribute));
335 }
336 
337 template<>
340  const char *name, const bool &value)
341 {
342  elem->setAttribute(XMLUniStr(name), XMLUniStr(makeBool(value)));
343 }
344 
345 template<>
348 {
349  const XMLCh *content = node->getTextContent();
350  return isBool(XMLSimpleStr(content));
351 }
352 
353 template<>
356  XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *doc,
357  const bool &value)
358 {
359  node->appendChild(doc->createTextNode(XMLUniStr(makeBool(value))));
360 }
int i
Definition: DBlmapReader.cc:9
static const char * makeBool(bool value)
Definition: XMLDocument.cc:298
XMLInputSourceWrapper< STLInputStream > STLInputSource
Definition: XMLUtils.h:194
static T readContent(XERCES_CPP_NAMESPACE_QUALIFIER DOMNode *node)
std::auto_ptr< XERCES_CPP_NAMESPACE_QUALIFIER InputSource > inputSource
Definition: XMLDocument.h:67
void xercesTerminate()
Definition: Xerces.cc:22
XERCES_CPP_NAMESPACE_QUALIFIER DOMImplementation * impl
Definition: XMLDocument.h:74
int init
Definition: HydjetWrapper.h:62
std::auto_ptr< XercesPlatform > platform
Definition: XMLDocument.h:66
#define XERCES_CPP_NAMESPACE_QUALIFIER
Definition: LHERunInfo.h:16
void xercesInitialize()
Definition: Xerces.cc:17
tuple node
Definition: Node.py:50
std::auto_ptr< XERCES_CPP_NAMESPACE_QUALIFIER HandlerBase > errHandler
Definition: XMLDocument.h:73
static bool hasAttribute(XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *elem, const char *name)
Definition: XMLDocument.cc:303
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
tuple doc
Definition: asciidump.py:381
void openForWrite(const std::string &fileName)
Definition: XMLDocument.cc:259
static void writeAttribute(XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *elem, const char *name, const T &value)
std::auto_ptr< XERCES_CPP_NAMESPACE_QUALIFIER XercesDOMParser > parser
Definition: XMLDocument.h:72
std::string fileName
Definition: XMLDocument.h:69
XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument * createDocument(const std::string &root)
Definition: XMLDocument.cc:266
void openForRead(std::auto_ptr< std::istream > &inputStream)
Definition: XMLDocument.cc:212
volatile std::atomic< bool > shutdown_flag false
static unsigned int instances
Definition: XMLDocument.h:60
long double T
tuple size
Write out results.
Helper class to handle FWLite file input sources.
string root
initialization
Definition: dbtoconf.py:70
static bool isBool(std::string value)
Definition: XMLDocument.cc:281