1#ifndef _MBXMLUTILSHELPER_DOM_H_
2#define _MBXMLUTILSHELPER_DOM_H_
4#include <fmatvec/atom.h>
11#include <boost/filesystem.hpp>
12#include <xercesc/dom/DOMErrorHandler.hpp>
13#include <xercesc/dom/DOMElement.hpp>
14#include <xercesc/dom/DOMText.hpp>
15#include <xercesc/dom/DOMLSParser.hpp>
16#include <xercesc/dom/DOMLocator.hpp>
17#include <xercesc/dom/DOMUserDataHandler.hpp>
18#include <xercesc/dom/DOMDocument.hpp>
19#include <xercesc/util/TransService.hpp>
20#include <xercesc/util/XMLEntityResolver.hpp>
21#include <xercesc/framework/psvi/PSVIHandler.hpp>
22#include <boost/lexical_cast.hpp>
23#include <boost/container/small_vector.hpp>
24#include <fmatvec/toString.h>
26namespace XERCES_CPP_NAMESPACE {
27 class DOMProcessingInstruction;
28 class DOMImplementation;
29 class AbstractDOMParser;
33 template<> std::vector<double> lexical_cast(
const std::string& str);
34 template<> std::vector<std::vector<double>> lexical_cast(
const std::string& str);
35 template<> std::vector<int> lexical_cast(
const std::string& str);
36 template<> std::vector<std::vector<int>> lexical_cast(
const std::string& str);
37 template<>
bool lexical_cast<bool>(
const std::string& arg);
44 static void check(
const xercesc::DOMElement *me,
const T &value,
int r,
int c);
47struct CheckSize<std::vector<T>> {
48 static void check(
const xercesc::DOMElement *me,
const std::vector<T> &value,
int r,
int c);
51struct CheckSize<std::vector<std::vector<T>>> {
52 static void check(
const xercesc::DOMElement *me,
const std::vector<std::vector<T>> &value,
int r,
int c);
61template<
class T>
using XercesUniquePtr = std::unique_ptr<T, XercesUniquePtrDeleter<T>>;
64template<
typename DOMDocumentType>
66template<
typename DOMDocumentType>
68template<
typename DOMElementType>
70template<
typename DOMElementType>
77 xercesc::XMLPlatformUtils::Initialize();
80 xercesc::XMLPlatformUtils::Terminate();
88 const XMLCh *operator%(
const std::string &str) {
90 return &xercesc::chNull;
91 const XMLCh *unicode=xercesc::TranscodeFromStr(
reinterpret_cast<const XMLByte*
>(str.c_str()), str.length(),
"UTF8").adopt();
92 store.emplace_back(unicode, &releaseXMLCh);
95 const XMLCh *operator()(
const std::string &str) {
return operator%(str); }
96 std::string operator%(
const XMLCh *unicode) {
97 if(!unicode || unicode[0]==0)
99 return reinterpret_cast<const char*
>(xercesc::TranscodeToStr(unicode,
"UTF8").str());
101 std::string operator()(
const XMLCh *unicode) {
return operator%(unicode); }
102 static void releaseXMLCh(
const XMLCh *s) { xercesc::XMLPlatformUtils::fgMemoryManager->deallocate(
const_cast<XMLCh*
>(s)); }
104 boost::container::small_vector<std::unique_ptr<
const XMLCh,
decltype(&releaseXMLCh)>, 1> store;
109class FQN :
public std::pair<std::string, std::string> {
114 FQN(
const std::string &name) : std::pair<std::string, std::string>(
"", name) {}
116 FQN(
const char *name) : std::pair<std::string, std::string>(
"", name) {}
118 FQN(
const std::string &ns,
const std::string &name) : std::pair<std::string, std::string>(ns, name) {}
125 EmbedDOMLocator(
const boost::filesystem::path &file_,
int row_,
int embedCount_, std::string xpath_) : DOMLocator(),
126 file(x%file_.string()), row(row_), embedCount(embedCount_), xpath(std::move(xpath_)) {}
128 file(x%(
X()%src.file)), row(src.row), embedCount(src.embedCount), xpath(src.xpath) {}
130 file=x%(
X()%src.file);
132 embedCount=src.embedCount;
139 XMLFileLoc getLineNumber()
const override {
return row; }
140 XMLFileLoc getColumnNumber()
const override {
return 0; }
141 XMLFilePos getByteOffset()
const override {
return ~(XMLFilePos(0)); }
142 XMLFilePos getUtf16Offset()
const override {
return ~(XMLFilePos(0)); }
143 xercesc::DOMNode *getRelatedNode()
const override {
return nullptr; }
144 const XMLCh *getURI()
const override {
return file; }
145 int getEmbedCount()
const {
return embedCount; }
150 static void addNSURIPrefix(std::string nsuri,
const std::vector<std::string> &prefix);
151 static const std::map<std::string, std::string>& getNSURIPrefix() {
return nsURIPrefix(); }
158 static std::map<std::string, std::string>& nsURIPrefix();
164 NamespaceURI(std::string nsuri_,
const std::vector<std::string> &preferredPrefix={}) : nsuri(std::move(nsuri_)) {
165 EmbedDOMLocator::addNSURIPrefix(nsuri, preferredPrefix);
167 FQN operator%(
const std::string &localName)
const {
return {nsuri, localName}; }
168 const std::string& getNamespaceURI()
const {
return nsuri; }
174const NamespaceURI XINCLUDE(
"http://www.w3.org/2001/XInclude", {
"xi",
"xinc",
"xinclude"});
176const NamespaceURI XMLNS(
"http://www.w3.org/2000/xmlns/", {
"xmlns"});
178const NamespaceURI PV(
"http://www.mbsim-env.de/MBXMLUtils", {
"p",
"pv",
"mbxmlutils"});
180const NamespaceURI XMLCATALOG(
"urn:oasis:names:tc:entity:xmlns:xml:catalog", {
"catalog",
"xmlcatalog"});
184#define RETHROW_AS_DOMEVALEXCEPTION(e) \
185 catch(MBXMLUtils::DOMEvalException &ex) { \
188 catch(const std::exception &ex) { \
189 throw DOMEvalException(ex.what(), e); \
200 void appendContext(
const xercesc::DOMNode *n,
int lineNr=0);
201 const std::string& getMessage()
const {
return errorMsg; }
202 void setMessage(
const std::string& errorMsg_) { errorMsg=errorMsg_; }
203 void setSubsequentError(
bool sse) { subsequentError=sse; }
204 const char* what()
const noexcept override;
205 xercesc::DOMNode::NodeType getNodeType()
const {
return nodeType; }
206 static bool isHTMLOutputEnabled();
207 static void htmlEscaping(std::string &msg);
209 DOMEvalException(
const std::string &errorMsg_,
const xercesc::DOMLocator &loc);
239 bool subsequentError{
false};
240 std::string errorMsg;
241 std::vector<EmbedDOMLocator> locationStack;
242 mutable std::string whatStr;
243 xercesc::DOMNode::NodeType nodeType {
static_cast<xercesc::DOMNode::NodeType
>(-1) };
251 bool handleError(
const xercesc::DOMError&)
override;
252 bool hasError() {
return errorSet; }
254 void resetError() { errorSet=
false; }
256 bool errorSet{
false};
261template<
typename DOMElementType>
283 std::string
getEmbedData(
const std::string &name)
const;
286 void addEmbedData(
const std::string &name,
const std::string &data);
302 template<
class T> T
getText(
int r=0,
int c=0)
const {
304 auto textEle=E(me)->getFirstTextChild();
305 auto text=textEle ?
X()%textEle->getData() :
"";
306 auto ret=boost::lexical_cast<T>(text);
307 CheckSize<T>::check(me, ret, r, c);
310 catch(
const boost::bad_lexical_cast &ex) {
313 catch(
const std::exception &ex) {
318 template<
class T>
void addElementText(
const FQN &name,
const T &value) {
319 xercesc::DOMElement *ele=D(me->getOwnerDocument())->createElement(name);
320 ele->insertBefore(me->getOwnerDocument()->createTextNode(
MBXMLUtils::X()%fmatvec::toString(value)),
nullptr);
321 me->insertBefore(ele,
nullptr);
332 const xercesc::DOMElement *&found=DOMElementWrapper<DOMElementType>::dummyArg)
const;
340 boost::filesystem::path
convertPath(
const boost::filesystem::path &relPath)
const;
379 me->setAttributeNS(
X()%name.first,
X()%name.second,
X()%fmatvec::toString(value));
388 typename std::conditional<std::is_same<DOMElementType, const xercesc::DOMElement>::value,
392 static const xercesc::DOMElement *dummyArg;
397template<
typename DOMElementType>
398DOMElementWrapper<DOMElementType> E(DOMElementType *me) {
return DOMElementWrapper<DOMElementType>(me); }
400template<
typename DOMElementType>
401DOMElementWrapper<DOMElementType> E(
const std::shared_ptr<DOMElementType> &me) {
return DOMElementWrapper<DOMElementType>(me.get()); }
403template<
typename DOMElementType>
404DOMElementWrapper<DOMElementType> E(
const XercesUniquePtr<DOMElementType> &me) {
return DOMElementWrapper<DOMElementType>(me.get()); }
406template<>
const xercesc::DOMElement *DOMElementWrapper< xercesc::DOMElement>::dummyArg;
407template<>
const xercesc::DOMElement *DOMElementWrapper<const xercesc::DOMElement>::dummyArg;
410template<
typename DOMAttrType>
422 typename std::conditional<std::is_same<DOMAttrType, const xercesc::DOMAttr>::value,
430template<
typename DOMAttrType>
431DOMAttrWrapper<DOMAttrType> A(DOMAttrType *me) {
return DOMAttrWrapper<DOMAttrType>(me); }
433template<
typename DOMAttrType>
434DOMAttrWrapper<DOMAttrType> A(
const std::shared_ptr<DOMAttrType> &me) {
return DOMAttrWrapper<DOMAttrType>(me.get()); }
436template<
typename DOMAttrType>
437DOMAttrWrapper<DOMAttrType> A(
const XercesUniquePtr<DOMAttrType> &me) {
return DOMAttrWrapper<DOMAttrType>(me.get()); }
442template<
typename DOMDocumentType>
451 XercesUniquePtr<xercesc::DOMElement>
validate();
456 std::shared_ptr<DOMParser>
getParser()
const;
467 xercesc::DOMElement*
locateElement(
const std::vector<int> &idx)
const;
469 typename std::conditional<std::is_same<DOMDocumentType, const xercesc::DOMDocument>::value,
477template<
typename DOMDocumentType>
478DOMDocumentWrapper<DOMDocumentType> D(DOMDocumentType *me) {
return DOMDocumentWrapper<DOMDocumentType>(me); }
480template<
typename DOMDocumentType>
481DOMDocumentWrapper<DOMDocumentType> D(
const std::shared_ptr<DOMDocumentType> &me) {
return DOMDocumentWrapper<DOMDocumentType>(me.get()); }
483template<
typename DOMDocumentType>
484DOMDocumentWrapper<DOMDocumentType> D(
const XercesUniquePtr<DOMDocumentType> &me) {
return DOMDocumentWrapper<DOMDocumentType>(me.get()); }
488 void setParser(
DOMParser *parser_) { parser=parser_; }
489 xercesc::DOMLSParserFilter::FilterAction acceptNode(xercesc::DOMNode *n)
override;
490 xercesc::DOMLSParserFilter::FilterAction startElement(xercesc::DOMElement *e)
override;
491 xercesc::DOMNodeFilter::ShowType getWhatToShow()
const override;
492 void setLineNumberOffset(
int offset) { lineNumberOffset=offset; }
495 int lineNumberOffset { 0 };
500 void setParser(
DOMParser *parser_) { parser=parser_; }
501 void handleElementPSVI(
const XMLCh *localName,
const XMLCh *uri, xercesc::PSVIElement *info)
override;
502 void handleAttributesPSVI(
const XMLCh *localName,
const XMLCh *uri, xercesc::PSVIAttributeList *psviAttributes)
override;
509 void handle(DOMOperationType operation,
const XMLCh* key,
void *data,
const xercesc::DOMNode *src, xercesc::DOMNode *dst)
override;
516 void setParser(
DOMParser *parser_) { parser=parser_; }
517 xercesc::InputSource* resolveEntity(xercesc::XMLResourceIdentifier *resourceIdentifier)
override;
523class DOMParser :
public std::enable_shared_from_this<DOMParser> {
535 static std::shared_ptr<DOMParser>
create(const std::variant<boost::filesystem::path, xercesc::DOMElement*> &xmlCatalog=static_cast<xercesc::DOMElement*>(nullptr));
539 std::shared_ptr<xercesc::DOMDocument>
parse(const boost::filesystem::path &inputSource,
540 std::vector<boost::filesystem::path> *dependencies=nullptr,
541 bool doXInclude=true);
545 std::shared_ptr<xercesc::DOMDocument>
parse( std::istream &inputStream,
546 std::vector<boost::filesystem::path> *dependencies=nullptr,
547 bool doXInclude=true);
551 xercesc::DOMElement*
parseWithContext(const std::string &str, xercesc::DOMNode *contextNode, xercesc::DOMLSParser::ActionType action,
552 std::vector<boost::filesystem::path> *dependencies=nullptr,
553 bool doXInclude=true);
556 static void
serialize(xercesc::DOMNode *n, const boost::filesystem::path &outputSource);
565 const std::map<FQN, xercesc::XSTypeDefinition*>& getTypeMap() const {
return typeMap; }
567 xercesc::DOMImplementation *domImpl;
568 DOMParser(
const std::variant<boost::filesystem::path, xercesc::DOMElement*> &xmlCatalog);
569 std::shared_ptr<xercesc::DOMLSParser> parser;
570 std::map<FQN, xercesc::XSTypeDefinition*> typeMap;
575 std::map<std::string, boost::filesystem::path> registeredGrammar;
577 static void handleXInclude(xercesc::DOMElement *&e, std::vector<boost::filesystem::path> *dependencies);
585void CheckSize<T>::check(
const xercesc::DOMElement *me,
const T &value,
int r,
int c) {}
587void CheckSize<std::vector<T>>::check(
const xercesc::DOMElement *me,
const std::vector<T> &value,
int r,
int c) {
588 if(r!=0 && r!=
static_cast<int>(value.size()))
590 " but got vector of size "+fmatvec::toString(value.size())+
".", me);
593void CheckSize<std::vector<std::vector<T>>>::check(
const xercesc::DOMElement *me,
const std::vector<std::vector<T>> &value,
int r,
int c) {
594 if(r!=0 && r!=
static_cast<int>(value.size()))
596 " but got matrix of row-size "+fmatvec::toString(value.size())+
".", me);
597 if(!value.empty() && c!=0 && c!=
static_cast<int>(value[0].size()))
599 " but got matrix of col-size "+fmatvec::toString(value[0].size())+
".", me);
Helper class for extending DOMAttr (use the function A(...)).
Definition: dom.h:411
DOMAttrWrapper(DOMAttrType *me_)
Wrap DOMAttr to my special element.
Definition: dom.h:414
std::string getRootXPathExpression() const
Definition: dom.cc:732
bool isDerivedFrom(const FQN &baseTypeName) const
Definition: dom.cc:726
std::conditional< std::is_same< DOMAttrType, constxercesc::DOMAttr >::value, constDOMAttrWrapper *, DOMAttrWrapper * >::type operator->()
Treat this object as a pointer (like DOMAttr*)
Definition: dom.h:423
Helper class for extending DOMDocument (use the function D(...)).
Definition: dom.h:443
xercesc::DOMElement * locateElement(const std::vector< int > &idx) const
Definition: dom.cc:858
boost::filesystem::path getDocumentFilename() const
Definition: dom.cc:790
xercesc::DOMElement * createElement(const FQN &name)
Definition: dom.cc:776
DOMDocumentWrapper(DOMDocumentType *me_)
Wrap DOMDocument to my special element.
Definition: dom.h:446
std::conditional< std::is_same< DOMDocumentType, constxercesc::DOMDocument >::value, constDOMDocumentWrapper *, DOMDocumentWrapper * >::type operator->()
Treat this object as a pointer (like DOMDocument*)
Definition: dom.h:470
xercesc::DOMNode * evalRootXPathExpression(std::string xpathExpression, xercesc::DOMElement *context=nullptr)
Definition: dom.cc:818
XercesUniquePtr< xercesc::DOMElement > validate()
Definition: dom.cc:741
std::shared_ptr< DOMParser > getParser() const
Get full qualified tag name.
Definition: dom.cc:784
Helper class for extending DOMElement (use the function E(...)).
Definition: dom.h:262
void setOriginalElementLineNumber(int lineNr)
Set the line number of the original element.
Definition: dom.cc:688
std::string getRootXPathExpression() const
Definition: dom.cc:613
void setEmbedCountNumber(int embedCount)
Definition: dom.cc:590
std::conditional< std::is_same< DOMElementType, constxercesc::DOMElement >::value, constDOMElementWrapper *, DOMElementWrapper * >::type operator->()
Treat this object as a pointer (like DOMElement*)
Definition: dom.h:389
std::string getAttribute(const FQN &name) const
Get attribute named name.
Definition: dom.cc:504
const xercesc::DOMComment * getFirstCommentChild() const
Get first child comment.
Definition: dom.cc:402
bool hasAttribute(const FQN &name) const
check if this element has a attibute named name.
Definition: dom.cc:695
const xercesc::DOMProcessingInstruction * getFirstProcessingInstructionChildNamed(const std::string &target) const
Get first child processing instruction of the specified target.
Definition: dom.cc:351
const xercesc::DOMText * getFirstTextChild() const
Definition: dom.cc:421
boost::filesystem::path getOriginalFilename(bool skipThis=false, const xercesc::DOMElement *&found=DOMElementWrapper< DOMElementType >::dummyArg) const
Definition: dom.cc:462
int getEmbedCountNumber() const
Definition: dom.cc:581
std::vector< int > getElementLocation() const
Definition: dom.cc:661
FQN getAttributeQName(const FQN &name) const
Get attribute named name of type QName.
Definition: dom.cc:510
void addProcessingInstructionChildNamed(const std::string &target, const std::string &data)
Add a processing instruction child of the specified target.
Definition: dom.cc:374
const xercesc::DOMAttr * getAttributeNode(const FQN &name) const
Get attribute node named name.
Definition: dom.cc:521
const xercesc::DOMElement * getNextElementSiblingNamed(const FQN &name) const
Get next sibling element of the specified full qualified name.
Definition: dom.cc:334
void removeAttribute(const FQN &name)
remove from this element the attibute named name.
Definition: dom.cc:576
std::string getEmbedData(const std::string &name) const
Get the embed data named name from the current element. Returns "" if not such data exists.
Definition: dom.cc:380
boost::filesystem::path convertPath(const boost::filesystem::path &relPath) const
Definition: dom.cc:496
T getText(int r=0, int c=0) const
Get the child text as type T.
Definition: dom.h:302
void setEmbedXPathCount(int xPathCount)
Definition: dom.cc:606
const xercesc::DOMElement * getFirstElementChildNamed(const FQN &name) const
Get first child element of the specified full qualified name.
Definition: dom.cc:317
bool isDerivedFrom(const FQN &baseTypeName) const
Definition: dom.cc:717
void setOriginalFilename(boost::filesystem::path orgFileName=boost::filesystem::path())
Definition: dom.cc:489
void setAttribute(const FQN &name, const T &value)
Set attribute.
Definition: dom.h:378
FQN getTagName() const
Get full qualified tag name.
Definition: dom.h:267
int getOriginalElementLineNumber() const
Get the line number of the original element.
Definition: dom.cc:679
DOMElementWrapper(DOMElementType *me_)
Wrap DOMElement to my special element.
Definition: dom.h:265
void addEmbedData(const std::string &name, const std::string &data)
Definition: dom.cc:392
int getEmbedXPathCount() const
Definition: dom.cc:597
int getLineNumber() const
Definition: dom.cc:567
Print DOM error messages.
Definition: dom.h:248
static std::string convertToString(const EmbedDOMLocator &loc, const std::string &message, bool subsequentError=false)
Definition: dom.cc:1003
A XML DOM parser.
Definition: dom.h:523
std::shared_ptr< xercesc::DOMDocument > createDocument()
create a empty document
Definition: dom.cc:1448
xercesc::DOMElement * parseWithContext(const std::string &str, xercesc::DOMNode *contextNode, xercesc::DOMLSParser::ActionType action, std::vector< boost::filesystem::path > *dependencies=nullptr, bool doXInclude=true)
Definition: dom.cc:1366
std::shared_ptr< xercesc::DOMDocument > parse(const boost::filesystem::path &inputSource, std::vector< boost::filesystem::path > *dependencies=nullptr, bool doXInclude=true)
static void serialize(xercesc::DOMNode *n, const boost::filesystem::path &outputSource)
Definition: dom.cc:1398
static void serializeToString(xercesc::DOMNode *n, std::string &outputData)
Definition: dom.cc:1419
void resetCachedGrammarPool()
reset all loaded grammars
Definition: dom.cc:1443
static std::shared_ptr< DOMParser > create(const std::variant< boost::filesystem::path, xercesc::DOMElement * > &xmlCatalog=static_cast< xercesc::DOMElement * >(nullptr))
Definition: dom.cc:1152
std::string getRootHRXPathExpression() const
get human readable (simple) XPath expression to the location
Definition: dom.cc:288
const std::string & getRootXPathExpression() const
get a (simple) XPath expression to the location: each element is prefixed with the namespace URI betw...
Definition: dom.h:147
FQN(const char *name)
Anonymous FQN (required for implicit casting of string literals to anonymous FQNs)
Definition: dom.h:116
FQN(const std::string &ns, const std::string &name)
FQN.
Definition: dom.h:118
FQN(const std::string &name)
Anonymous FQN.
Definition: dom.h:114
Initialize Xerces on load and terminate it on unload of the library/program.
Definition: dom.h:74
Helper class to easily construct full qualified XML names (FQN) using XML namespace prefixes.
Definition: dom.h:162