23 #include <sys/types.h>
33 std::string undressed_file_name(
const std::string& fn) {
36 gSystem->ExpandPathName(tfn);
37 return std::string(tfn.Data());
41 int s_minPrintLevel = dd4hep::INFO;
43 std::string _clean_fname(
const std::string& filepath) {
45 std::string
const& temp =
getEnviron(filepath);
46 std::string temp2 = undressed_file_name( temp.empty() ? filepath : temp );
47 if ( strncmp(temp2.c_str(),
"file:",5)==0 )
return temp2.substr(5);
54 #include <xercesc/framework/LocalFileFormatTarget.hpp>
55 #include <xercesc/framework/StdOutFormatTarget.hpp>
56 #include <xercesc/framework/MemBufFormatTarget.hpp>
57 #include <xercesc/framework/MemBufInputSource.hpp>
58 #include <xercesc/sax/SAXParseException.hpp>
59 #include <xercesc/sax/EntityResolver.hpp>
60 #include <xercesc/sax/InputSource.hpp>
61 #include <xercesc/parsers/XercesDOMParser.hpp>
62 #include <xercesc/util/XMLEntityResolver.hpp>
63 #include <xercesc/util/PlatformUtils.hpp>
64 #include <xercesc/util/XercesDefs.hpp>
65 #include <xercesc/util/XMLUni.hpp>
66 #include <xercesc/util/XMLURL.hpp>
67 #include <xercesc/util/XMLString.hpp>
68 #include <xercesc/dom/DOM.hpp>
69 #include <xercesc/sax/ErrorHandler.hpp>
71 using namespace xercesc;
87 printout(DEBUG,
"DocumentErrorHandler",
"+++ Destructing the XercesC DOM-XML document error handler....");
96 void error(
const SAXParseException& e);
98 void fatalError(
const SAXParseException& e);
100 virtual bool handleError(
const DOMError& domError);
105 std::string err =
"DOM UNKNOWN: ";
106 switch (domError.getSeverity()) {
107 case DOMError::DOM_SEVERITY_WARNING:
108 err =
"DOM WARNING: ";
110 case DOMError::DOM_SEVERITY_ERROR:
113 case DOMError::DOM_SEVERITY_FATAL_ERROR:
119 printout(FATAL,
"DocumentErrorHandler",
"+++ %s %s: %s", err.c_str(),
121 DOMLocator* loc = domError.getLocation();
123 printout(FATAL,
"DocumentErrorHandler",
"+++ Location: Line:%d Column: %d",
124 int(loc->getLineNumber()),
int(loc->getColumnNumber()));
130 std::string m(
_toString(e.getMessage()));
131 if (m.find(
"The values for attribute 'name' must be names or name tokens") != std::string::npos
132 || m.find(
"The values for attribute 'ID' must be names or name tokens") != std::string::npos
133 || m.find(
"for attribute 'name' must be Name or Nmtoken") != std::string::npos
134 || m.find(
"for attribute 'ID' must be Name or Nmtoken") != std::string::npos
135 || m.find(
"for attribute 'name' is invalid Name or NMTOKEN value") != std::string::npos
136 || m.find(
"for attribute 'ID' is invalid Name or NMTOKEN value") != std::string::npos)
138 std::string sys(
_toString(e.getSystemId()));
139 printout(ERROR,
"XercesC",
"+++ Error at file \"%s\", Line %d Column: %d Message:%s",
140 sys.c_str(),
int(e.getLineNumber()),
int(e.getColumnNumber()), m.c_str());
144 std::string m(
_toString(e.getMessage()));
145 std::string sys(
_toString(e.getSystemId()));
146 printout(FATAL,
"XercesC",
"+++ FATAL Error at file \"%s\", Line %d Column: %d Message:%s",
147 sys.c_str(),
int(e.getLineNumber()),
int(e.getColumnNumber()), m.c_str());
153 class dd4hepDOMParser :
public XercesDOMParser {
158 class Resolver :
public XMLEntityResolver {
161 Resolver(dd4hepDOMParser* p) :
parser(p) {}
162 virtual ~Resolver() {}
163 virtual InputSource *resolveEntity(XMLResourceIdentifier *
id)
164 {
return parser->read_uri(
id); }
175 virtual ~dd4hepDOMParser() {
179 InputSource *read_uri(XMLResourceIdentifier *
id) {
181 std::string buf, systemID(
_toString(id->getSystemId()));
183 const XMLByte* input = (
const XMLByte*)XMLString::replicate(buf.c_str());
185 std::string baseURI(
_toString(id->getBaseURI()));
186 std::string schema(
_toString(id->getSchemaLocation()));
188 if ( s_minPrintLevel <= INFO ) {
189 printout(INFO,
"XercesC",
"+++ Resolved URI: sysID:%s uri:%s ns:%s schema:%s",
190 systemID.c_str(), baseURI.c_str(),
ns.c_str(), schema.c_str());
193 return new MemBufInputSource(input,buf.length(),systemID.c_str(),
true);
201 XercesDOMParser* make_parser(
UriReader* reader=0) {
202 XercesDOMParser*
parser =
new dd4hepDOMParser(reader);
203 parser->setValidationScheme(XercesDOMParser::Val_Auto);
204 parser->setValidationSchemaFullChecking(
true);
205 parser->setCreateEntityReferenceNodes(
false);
206 parser->setDoNamespaces(
false);
207 parser->setDoSchema(
true);
220 DOMImplementation *imp = DOMImplementationRegistry::getDOMImplementation(
Strng_t(
"LS"));
221 MemBufFormatTarget *tar =
new MemBufFormatTarget();
222 DOMLSOutput *out = imp->createLSOutput();
223 DOMLSSerializer *wrt = imp->createLSSerializer();
224 out->setByteStream(tar);
225 wrt->getDomConfig()->setParameter(
Strng_t(
"format-pretty-print"),
true);
226 wrt->write(doc, out);
227 os << tar->getRawBuffer() << std::endl << std::flush;
232 printout(ERROR,
"dumpTree",
"+++ Cannot dump invalid document.");
236 void dump_doc(DOMDocument* doc, std::ostream& os) {
253 std::string path = system_path(base);
254 std::string dir = ::dirname((
char*)path.c_str());
265 std::string path, dir = system_path(base);
266 TUri uri_base(dir.c_str()), uri_rel(fn.c_str());
267 TUrl url_base(dir.c_str());
268 path = TUri::MergePaths(uri_rel,uri_base);
269 TUri
final(path.c_str());
271 path = url_base.GetProtocol()+std::string(
"://")+
final.GetUri().Data();
272 if ( path[path.length()-1]==
'/' ) path = path.substr(0,path.length()-1);
278 DOMElement* elt = (DOMElement*)base.
ptr();
279 std::string path =
_toString(elt->getBaseURI());
280 if ( path[0] ==
'/' ) {
281 std::string tmp =
"file:"+path;
290 DOMElement* elt = (DOMElement*)base.
ptr();
297 XMLURL ref_url(elt->getBaseURI(), p);
302 return load(path, reader);
305 std::string b =
_toString(elt->getBaseURI());
307 printout(DEBUG,
"DocumentHandler",
"+++ URI exception: %s -> %s [%s]",b.c_str(),e.c_str(),exc.what());
310 std::string b =
_toString(elt->getBaseURI());
312 printout(DEBUG,
"DocumentHandler",
"+++ URI exception: %s -> %s",b.c_str(),e.c_str());
315 std::string buf, sys = system_path(base,fname);
317 std::string buf, sys, dir =
_toString(elt->getBaseURI());
319 dir = ::dirname((
char*)dir.c_str());
320 while( fn.substr(0,3) ==
"../" ) {
321 dir = ::dirname((
char*)dir.c_str());
324 sys = dir +
"/" + fn;
326 if ( reader->
load(sys, buf) ) {
328 Document doc =
parse(buf.c_str(), buf.length(), sys.c_str(), reader);
332 return parse(buf.c_str(), buf.length(), sys.c_str(), reader);
340 auto fname_clean = _clean_fname(fname);
342 printout(DEBUG,
"DocumentHandler",
"+++ Loading document URI: %s",fname_clean.c_str());
344 size_t idx = fname_clean.find(
':');
345 size_t idq = fname_clean.find(
'/');
346 if ( idq == std::string::npos ) idq = 0;
347 XMLURL xerurl = (
const XMLCh*)
Strng_t(idx==std::string::npos || idx>idq ?
"file:"+fname_clean : fname_clean);
348 std::string proto =
_toString(xerurl.getProtocolName());
350 printout(DEBUG,
"DocumentHandler",
"+++ protocol:%s path:%s",proto.c_str(), path.c_str());
354 std::unique_ptr < XercesDOMParser >
parser(make_parser(reader));
356 if ( !path.empty() ) {
357 parser->parse(path.c_str());
361 if ( reader && reader->
load(fname_clean, path) ) {
362 MemBufInputSource src((
const XMLByte*)path.c_str(), path.length(), fname.c_str(),
false);
364 return (XmlDocument*)
parser->adoptDocument();
366 return (XmlDocument*)0;
370 printout(ERROR,
"DocumentHandler",
"+++ Exception(XercesC): parse(path):%s",e.what());
372 parser->parse(fname.c_str());
376 printout(FATAL,
"DocumentHandler",
"+++ Exception(XercesC): parse(URI):%s",ex.what());
380 printout(DEBUG,
"DocumentHandler",
"+++ Document %s succesfully parsed with XercesC .....",path.c_str());
381 return (XmlDocument*)
parser->adoptDocument();
386 std::unique_ptr < XercesDOMParser >
parser(make_parser(rdr));
387 MemBufInputSource src((
const XMLByte*)bytes, length, sys_id,
false);
389 DOMDocument* doc =
parser->adoptDocument();
390 doc->setXmlStandalone(
true);
391 doc->setStrictErrorChecking(
true);
392 return (XmlDocument*) doc;
397 XMLFormatTarget *tar = 0;
398 DOMImplementation *imp = DOMImplementationRegistry::getDOMImplementation(
Strng_t(
"LS"));
399 DOMLSOutput *out = imp->createLSOutput();
400 DOMLSSerializer *wrt = imp->createLSSerializer();
403 tar =
new StdOutFormatTarget();
405 std::string fn = undressed_file_name(fname);
406 tar =
new LocalFileFormatTarget(
Strng_t(fn));
408 out->setByteStream(tar);
409 wrt->getDomConfig()->setParameter(
Strng_t(
"format-pretty-print"),
true);
410 wrt->write((xercesc::DOMDocument*) doc.
ptr(), out);
430 Xml(
void* ptr) : p(ptr) {}
431 Xml(
const void* ptr) : cp(ptr) {}
446 std::string fn, clean = _clean_fname(fname);
451 std::string bn =
Xml(elt.document()).
d->Value();
453 char drive[_MAX_DRIVE], dir[_MAX_DIR], file[_MAX_FNAME], ext[_MAX_EXT];
454 ::_splitpath(bn.c_str(),drive,dir,file,ext);
461 fn = ::dirname((
char*)bn.c_str());
464 fn += _clean_fname(fname);
466 if ( ::stat(fn.c_str(),&st)==0 )
468 else if ( ::stat(clean.c_str(),&st)==0 )
479 fn =
Xml(elt.document()).
d->Value();
481 return undressed_file_name(fn);
486 std::string clean = _clean_fname(fname);
488 printout(WARNING,
"DocumentHandler",
"+++ Loading document URI: %s %s",
489 fname.c_str(),
"[URI Resolution is not supported by TiXML]");
491 else if ( s_minPrintLevel <= INFO ) {
492 printout(INFO,
"DocumentHandler",
"+++ Loading document URI: %s [Resolved:'%s']",
493 fname.c_str(),clean.c_str());
500 if ( doc->
Error() ) {
501 printout(FATAL,
"DocumentHandler",
"+++ Error (TinyXML) parsing XML document:%s [%s]",
502 fname.c_str(), clean.c_str());
503 printout(FATAL,
"DocumentHandler",
"+++ Error (TinyXML) XML parsing error:%s",
505 printout(FATAL,
"DocumentHandler",
"+++ Document:%s Location Line:%d Column:%d",
507 except(
"dd4hep:XML",
"++ file:%s error:%s",clean.c_str(),doc->
ErrorDesc());
509 except(
"dd4hep:XML",
"++ Unknown error (TinyXML) while parsing:%s",fname.c_str());
513 printout(ERROR,
"DocumentHandler",
"+++ Exception (TinyXML): parse(path):%s",e.what());
516 if ( s_minPrintLevel <= INFO ) {
517 printout(INFO,
"DocumentHandler",
"+++ Document %s succesfully parsed with TinyXML .....",
520 return (XmlDocument*)doc;
528 std::string path = system_path(base, fname);
529 return load(path,reader);
535 printout(WARNING,
"DocumentHandler",
"+++ Parsing memory document %s",
536 "[URI Resolution is not supported by TiXML]");
541 size_t str_len = ::strlen(bytes);
544 if ( str_len+1 != len || bytes[str_len] != 0 || ::isspace(bytes[str_len-1]) ) {
545 std::unique_ptr<char[]> data(
new char[len+1]);
546 char* buff = data.get();
548 ::memcpy(buff, bytes, len+1);
550 for(
size_t i=len-1; i>0 && (buff[i]==0 || ::isspace(buff[i])); --i)
552 if ( 0 == doc->
Parse(buff) ) {
553 return (XmlDocument*)doc;
559 if ( 0 == doc->
Parse(bytes) ) {
560 return (XmlDocument*)doc;
562 if ( doc->
Error() ) {
563 printout(FATAL,
"DocumentHandler",
564 "+++ Error (TinyXML) while parsing XML string [%s]",
566 printout(FATAL,
"DocumentHandler",
567 "+++ XML Document error: %s Location Line:%d Column:%d",
569 throw std::runtime_error(std::string(
"dd4hep: ")+doc->
ErrorDesc());
571 throw std::runtime_error(
"dd4hep: Unknown error while parsing XML document string with TiXml.");
573 throw std::runtime_error(
"dd4hep: FAILED to parse invalid document string [NULL] with TiXml.");
576 printout(ERROR,
"DocumentHandler",
"+++ Exception (TinyXML): parse(string):%s",e.what());
584 std::string fn = undressed_file_name(fname);
585 FILE* file = fn.empty() ? stdout : ::fopen(fn.c_str(),
"w");
587 printout(ERROR,
"DocumentHandler",
"+++ Failed to open output file: %s",fname.c_str());
592 if ( !fn.empty() ) ::fclose(file);
624 int tmp = s_minPrintLevel;
625 s_minPrintLevel = level;
631 const char comment[] =
"\n"
632 " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"
633 " ++++ dd4hep generated alignment file using the ++++\n"
634 " ++++ dd4hep Detector description XML generator. ++++\n"
640 " ++++ M.Frank CERN/LHCb ++++\n"
641 " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n ";
647 return load(fname, 0);
652 return load(base, fname, 0);
657 return parse(bytes, length,
"xml-memory-buffer", 0);
663 return system_path(base, fn);
668 std::string path = system_path(base,fname);
669 std::string dir = ::dirname((
char*)path.c_str());
675 std::string path = system_path(base);
676 std::string dir = ::dirname((
char*)path.c_str());
682 std::string top(tag);
683 std::string empty =
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
684 empty +=
"<" + top +
"/>\0\0";
695 return create(tag.c_str(), comment.c_str());