25 #include <sys/types.h>
32 using namespace DD4hep;
33 using namespace DD4hep::XML;
36 #include "xercesc/framework/LocalFileFormatTarget.hpp"
37 #include "xercesc/framework/StdOutFormatTarget.hpp"
38 #include "xercesc/framework/MemBufFormatTarget.hpp"
39 #include "xercesc/framework/MemBufInputSource.hpp"
40 #include "xercesc/sax/SAXParseException.hpp"
41 #include "xercesc/sax/EntityResolver.hpp"
42 #include "xercesc/sax/InputSource.hpp"
43 #include "xercesc/parsers/XercesDOMParser.hpp"
44 #include "xercesc/util/XMLEntityResolver.hpp"
45 #include "xercesc/util/PlatformUtils.hpp"
46 #include "xercesc/util/XercesDefs.hpp"
47 #include "xercesc/util/XMLUni.hpp"
48 #include "xercesc/util/XMLURL.hpp"
49 #include "xercesc/util/XMLString.hpp"
50 #include "xercesc/dom/DOM.hpp"
51 #include "xercesc/sax/ErrorHandler.hpp"
53 using namespace xercesc;
69 printout(
DEBUG,
"DocumentErrorHandler",
"+++ Destructing the XercesC DOM-XML document error handler....");
78 void error(
const SAXParseException&
e);
80 void fatalError(
const SAXParseException&
e);
82 virtual bool handleError(
const DOMError& domError);
86 bool DocumentErrorHandler::handleError(
const DOMError& domError) {
87 string err =
"DOM UNKNOWN: ";
88 switch (domError.getSeverity()) {
89 case DOMError::DOM_SEVERITY_WARNING:
90 err =
"DOM WARNING: ";
92 case DOMError::DOM_SEVERITY_ERROR:
95 case DOMError::DOM_SEVERITY_FATAL_ERROR:
101 printout(
FATAL,
"DocumentErrorHandler",
"+++ %s %s: %s", err.c_str(),
103 DOMLocator* loc = domError.getLocation();
105 printout(
FATAL,
"DocumentErrorHandler",
"+++ Location: Line:%d Column: %d",
106 int(loc->getLineNumber()),
int(loc->getColumnNumber()));
111 void DocumentErrorHandler::error(
const SAXParseException&
e) {
113 if (m.find(
"The values for attribute 'name' must be names or name tokens") != string::npos
114 || m.find(
"The values for attribute 'ID' must be names or name tokens") != string::npos
115 || m.find(
"for attribute 'name' must be Name or Nmtoken") != string::npos
116 || m.find(
"for attribute 'ID' must be Name or Nmtoken") != string::npos
117 || m.find(
"for attribute 'name' is invalid Name or NMTOKEN value") != string::npos
118 || m.find(
"for attribute 'ID' is invalid Name or NMTOKEN value") != string::npos)
121 printout(
ERROR,
"XercesC",
"+++ Error at file \"%s\", Line %d Column: %d Message:%s",
122 sys.c_str(), int(e.getLineNumber()),
int(e.getColumnNumber()), m.c_str());
125 void DocumentErrorHandler::fatalError(
const SAXParseException&
e) {
128 printout(
FATAL,
"XercesC",
"+++ FATAL Error at file \"%s\", Line %d Column: %d Message:%s",
129 sys.c_str(), int(e.getLineNumber()),
int(e.getColumnNumber()), m.c_str());
135 class DD4hepDOMParser :
public XercesDOMParser {
140 class Resolver :
public XMLEntityResolver {
143 Resolver(DD4hepDOMParser* p) :
parser(p) {}
144 virtual ~Resolver() {}
145 virtual InputSource *resolveEntity(XMLResourceIdentifier *
id)
146 {
return parser->read_uri(
id); }
157 virtual ~DD4hepDOMParser() {
161 InputSource *read_uri(XMLResourceIdentifier *
id) {
163 string buf, systemID(
_toString(id->getSystemId()));
165 const XMLByte* input = (
const XMLByte*)XMLString::replicate(buf.c_str());
167 string baseURI(
_toString(id->getBaseURI()));
168 string schema(
_toString(id->getSchemaLocation()));
170 printout(
INFO,
"XercesC",
"+++ Resolved URI: sysID:%s uri:%s ns:%s schema:%s",
171 systemID.c_str(), baseURI.c_str(),
ns.c_str(), schema.c_str());
173 return new MemBufInputSource(input,buf.length(),systemID.c_str(),
true);
181 XercesDOMParser* make_parser(
UriReader* reader=0) {
182 XercesDOMParser*
parser =
new DD4hepDOMParser(reader);
183 parser->setValidationScheme(XercesDOMParser::Val_Auto);
184 parser->setValidationSchemaFullChecking(
true);
185 parser->setCreateEntityReferenceNodes(
false);
186 parser->setDoNamespaces(
false);
187 parser->setDoSchema(
true);
195 DOMImplementation *imp = DOMImplementationRegistry::getDOMImplementation(
Strng_t(
"LS"));
196 MemBufFormatTarget *tar =
new MemBufFormatTarget();
197 DOMLSOutput *out = imp->createLSOutput();
198 DOMLSSerializer *wrt = imp->createLSSerializer();
199 out->setByteStream(tar);
200 wrt->getDomConfig()->setParameter(
Strng_t(
"format-pretty-print"),
true);
201 wrt->write(doc, out);
202 os << tar->getRawBuffer() << endl << flush;
207 printout(
ERROR,
"dumpTree",
"+++ Cannot dump invalid document.");
226 string DocumentHandler::system_path(
Handle_t base,
const string& fn) {
227 string path, dir = system_path(base);
228 TUri uri_base(dir.c_str()), uri_rel(fn.c_str());
229 TUrl url_base(dir.c_str());
230 path = TUri::MergePaths(uri_rel,uri_base);
231 TUri
final(path.c_str());
233 path = url_base.GetProtocol()+string(
"://")+
final.GetUri().Data();
234 if ( path[path.length()-1]==
'/' ) path = path.substr(0,path.length()-1);
239 string DocumentHandler::system_path(
Handle_t base) {
240 DOMElement* elt = (DOMElement*)base.
ptr();
241 string path =
_toString(elt->getBaseURI());
242 if ( path[0] ==
'/' ) {
243 string tmp =
"file:"+path;
252 DOMElement* elt = (DOMElement*)base.
ptr();
255 XMLURL ref_url(elt->getBaseURI(), p);
257 return load(path, reader);
259 catch(
const exception& exc) {
262 printout(
DEBUG,
"DocumentHandler",
"+++ URI exception: %s -> %s [%s]",b.c_str(),e.c_str(),exc.what());
267 printout(
DEBUG,
"DocumentHandler",
"+++ URI exception: %s -> %s",b.c_str(),e.c_str());
270 string buf, sys = system_path(base,fname);
272 string buf, sys, dir =
_toString(elt->getBaseURI());
274 dir = ::dirname((
char*)dir.c_str());
275 while( fn.substr(0,3) ==
"../" ) {
276 dir = ::dirname((
char*)dir.c_str());
279 sys = dir +
"/" + fn;
281 if ( reader->
load(sys, buf) ) {
283 Document doc =
parse(buf.c_str(), buf.length(), sys.c_str(), reader);
287 return parse(buf.c_str(), buf.length(), sys.c_str(), reader);
296 printout(
DEBUG,
"DocumentHandler",
"+++ Loading document URI: %s",fname.c_str());
298 size_t idx = fname.find(
':');
299 size_t idq = fname.find(
'/');
300 if ( idq == string::npos ) idq = 0;
301 XMLURL xerurl = (
const XMLCh*)
Strng_t(idx==string::npos || idx>idq ?
"file:"+fname : fname);
302 string proto =
_toString(xerurl.getProtocolName());
304 printout(
DEBUG,
"DocumentHandler",
"+++ protocol:%s path:%s",proto.c_str(), path.c_str());
310 if ( !path.empty() ) {
311 parser->parse(path.c_str());
315 if ( reader && reader->
load(fname, path) ) {
316 MemBufInputSource src((
const XMLByte*)path.c_str(), path.length(), fname.c_str(),
false);
318 return (XmlDocument*)parser->adoptDocument();
320 return (XmlDocument*)0;
323 catch (
const exception& e) {
324 printout(
ERROR,
"DocumentHandler",
"+++ Exception(XercesC): parse(path):%s",e.what());
326 parser->parse(fname.c_str());
329 catch (
const exception& ex) {
330 printout(
FATAL,
"DocumentHandler",
"+++ Exception(XercesC): parse(URI):%s",ex.what());
334 printout(
DEBUG,
"DocumentHandler",
"+++ Document %s succesfully parsed with XercesC .....",path.c_str());
335 return (XmlDocument*)parser->adoptDocument();
341 MemBufInputSource src((
const XMLByte*)bytes, length, sys_id,
false);
343 DOMDocument* doc = parser->adoptDocument();
344 doc->setXmlStandalone(
true);
345 doc->setStrictErrorChecking(
true);
346 return (XmlDocument*) doc;
350 int DocumentHandler::output(
Document doc,
const string& fname)
const {
351 XMLFormatTarget *tar = 0;
352 DOMImplementation *imp = DOMImplementationRegistry::getDOMImplementation(
Strng_t(
"LS"));
353 DOMLSOutput *out = imp->createLSOutput();
354 DOMLSSerializer *wrt = imp->createLSSerializer();
357 tar =
new StdOutFormatTarget();
359 tar =
new LocalFileFormatTarget(
Strng_t(fname));
361 out->setByteStream(tar);
362 wrt->getDomConfig()->setParameter(
Strng_t(
"format-pretty-print"),
true);
363 wrt->write((xercesc::DOMDocument*) doc.
ptr(), out);
383 Xml(
void* ptr) : p(ptr) {}
384 Xml(
const void* ptr) : cp(ptr) {}
398 static string _clean_fname(
const string&
s) {
400 std::string temp2 = temp.empty() ? s : temp;
401 if ( strncmp(temp2.c_str(),
"file:",5)==0 )
return temp2.substr(5);
407 string DocumentHandler::system_path(
Handle_t base,
const string& fname) {
408 string fn, clean = _clean_fname(fname);
413 string bn =
Xml(elt.document()).d->Value();
415 char drive[_MAX_DRIVE], dir[_MAX_DIR], file[_MAX_FNAME], ext[_MAX_EXT];
416 ::_splitpath(bn.c_str(),drive,dir,file,ext);
423 fn = ::dirname((
char*)bn.c_str());
426 fn += _clean_fname(fname);
428 if ( ::stat(fn.c_str(),&st)==0 )
430 else if ( ::stat(clean.c_str(),&st)==0 )
436 string DocumentHandler::system_path(
Handle_t base) {
441 fn =
Xml(elt.document()).d->Value();
448 string clean = _clean_fname(fname);
451 fname.c_str(),
"[URI Resolution is not supported by TiXML]");
454 printout(
INFO,
"DocumentHandler",
"+++ Loading document URI: %s",fname.c_str());
461 if ( doc->
Error() ) {
463 printout(
FATAL,
"DocumentHandler",
"+++ Document:%s Location Line:%d Column:%d",
465 throw runtime_error(
string(
"DD4hep: ")+doc->
ErrorDesc());
467 throw runtime_error(
"DD4hep: Unknown error whaile parsing XML document with TinyXML.");
470 catch(exception& e) {
471 printout(
ERROR,
"DocumentHandler",
"+++ Exception (TinyXML): parse(path):%s",e.what());
474 printout(
INFO,
"DocumentHandler",
"+++ Document %s succesfully parsed with TinyXML .....",fname.c_str());
475 return (XmlDocument*)doc;
483 string path = system_path(base, fname);
484 return load(path,reader);
491 "[URI Resolution is not supported by TiXML]");
495 if ( 0 == doc->
Parse(bytes) ) {
496 return (XmlDocument*)doc;
498 if ( doc->
Error() ) {
500 printout(
FATAL,
"DocumentHandler",
"+++ Document:%s Location Line:%d Column:%d",
502 throw runtime_error(
string(
"DD4hep: ")+doc->
ErrorDesc());
504 throw runtime_error(
"DD4hep: Unknown error whaile parsing XML document with TiXml.");
506 catch(exception& e) {
507 printout(
ERROR,
"DocumentHandler",
"+++ Exception (TinyXML): parse(string):%s",e.what());
514 int DocumentHandler::output(
Document doc,
const string& fname)
const {
515 FILE* file = fname.empty() ? stdout : ::fopen(fname.c_str(),
"w");
517 printout(
ERROR,
"DocumentHandler",
"+++ Failed to open output file: %s",fname.c_str());
522 if ( !fname.empty() ) ::fclose(file);
547 DocumentHandler::DocumentHandler() {}
550 DocumentHandler::~DocumentHandler() {}
554 return load(fname, 0);
559 return load(base, fname, 0);
564 return parse(bytes, length,
"xml-memory-buffer", 0);
570 return system_path(base, fn);
575 string path = system_path(base,fname);
576 string dir = ::dirname((
char*)path.c_str());
581 string DocumentHandler::system_directory(
Handle_t base) {
582 string path = system_path(base);
583 string dir = ::dirname((
char*)path.c_str());
588 Document DocumentHandler::create(
const char* tag,
const char* comment)
const {
590 string empty =
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
591 empty +=
"<" + top +
"/>\0\0";
TinyXML class. See http://www.grinninglizard.com/tinyxml.
XercesC internal class. Not described here.
void addComment(const char *text) const
Add comment node to the element.
XML-DOM ERror handler class for the XercesC document parser.
std::string getEnviron(const std::string &env)
Helper function to lookup environment from the expression evaluator.
const std::string & Str()
Return the result.
void dump_tree(Document doc, ostream &os)
Dump DOM tree using XercesC handles.
DOC ptr() const
Accessot to DOM document behaviour.
void dump_tree(Handle_t elt, ostream &os)
Dump DOM tree using XercesC handles.
virtual bool load(const std::string &system_id, std::string &data)
Resolve a given URI to a string containing the data.
Out version of the std auto_ptr implementation base either on auto_ptr or unique_ptr.
User abstraction class to manipulate XML elements within a document.
const char * Value() const
Handle_t root() const
Access the ROOT eleemnt of the DOM document.
TinyXML class. See http://www.grinninglizard.com/tinyxml.
static pair< TClass *, void * > load(TBranch *branch, int entry)
int ErrorCol() const
The column where the error occured. See ErrorRow()
Class supporting to read data given a URI.
void warning(const SAXParseException &)
Warnings callback. Ignore them.
virtual const char * Parse(const char *p, TiXmlParsingData *data=0, TiXmlEncoding encoding=TIXML_DEFAULT_ENCODING)
TinyXML class. See http://www.grinninglizard.com/tinyxml.
Helper class to encapsulate a unicode string.
virtual void parserLoaded(const std::string &system_id)
Inform reader about a locally (e.g. by XercesC) handled source load.
virtual ~DocumentErrorHandler()
Destructor.
virtual bool Accept(TiXmlVisitor *visitor) const =0
virtual bool Accept(TiXmlVisitor *content) const
UriReader * m_reader
Pointer to URI reader.
void dump_doc(DOMDocument *doc, ostream &os)
Dump DOM tree using XercesC handles.
DocumentErrorHandler()
Constructor.
void resetErrors()
Reset errors (Noop)
int parse(Property &result, const std::string &input)
TinyXML class. See http://www.grinninglizard.com/tinyxml.
bool LoadFile(TiXmlEncoding encoding=TIXML_DEFAULT_ENCODING)
const char * ErrorDesc() const
Contains a textual (english) description of the error if one occurs.
Class to easily access the properties of single XmlElements.
Class supporting the basic functionality of an XML document.
Union to ease castless object access when using XercesC.
const XmlAttr * Attribute
void dumpTree(DOMNode *doc, ostream &os)
Dump DOM tree using XercesC handles.
Elt_t ptr() const
Direct access to the XmlElement by function.
TinyXML class. See http://www.grinninglizard.com/tinyxml.
int printout(PrintLevel severity, const char *src, const char *fmt,...)
Calls the display action with a given severity level.
XercesC internal class. Not described here.
DocumentErrorHandler m_errHandler
Xerces Error handler.
static std::string _toString(const DD4hep::XML::XmlChar *value)
std::string conversion of XML strings (e.g. Unicode for Xerces-C)