All Classes Namespaces Functions Variables Typedefs Enumerations
dom.h
1 #ifndef _MBXMLUTILSHELPER_DOM_H_
2 #define _MBXMLUTILSHELPER_DOM_H_
3 
4 #include <fmatvec/atom.h>
5 #include <string>
6 #include <vector>
7 #include <map>
8 #include <set>
9 #include <boost/filesystem.hpp>
10 #include <xercesc/dom/DOMErrorHandler.hpp>
11 #include <xercesc/dom/DOMElement.hpp>
12 #include <xercesc/dom/DOMText.hpp>
13 #include <xercesc/dom/DOMLSParser.hpp>
14 #include <xercesc/dom/DOMLocator.hpp>
15 #include <xercesc/dom/DOMUserDataHandler.hpp>
16 #include <xercesc/util/TransService.hpp>
17 #include <xercesc/util/XMLEntityResolver.hpp>
18 #include <xercesc/framework/psvi/PSVIHandler.hpp>
19 
20 namespace XERCES_CPP_NAMESPACE {
21  class DOMProcessingInstruction;
22  class DOMImplementation;
23  class AbstractDOMParser;
24 }
25 
26 namespace MBXMLUtils {
27 
29 class InitXerces {
30  public:
31  InitXerces() {
32  xercesc::XMLPlatformUtils::Initialize();
33  }
34  ~InitXerces() {
35  xercesc::XMLPlatformUtils::Terminate();
36  }
37 };
38 
41 class X {
42  public:
43  const XMLCh *operator%(const std::string &str) {
44  if(str.empty())
45  return &xercesc::chNull;
46  const XMLCh *unicode=xercesc::TranscodeFromStr(reinterpret_cast<const XMLByte*>(str.c_str()), str.length(), "UTF8").adopt();
47  store.push_back(std::shared_ptr<const XMLCh>(unicode, &releaseXMLCh));
48  return unicode;
49  }
50  const XMLCh *operator()(const std::string &str) { return operator%(str); }
51  std::string operator%(const XMLCh *unicode) {
52  if(!unicode || unicode[0]==0)
53  return std::string();
54  return reinterpret_cast<const char*>(xercesc::TranscodeToStr(unicode, "UTF8").str());
55  }
56  std::string operator()(const XMLCh *unicode) { return operator%(unicode); }
57  static void releaseXMLCh(const XMLCh *s) { xercesc::XMLPlatformUtils::fgMemoryManager->deallocate(const_cast<XMLCh*>(s)); }
58  private:
59  std::vector<std::shared_ptr<const XMLCh> > store;
60 };
61 
63 class DOMErrorPrinter: public xercesc::DOMErrorHandler, virtual public fmatvec::Atom
64 {
65  public:
66  DOMErrorPrinter() : warningCount(0), errorCount(0) {}
67  bool handleError(const xercesc::DOMError&);
68  int getNumWarnings() const { return warningCount; }
69  int getNumErrors() const { return errorCount; }
70  void resetCounter() { warningCount=0; errorCount=0; }
71  protected:
72  int warningCount;
73  int errorCount;
74 };
75 
78 class FQN : public std::pair<std::string, std::string> {
79  public:
81  FQN() : std::pair<std::string, std::string>() {}
83  FQN(const std::string &name) : std::pair<std::string, std::string>("", name) {}
85  FQN(const char *name) : std::pair<std::string, std::string>("", name) {}
87  FQN(const std::string &ns, const std::string &name) : std::pair<std::string, std::string>(ns, name) {}
88 };
89 
91 class NamespaceURI {
92  public:
93  NamespaceURI(const std::string &nsuri_) : nsuri(nsuri_) {}
94  FQN operator%(const std::string &localName) const { return FQN(nsuri, localName); }
95  std::string getNamespaceURI() const { return nsuri; }
96  private:
97  std::string nsuri;
98 };
99 
101 const NamespaceURI XINCLUDE("http://www.w3.org/2001/XInclude");
103 const NamespaceURI PV("http://www.mbsim-env.de/MBXMLUtils");
104 
106 template<typename DOMElementType>
108  public:
110  DOMElementWrapper(DOMElementType *me_) : me(me_) {}
112  FQN getTagName() const { return FQN(X()%me->getNamespaceURI(), X()%me->getLocalName()); }
114  const xercesc::DOMElement *getFirstElementChildNamed(const FQN &name) const;
116  xercesc::DOMElement *getFirstElementChildNamed(const FQN &name);
118  const xercesc::DOMProcessingInstruction *getFirstProcessingInstructionChildNamed(const std::string &target) const;
120  xercesc::DOMProcessingInstruction *getFirstProcessingInstructionChildNamed(const std::string &target);
122  const xercesc::DOMText *getFirstTextChild() const;
124  xercesc::DOMText *getFirstTextChild();
127  bool isDerivedFrom(const FQN &base) const;
133  boost::filesystem::path getOriginalFilename(bool skipThis=false,
134  const xercesc::DOMElement *&found=DOMElementWrapper<DOMElementType>::dummyArg) const;
138  void setOriginalFilename();
141  boost::filesystem::path convertPath(const boost::filesystem::path &relPath) const;
144  int getLineNumber() const;
147  int getEmbedCountNumber() const;
150  void setEmbedCountNumber(int embedCount);
152  int getOriginalElementLineNumber() const;
154  void setOriginalElementLineNumber(int lineNr);
156  std::string getAttribute(const FQN &name) const;
158  const xercesc::DOMAttr* getAttributeNode(const FQN &name) const;
160  xercesc::DOMAttr* getAttributeNode(const FQN &name);
162  void setAttribute(const FQN &name, const std::string &value);
164  bool hasAttribute(const FQN &name) const;
166  void removeAttribute(const FQN &name);
170  typename std::conditional<std::is_same<DOMElementType, const xercesc::DOMElement>::value,
172  return this;
173  }
174  static const xercesc::DOMElement *dummyArg;
175  private:
176  DOMElementType *me;
177 };
179 template<typename DOMElementType>
180 DOMElementWrapper<DOMElementType> E(DOMElementType *me) { return DOMElementWrapper<DOMElementType>(me); }
182 template<typename DOMElementType>
183 DOMElementWrapper<DOMElementType> E(std::shared_ptr<DOMElementType> me) { return DOMElementWrapper<DOMElementType>(me.get()); }
184 
186 template<typename DOMAttrType>
188  public:
190  DOMAttrWrapper(DOMAttrType *me_) : me(me_) {}
193  bool isDerivedFrom(const FQN &base) const;
195  typename std::conditional<std::is_same<DOMAttrType, const xercesc::DOMAttr>::value,
197  return this;
198  }
199  private:
200  DOMAttrType *me;
201 };
203 template<typename DOMAttrType>
204 DOMAttrWrapper<DOMAttrType> A(DOMAttrType *me) { return DOMAttrWrapper<DOMAttrType>(me); }
206 template<typename DOMAttrType>
207 DOMAttrWrapper<DOMAttrType> A(std::shared_ptr<DOMAttrType> me) { return DOMAttrWrapper<DOMAttrType>(me.get()); }
208 
209 class DOMParser;
210 
212 template<typename DOMDocumentType>
214  public:
216  DOMDocumentWrapper(DOMDocumentType *me_) : me(me_) {}
218  void validate();
221  xercesc::DOMElement* createElement(const FQN &name);
223  std::shared_ptr<DOMParser> getParser() const;
225  typename std::conditional<std::is_same<DOMDocumentType, const xercesc::DOMDocument>::value,
227  return this;
228  }
229  private:
230  DOMDocumentType *me;
231 };
233 template<typename DOMDocumentType>
234 DOMDocumentWrapper<DOMDocumentType> D(DOMDocumentType *me) { return DOMDocumentWrapper<DOMDocumentType>(me); }
236 template<typename DOMDocumentType>
237 DOMDocumentWrapper<DOMDocumentType> D(std::shared_ptr<DOMDocumentType> me) { return DOMDocumentWrapper<DOMDocumentType>(me.get()); }
238 
241 class EmbedDOMLocator : public xercesc::DOMLocator {
242  public:
243  EmbedDOMLocator(const boost::filesystem::path &file_, int row_, int embedCount_=0);
244  EmbedDOMLocator(const EmbedDOMLocator &src) {
245  file=x%(X()%src.file); row=src.row; embedCount=src.embedCount;
246  }
247  EmbedDOMLocator& operator=(const EmbedDOMLocator &src) {
248  file=x%(X()%src.file); row=src.row; embedCount=src.embedCount;
249  return *this;
250  }
251  XMLFileLoc getLineNumber() const { return row; }
252  XMLFileLoc getColumnNumber() const { return 0; }
253  XMLFilePos getByteOffset() const { return ~(XMLFilePos(0)); }
254  XMLFilePos getUtf16Offset() const { return ~(XMLFilePos(0)); }
255  xercesc::DOMNode *getRelatedNode() const { return NULL; }
256  const XMLCh *getURI() const { return file; }
257  std::string getEmbedCount() const;
258  private:
259  X x;
260  const XMLCh *file;
261  int row;
262  int embedCount;
263 };
264 
265 // Exception wrapping for DOMEvalException.
266 // Catch a exception of type DOMEvalException, set the current XML context to DOMElement e and rethrow.
267 // Not not change the context if it was alread set before.
268 #define MBXMLUTILS_RETHROW(e) \
269  catch(MBXMLUtils::DOMEvalException &ex) { \
270  if(ex.getLocationStack().size()==0) \
271  ex.setContext(e); \
272  throw; \
273  } \
274  catch(const std::exception &ex) { \
275  throw DOMEvalException(ex.what(), e); \
276  }
277 
279 class DOMEvalException : public std::exception {
280  public:
281  DOMEvalException(const std::string &errorMsg_, const xercesc::DOMElement *e=NULL, const xercesc::DOMAttr *a=NULL);
282  DOMEvalException(const DOMEvalException &src) : errorMsg(src.errorMsg),
283  locationStack(src.locationStack) {}
284  DOMEvalException &operator=(const DOMEvalException &src) {
285  errorMsg=src.errorMsg; locationStack=src.locationStack;
286  return *this;
287  }
288  ~DOMEvalException() throw() {}
289  static void generateLocationStack(const xercesc::DOMElement *e, std::vector<EmbedDOMLocator> &locationStack);
290  static void locationStack2Stream(const std::string &indent, const std::vector<EmbedDOMLocator> &locationStack,
291  const std::string &attrName, std::ostream &str);
292  static std::string fileOutput(const xercesc::DOMLocator &loc);
293  void setContext(const xercesc::DOMElement *e);
294  const std::string& getMessage() const { return errorMsg; }
295  const std::vector<EmbedDOMLocator>& getLocationStack() const { return locationStack; }
296  const char* what() const throw();
297  private:
298  std::string errorMsg;
299  std::vector<EmbedDOMLocator> locationStack;
300  std::string attrName;
301  mutable std::string whatStr;
302 };
303 
304 class LocationInfoFilter : public xercesc::DOMLSParserFilter {
305  public:
306  void setParser(DOMParser *parser_) { parser=parser_; }
307  xercesc::DOMLSParserFilter::FilterAction acceptNode(xercesc::DOMNode *n);
308  xercesc::DOMLSParserFilter::FilterAction startElement(xercesc::DOMElement *e);
309  xercesc::DOMNodeFilter::ShowType getWhatToShow() const;
310  private:
311  DOMParser *parser;
312  static const std::string lineNumberKey;
313 };
314 
315 class TypeDerivativeHandler : public xercesc::PSVIHandler, virtual public fmatvec::Atom {
316  public:
317  void setParser(DOMParser *parser_) { parser=parser_; }
318  void handleElementPSVI(const XMLCh *const localName, const XMLCh *const uri, xercesc::PSVIElement *elementInfo);
319  void handleAttributesPSVI(const XMLCh *const localName, const XMLCh *const uri, xercesc::PSVIAttributeList *psviAttributes);
320  private:
321  DOMParser *parser;
322 };
323 
324 class DOMParserUserDataHandler : public xercesc::DOMUserDataHandler {
325  public:
326  void handle(DOMOperationType operation, const XMLCh* const key, void *data, const xercesc::DOMNode *src, xercesc::DOMNode *dst);
327 };
328 
329 class EntityResolver : public xercesc::XMLEntityResolver {
330  public:
331  void setParser(DOMParser *parser_) { parser=parser_; }
332  xercesc::InputSource* resolveEntity(xercesc::XMLResourceIdentifier *resourceIdentifier) override;
333  private:
334  DOMParser *parser;
335 };
336 
338 class DOMParser {
339  friend bool isDerivedFrom(const xercesc::DOMNode *me, const FQN &baseTypeName);
340  friend class TypeDerivativeHandler;
341  friend class LocationInfoFilter;
342  friend class DOMParserUserDataHandler;
343  friend class EntityResolver;
344  template<typename> friend class DOMDocumentWrapper;
345  public:
347  static std::shared_ptr<DOMParser> create(const std::set<boost::filesystem::path> &schemas={});
349  std::shared_ptr<xercesc::DOMDocument> parse(const boost::filesystem::path &inputSource,
350  std::vector<boost::filesystem::path> *dependencies=NULL);
353  static void serialize(xercesc::DOMNode *n, const boost::filesystem::path &outputSource, bool prettyPrint=true);
356  static void serializeToString(xercesc::DOMNode *n, std::string &outputData, bool prettyPrint=true);
358  void resetCachedGrammarPool();
360  std::shared_ptr<xercesc::DOMDocument> createDocument();
361  private:
362  static const std::string domParserKey;
363 
364  // Load XML Schema grammar file: is actually loaded (the main XML Schema file of a XML file must be loaded direclty)
365  void loadGrammar(const boost::filesystem::path &schemaFilename);
366  // Register XML Schema grammar file: is loaded on demand if needed by another XML Schema
367  void registerGrammar(const std::shared_ptr<DOMParser> &nonValParser, const boost::filesystem::path &schemaFilename);
368 
369  xercesc::DOMImplementation *domImpl;
370  DOMParser(const std::set<boost::filesystem::path> &schemas);
371  std::shared_ptr<xercesc::DOMLSParser> parser;
372  std::weak_ptr<DOMParser> me;
373  std::map<FQN, xercesc::XSTypeDefinition*> typeMap;
374  DOMErrorPrinter errorHandler;
375  LocationInfoFilter locationFilter;
376  TypeDerivativeHandler typeDerHandler;
377  EntityResolver entityResolver;
378  static DOMParserUserDataHandler userDataHandler;
379  std::map<std::string, boost::filesystem::path> registeredGrammar;
380 
381  void handleXIncludeAndCDATA(xercesc::DOMElement *&e, std::vector<boost::filesystem::path> *dependencies=NULL);
382 };
383 
384 }
385 
386 #endif
xercesc::DOMElement * createElement(const FQN &name)
Definition: dom.cc:368
void validate()
(re)validate the document using the parser this document was created
Definition: dom.cc:336
FQN(const char *name)
Anonymous FQN (required for implicit casting of string literals to anonymous FQNs) ...
Definition: dom.h:85
Definition: dom.h:78
void workaroundDefaultAttributesOnImportNode()
Workaround: convert default attributes to normal attributes (must be used before importNode to also i...
Definition: dom.cc:282
void setEmbedCountNumber(int embedCount)
Definition: dom.cc:257
std::conditional< std::is_same< DOMElementType, const xercesc::DOMElement >::value, const DOMElementWrapper *, DOMElementWrapper * >::type operator->()
Treat this object as a pointer (like DOMElement*)
Definition: dom.h:171
bool isDerivedFrom(const FQN &base) const
Definition: dom.cc:327
boost::filesystem::path getOriginalFilename(bool skipThis=false, const xercesc::DOMElement *&found=DOMElementWrapper< DOMElementType >::dummyArg) const
Definition: dom.cc:168
Helper class to easily construct full qualified XML names (FQN) using XML namespace prefixes...
Definition: dom.h:91
FQN(const std::string &ns, const std::string &name)
FQN.
Definition: dom.h:87
FQN(const std::string &name)
Anonymous FQN.
Definition: dom.h:83
Definition: dom.h:329
Definition: dom.h:304
int getOriginalElementLineNumber() const
Get the line number of the original element.
Definition: dom.cc:265
FQN()
Empty FQN.
Definition: dom.h:81
Definition: dom.h:41
Helper class for extending DOMDocument (use the function D(...)).
Definition: dom.h:213
DOMElementWrapper(DOMElementType *me_)
Wrap DOMElement to my special element.
Definition: dom.h:110
std::shared_ptr< DOMParser > getParser() const
Get full qualified tag name.
Definition: dom.cc:376
std::string getAttribute(const FQN &name) const
Get attribute named name.
Definition: dom.cc:212
bool hasAttribute(const FQN &name) const
check if this element has a attibute named name.
Definition: dom.cc:296
int getEmbedCountNumber() const
Definition: dom.cc:248
int getLineNumber() const
Definition: dom.cc:234
std::shared_ptr< xercesc::DOMDocument > createDocument()
create a empty document
Definition: dom.cc:713
Definition: dom.h:241
Initialize Xerces on load and terminate it on unload of the library/program.
Definition: dom.h:29
void setAttribute(const FQN &name, const std::string &value)
Set attribute.
Definition: dom.cc:229
static std::shared_ptr< DOMParser > create(const std::set< boost::filesystem::path > &schemas={})
Create DOM parser.
Definition: dom.cc:529
FQN getTagName() const
Get full qualified tag name.
Definition: dom.h:112
Exception during evaluation of the DOM tree including a location stack.
Definition: dom.h:279
boost::filesystem::path convertPath(const boost::filesystem::path &relPath) const
Definition: dom.cc:204
Helper class for extending DOMAttr (use the function A(...)).
Definition: dom.h:187
const xercesc::DOMText * getFirstTextChild() const
Get first child text.
Definition: dom.cc:151
const xercesc::DOMProcessingInstruction * getFirstProcessingInstructionChildNamed(const std::string &target) const
Get first child processing instruction of the specified target.
Definition: dom.cc:128
void setOriginalElementLineNumber(int lineNr)
Set the line number of the original element.
Definition: dom.cc:274
bool isDerivedFrom(const FQN &base) const
Definition: dom.cc:318
void resetCachedGrammarPool()
reset all loaded grammars
Definition: dom.cc:708
Print DOM error messages.
Definition: dom.h:63
Helper class for extending DOMElement (use the function E(...)).
Definition: dom.h:107
void removeAttribute(const FQN &name)
remove from this element the attibute named name.
Definition: dom.cc:243
A XML DOM parser.
Definition: dom.h:338
std::conditional< std::is_same< DOMAttrType, const xercesc::DOMAttr >::value, const DOMAttrWrapper *, DOMAttrWrapper * >::type operator->()
Treat this object as a pointer (like DOMAttr*)
Definition: dom.h:196
std::shared_ptr< xercesc::DOMDocument > parse(const boost::filesystem::path &inputSource, std::vector< boost::filesystem::path > *dependencies=NULL)
Parse a XML document.
Definition: dom.cc:650
DOMAttrWrapper(DOMAttrType *me_)
Wrap DOMAttr to my special element.
Definition: dom.h:190
DOMDocumentWrapper(DOMDocumentType *me_)
Wrap DOMDocument to my special element.
Definition: dom.h:216
static void serialize(xercesc::DOMNode *n, const boost::filesystem::path &outputSource, bool prettyPrint=true)
Definition: dom.cc:678
void setOriginalFilename()
Definition: dom.cc:196
static void serializeToString(xercesc::DOMNode *n, std::string &outputData, bool prettyPrint=true)
Definition: dom.cc:684
const xercesc::DOMElement * getFirstElementChildNamed(const FQN &name) const
Get first child element of the specified full qualified name.
Definition: dom.cc:111
std::conditional< std::is_same< DOMDocumentType, const xercesc::DOMDocument >::value, const DOMDocumentWrapper *, DOMDocumentWrapper * >::type operator->()
Treat this object as a pointer (like DOMDocument*)
Definition: dom.h:226
const xercesc::DOMAttr * getAttributeNode(const FQN &name) const
Get attribute node named name.
Definition: dom.cc:218

Impressum / Disclaimer / Datenschutz Generated by doxygen 1.8.5 Valid HTML