File indexing completed on 2025-03-14 08:15:03
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifdef DD4HEP_USE_TINYXML
0016 #include <XML/tinyxml.h>
0017 #else
0018 #include <xercesc/util/Xerces_autoconf_config.hpp>
0019 #include <xercesc/util/XMLString.hpp>
0020 #include <xercesc/dom/DOMElement.hpp>
0021 #include <xercesc/dom/DOMDocument.hpp>
0022 #include <xercesc/dom/DOMNodeList.hpp>
0023 #include <xercesc/dom/DOM.hpp>
0024 #include <XML/config.h>
0025 #endif
0026
0027 #include <XML/XMLElements.h>
0028 #include <XML/Printout.h>
0029 #include <XML/XMLTags.h>
0030
0031
0032 #include <iostream>
0033 #include <stdexcept>
0034 #include <cstdio>
0035 #include <map>
0036
0037 using namespace dd4hep::xml;
0038 static const size_t INVALID_NODE = ~0U;
0039 static int s_float_precision = -1;
0040
0041
0042 namespace dd4hep {
0043 std::pair<int, double> _toInteger(const std::string& value);
0044 std::pair<int, double> _toFloatingPoint(const std::string& value);
0045 void _toDictionary(const std::string& name, const std::string& value, const std::string& typ);
0046 std::string _getEnviron(const std::string& env);
0047 }
0048
0049
0050 namespace {
0051 bool s_resolve_environment = true;
0052 std::string _checkEnviron(const std::string& env) {
0053 if ( s_resolve_environment ) {
0054 std::string r = dd4hep::_getEnviron(env);
0055 return r.empty() ? env : r;
0056 }
0057 return env;
0058 }
0059 }
0060
0061
0062 #define _D(x) Xml(x).d
0063 #define _E(x) Xml(x).e
0064 #define _N(x) Xml(x).n
0065 #define _L(x) Xml(x).l
0066 #define _XE(x) Xml(x).xe
0067
0068 #ifdef DD4HEP_USE_TINYXML
0069 #define ELEMENT_NODE_TYPE TiXmlNode::ELEMENT
0070 #define getTagName Value
0071 #define getTextContent GetText
0072 #define getName Name
0073 #define getValue Value
0074 #define getNodeValue Value
0075 #define getNodeType Type
0076 #define setNodeValue SetValue
0077 #define getParentNode Parent()->ToElement
0078 #define getAttributeNode(x) AttributeNode(x)
0079 #define appendChild LinkEndChild
0080 #define getOwnerDocument GetDocument
0081 #define getDocumentElement RootElement
0082 #define getDocumentURI Value
0083
0084
0085 union Xml {
0086 Xml(const void* ptr) : p(ptr) {}
0087 const void* p;
0088 TiXmlNode* n;
0089 TiXmlElement* e;
0090 TiXmlAttribute* a;
0091 TiXmlDocument* d;
0092 XmlElement* xe;
0093 };
0094
0095 namespace {
0096 XmlElement* node_first(XmlElement* e, const Tag_t& t) {
0097 if ( t.str()=="*" ) return e ? (XmlElement*)_E(e)->FirstChildElement() : 0;
0098 return e ? (XmlElement*)_E(e)->FirstChildElement(t.str()) : 0;
0099 }
0100 size_t node_count(XmlElement* elt, const Tag_t& t) {
0101 size_t cnt = 0;
0102 TiXmlElement* e = Xml(elt).e;
0103 if ( t.str()=="*" )
0104 for(e=e->FirstChildElement();e; e=e->NextSiblingElement()) ++cnt;
0105 else
0106 for(e=e->FirstChildElement(t.str());e; e=e->NextSiblingElement(t.str())) ++cnt;
0107 return cnt;
0108 }
0109 }
0110 XmlChar* dd4hep::xml::XmlString::replicate(const XmlChar* c) {
0111 return c ? ::strdup(c) : 0;
0112 }
0113 XmlChar* dd4hep::xml::XmlString::transcode(const char* c) {return c ? ::strdup(c) : 0;
0114 }
0115 void dd4hep::xml::XmlString::release(char** p) {
0116 if(p && *p) {::free(*p); *p=0;}
0117 }
0118 size_t dd4hep::xml::XmlString::length(const char* p) {
0119 return p ? ::strlen(p) : 0;
0120 }
0121
0122 #else
0123 #define ELEMENT_NODE_TYPE xercesc::DOMNode::ELEMENT_NODE
0124
0125
0126 union Xml {
0127 Xml(const void* ptr)
0128 : p(ptr) {
0129 }
0130 const void* p;
0131 xercesc::DOMNode* n;
0132 xercesc::DOMAttr* a;
0133 xercesc::DOMElement* e;
0134 xercesc::DOMDocument* d;
0135 xercesc::DOMNodeList* l;
0136 XmlElement* xe;
0137 };
0138
0139 XmlChar* dd4hep::xml::XmlString::replicate(const XmlChar* c) {
0140 return xercesc::XMLString::replicate(c);
0141 }
0142 char* dd4hep::xml::XmlString::transcode(const XmlChar* c) {
0143 return xercesc::XMLString::transcode(c);
0144 }
0145 XmlChar* dd4hep::xml::XmlString::transcode(const char* c) {
0146 return xercesc::XMLString::transcode(c);
0147 }
0148 void dd4hep::xml::XmlString::release(XmlChar** p) {
0149 return xercesc::XMLString::release(p);
0150 }
0151 void dd4hep::xml::XmlString::release(char** p) {
0152 return xercesc::XMLString::release(p);
0153 }
0154 size_t dd4hep::xml::XmlString::length(const char* p) {
0155 return p ? xercesc::XMLString::stringLen(p) : 0;
0156 }
0157 size_t dd4hep::xml::XmlString::length(const XmlChar* p) {
0158 return p ? xercesc::XMLString::stringLen(p) : 0;
0159 }
0160
0161 namespace {
0162 size_t node_count(XmlElement* e, const Tag_t& t) {
0163 size_t cnt = 0;
0164 if ( e ) {
0165 const std::string& tag = t;
0166 xercesc::DOMElement *ee = Xml(e).e;
0167 if ( ee ) {
0168 for(xercesc::DOMElement* elt=ee->getFirstElementChild(); elt; elt=elt->getNextElementSibling()) {
0169 if ( elt->getParentNode() == ee ) {
0170 std::string child_tag = _toString(elt->getTagName());
0171 if ( tag == "*" || child_tag == tag ) ++cnt;
0172 }
0173 }
0174 }
0175 }
0176 return cnt;
0177 }
0178 XmlElement* node_first(XmlElement* e, const Tag_t& t) {
0179 if ( e ) {
0180 const std::string& tag = t;
0181 xercesc::DOMElement* ee = Xml(e).e;
0182 if ( ee ) {
0183 for(xercesc::DOMElement* elt=ee->getFirstElementChild(); elt; elt=elt->getNextElementSibling()) {
0184 if ( elt->getParentNode() == ee ) {
0185 if ( tag == "*" ) return _XE(elt);
0186 std::string child_tag = _toString(elt->getTagName());
0187 if ( child_tag == tag ) return _XE(elt);
0188 }
0189 }
0190 }
0191 }
0192 return 0;
0193 }
0194 }
0195
0196
0197 std::string dd4hep::xml::_toString(const XmlChar *toTranscode) {
0198 char *buff = XmlString::transcode(toTranscode);
0199 std::string tmp(buff == 0 ? "" : buff);
0200 XmlString::release(&buff);
0201 if ( tmp.length()<3 ) return tmp;
0202 if ( !(tmp[0] == '$' && tmp[1] == '{') ) return tmp;
0203 tmp = _checkEnviron(tmp);
0204 return tmp;
0205 }
0206 #endif
0207
0208 namespace {
0209 Attribute attribute_node(XmlElement* n, const XmlChar* t) {
0210 return Attribute(_E(n)->getAttributeNode(t));
0211 }
0212 const XmlChar* attribute_value(Attribute a) {
0213 return Xml(a).a->getValue();
0214 }
0215 #if 0
0216 int node_type(XmlNode* n) {return Xml(n).n->getNodeType();}
0217 int node_type(Handle_t n) {return Xml(n.ptr()).n->getNodeType();}
0218 #endif
0219 }
0220
0221
0222 int dd4hep::xml::set_float_precision(int precision) {
0223 int tmp = s_float_precision;
0224 s_float_precision = precision;
0225 return tmp;
0226 }
0227
0228
0229 int dd4hep::xml::get_float_precision() {
0230 return s_float_precision;
0231 }
0232
0233
0234 std::string dd4hep::xml::_toString(Attribute attr) {
0235 if (attr)
0236 return _toString(attribute_value(attr));
0237 return "";
0238 }
0239
0240 template <typename T> static inline std::string __to_string(T value, const char* fmt) {
0241 char text[128];
0242 ::snprintf(text, sizeof(text), fmt, value);
0243 return text;
0244 }
0245
0246
0247 std::string dd4hep::xml::_toString(const char* s) {
0248 if ( !s || *s == 0 ) return "";
0249 else if ( !(*s == '$' && *(s+1) == '{') ) return s;
0250 return _checkEnviron(s);
0251 }
0252
0253
0254 std::string dd4hep::xml::_toString(const std::string& s) {
0255 if ( s.length() < 3 || s[0] != '$' ) return s;
0256 else if ( !(s[0] == '$' && s[1] == '{') ) return s;
0257 return _checkEnviron(s);
0258 }
0259
0260
0261 std::string dd4hep::xml::_toString(unsigned long v, const char* fmt) {
0262 return __to_string(v, fmt);
0263 }
0264
0265
0266 std::string dd4hep::xml::_toString(unsigned int v, const char* fmt) {
0267 return __to_string(v, fmt);
0268 }
0269
0270
0271 std::string dd4hep::xml::_toString(int v, const char* fmt) {
0272 return __to_string(v, fmt);
0273 }
0274
0275
0276 std::string dd4hep::xml::_toString(long v, const char* fmt) {
0277 return __to_string(v, fmt);
0278 }
0279
0280
0281 std::string dd4hep::xml::_toString(float v, const char* fmt) {
0282 if ( s_float_precision >= 0 ) {
0283 char format[32];
0284 ::snprintf(format, sizeof(format), "%%.%de", s_float_precision);
0285 return __to_string(v, format);
0286 }
0287 return __to_string(v, fmt);
0288 }
0289
0290
0291 std::string dd4hep::xml::_toString(double v, const char* fmt) {
0292 if ( s_float_precision >= 0 ) {
0293 char format[32];
0294 ::snprintf(format, sizeof(format), "%%.%de", s_float_precision);
0295 return __to_string(v, format);
0296 }
0297 return __to_string(v, fmt);
0298 }
0299
0300
0301 std::string dd4hep::xml::_toString(const Strng_t& s) {
0302 return _toString(Tag_t(s));
0303 }
0304
0305
0306 std::string dd4hep::xml::_toString(const Tag_t& s) {
0307 return s.str();
0308 }
0309
0310
0311 std::string dd4hep::xml::_ptrToString(const void* v, const char* fmt) {
0312 return __to_string(v, fmt);
0313 }
0314
0315 long dd4hep::xml::_toLong(const XmlChar* value) {
0316 if (value) {
0317 std::string s = _toString(value);
0318 return dd4hep::_toInteger(s).second;
0319 }
0320 return -1;
0321 }
0322
0323 unsigned long dd4hep::xml::_toULong(const XmlChar* value) {
0324 long val = _toLong(value);
0325 if ( val >= 0 ) return (unsigned long) val;
0326 std::string s = _toString(value);
0327 throw std::runtime_error("dd4hep: Severe error during expression evaluation of " + s);
0328 }
0329
0330 int dd4hep::xml::_toInt(const XmlChar* value) {
0331 return (int)_toLong(value);
0332 }
0333
0334 unsigned int dd4hep::xml::_toUInt(const XmlChar* value) {
0335 return (unsigned int)_toULong(value);
0336 }
0337
0338 bool dd4hep::xml::_toBool(const XmlChar* value) {
0339 if (value) {
0340 std::string s = _toString(value);
0341 char c = ::toupper(s[0]);
0342 if ( c == 'T' || c == '1' ) return true;
0343 if ( c == 'F' || c == '0' ) return false;
0344 return _toInt(value) != 0;
0345 }
0346 return false;
0347 }
0348
0349 float dd4hep::xml::_toFloat(const XmlChar* value) {
0350 if (value) {
0351 std::string s = _toString(value);
0352 return (float) dd4hep::_toFloatingPoint(s).second;
0353 }
0354 return 0.0;
0355 }
0356
0357 double dd4hep::xml::_toDouble(const XmlChar* value) {
0358 if (value) {
0359 std::string s = _toString(value);
0360 return dd4hep::_toFloatingPoint(s).second;
0361 }
0362 return 0.0;
0363 }
0364
0365 void dd4hep::xml::_toDictionary(const XmlChar* name, const XmlChar* value) {
0366 std::string n = _toString(name).c_str(), v = _toString(value);
0367 dd4hep::_toDictionary(n, v, "number");
0368 }
0369
0370
0371 void dd4hep::xml::_toDictionary(const XmlChar* name, const Strng_t& s) {
0372 return _toDictionary(name, s.ptr());
0373 }
0374
0375
0376 void dd4hep::xml::_toDictionary(const XmlChar* name, const Tag_t& t) {
0377 return _toDictionary(name, t.ptr());
0378 }
0379
0380 template <typename T>
0381 void dd4hep::xml::_toDictionary(const XmlChar* name, T value) {
0382 Strng_t item = _toString(value);
0383 const XmlChar* item_value = item;
0384 _toDictionary(name, item_value);
0385 }
0386
0387 #ifndef DD4HEP_USE_TINYXML
0388 template void dd4hep::xml::_toDictionary(const XmlChar* name, const char* value);
0389 #endif
0390 template void dd4hep::xml::_toDictionary(const XmlChar* name, const Tag_t& value);
0391 template void dd4hep::xml::_toDictionary(const XmlChar* name, const Strng_t& value);
0392 template void dd4hep::xml::_toDictionary(const XmlChar* name, const std::string& value);
0393 template void dd4hep::xml::_toDictionary(const XmlChar* name, unsigned long value);
0394 template void dd4hep::xml::_toDictionary(const XmlChar* name, unsigned int value);
0395 template void dd4hep::xml::_toDictionary(const XmlChar* name, unsigned short value);
0396 template void dd4hep::xml::_toDictionary(const XmlChar* name, int value);
0397 template void dd4hep::xml::_toDictionary(const XmlChar* name, long value);
0398 template void dd4hep::xml::_toDictionary(const XmlChar* name, short value);
0399 template void dd4hep::xml::_toDictionary(const XmlChar* name, float value);
0400 template void dd4hep::xml::_toDictionary(const XmlChar* name, double value);
0401
0402
0403 std::string dd4hep::xml::getEnviron(const std::string& env) {
0404 return dd4hep::_getEnviron(env);
0405 }
0406
0407
0408 bool dd4hep::xml::enableEnvironResolution(bool new_value) {
0409 bool tmp = s_resolve_environment;
0410 s_resolve_environment = new_value;
0411 return tmp;
0412 }
0413
0414 template <typename B>
0415 static inline std::string i_add(const std::string& a, B b) {
0416 std::string r = a;
0417 r += b;
0418 return r;
0419 }
0420
0421 Strng_t dd4hep::xml::operator+(const Strng_t& a, const std::string& b) {
0422 return _toString(a.ptr()) + b;
0423 }
0424
0425 Strng_t dd4hep::xml::operator+(const std::string& a, const Strng_t& b) {
0426 return a + _toString(b.ptr());
0427 }
0428
0429 Strng_t dd4hep::xml::operator+(const Strng_t& a, const char* b) {
0430 return _toString(a.ptr()) + b;
0431 }
0432
0433 Strng_t dd4hep::xml::operator+(const char* a, const Strng_t& b) {
0434 return std::string(a) + _toString(b.ptr());
0435 }
0436
0437 Strng_t dd4hep::xml::operator+(const Strng_t& a, const Strng_t& b) {
0438 return _toString(a.ptr()) + _toString(b.ptr());
0439 }
0440
0441 Tag_t dd4hep::xml::operator+(const Tag_t& a, const char* b) {
0442 std::string res = a.str() + b;
0443 return Tag_t(res);
0444 }
0445
0446 Tag_t dd4hep::xml::operator+(const char* a, const Tag_t& b) {
0447 std::string res = a + b.str();
0448 return Tag_t(res);
0449 }
0450
0451 Tag_t dd4hep::xml::operator+(const Tag_t& a, const Strng_t& b) {
0452 std::string res = a.str() + _toString(b);
0453 return Tag_t(res);
0454 }
0455
0456 Tag_t dd4hep::xml::operator+(const Tag_t& a, const std::string& b) {
0457 std::string res = a.str() + b;
0458 return Tag_t(res);
0459 }
0460
0461 #ifndef DD4HEP_USE_TINYXML
0462 Strng_t dd4hep::xml::operator+(const Strng_t& a, const XmlChar* b) {
0463 std::string res = _toString(a.ptr()) + _toString(b);
0464 return Tag_t(res);
0465 }
0466
0467 Strng_t dd4hep::xml::operator+(const XmlChar* a, const Strng_t& b) {
0468 std::string res = _toString(a) + _toString(b.ptr());
0469 return Tag_t(res);
0470 }
0471
0472 Strng_t dd4hep::xml::operator+(const XmlChar* a, const std::string& b) {
0473 std::string res = _toString(a) + b;
0474 return Tag_t(res);
0475 }
0476
0477 Strng_t dd4hep::xml::operator+(const std::string& a, const XmlChar* b) {
0478 std::string res = a + _toString(b);
0479 return Tag_t(res);
0480 }
0481
0482 Tag_t dd4hep::xml::operator+(const Tag_t& a, const XmlChar* b) {
0483 std::string res = a.str() + _toString(b);
0484 return Tag_t(res);
0485 }
0486
0487 Strng_t& Strng_t::operator=(const XmlChar* s) {
0488 if (m_xml)
0489 XmlString::release (&m_xml);
0490 m_xml = s ? XmlString::replicate(s) : 0;
0491 return *this;
0492 }
0493 #endif
0494
0495 Strng_t& Strng_t::operator=(const char* s) {
0496 if (m_xml)
0497 XmlString::release (&m_xml);
0498 m_xml = s ? XmlString::transcode(s) : 0;
0499 return *this;
0500 }
0501
0502 Strng_t& Strng_t::operator=(const Strng_t& s) {
0503 if (this != &s) {
0504 if (m_xml)
0505 XmlString::release (&m_xml);
0506 m_xml = XmlString::replicate(s.m_xml);
0507 }
0508 return *this;
0509 }
0510
0511 Strng_t& Strng_t::operator=(const std::string& s) {
0512 if (m_xml)
0513 XmlString::release (&m_xml);
0514 m_xml = XmlString::transcode(s.c_str());
0515 return *this;
0516 }
0517
0518 Tag_t& Tag_t::operator=(const Tag_t& s) {
0519 if (this != &s) {
0520 m_str = s.m_str;
0521 if (m_xml)
0522 XmlString::release (&m_xml);
0523 m_xml = XmlString::transcode(m_str.c_str());
0524 }
0525 return *this;
0526 }
0527
0528 Tag_t& Tag_t::operator=(const char* s) {
0529 if (m_xml)
0530 XmlString::release (&m_xml);
0531 if (s) {
0532 m_xml = XmlString::transcode(s);
0533 m_str = s;
0534 }
0535 else {
0536 m_xml = 0;
0537 m_str = "";
0538 }
0539 return *this;
0540 }
0541
0542 Tag_t& Tag_t::operator=(const Strng_t& s) {
0543 if (m_xml) {
0544 XmlString::release (&m_xml);
0545 }
0546 char* ns = s.m_xml ? XmlString::transcode(s.m_xml) : 0;
0547 m_str = ns ? ns : "";
0548 m_xml = XmlString::transcode(m_str.c_str());
0549 if (ns) {
0550 XmlString::release(&ns);
0551 }
0552 return *this;
0553 }
0554
0555 Tag_t& Tag_t::operator=(const std::string& s) {
0556 if (m_xml)
0557 XmlString::release (&m_xml);
0558 m_xml = XmlString::transcode(s.c_str());
0559 m_str = s;
0560 return *this;
0561 }
0562
0563
0564 NodeList::NodeList(const NodeList& copy)
0565 : m_tag(copy.m_tag), m_node(copy.m_node), m_ptr(0)
0566 {
0567 reset();
0568 }
0569
0570
0571 NodeList::NodeList(XmlElement* node, const XmlChar* tag_value)
0572 : m_tag(tag_value), m_node(node), m_ptr(0)
0573 {
0574 reset();
0575 }
0576
0577
0578 NodeList::~NodeList() {
0579 }
0580
0581
0582 XmlElement* NodeList::reset() {
0583 return m_ptr=node_first(m_node,m_tag);
0584 }
0585
0586
0587 XmlElement* NodeList::next() const {
0588 #ifdef DD4HEP_USE_TINYXML
0589 if ( m_tag.str()=="*" )
0590 return m_ptr =_XE(m_ptr ? _E(m_ptr)->NextSiblingElement() : 0);
0591 return m_ptr = _XE(m_ptr ? _E(m_ptr)->NextSiblingElement(m_tag.str()) : 0);
0592 #else
0593 xercesc::DOMElement *elt = Xml(m_ptr).e;
0594 for(elt=elt->getNextElementSibling(); elt; elt=elt->getNextElementSibling()) {
0595 if ( m_tag.str() == "*" ) return m_ptr=Xml(elt).xe;
0596 std::string child_tag = _toString(elt->getTagName());
0597 if ( child_tag == m_tag ) return m_ptr=Xml(elt).xe;
0598 }
0599 return m_ptr=0;
0600 #endif
0601 }
0602
0603
0604 XmlElement* NodeList::previous() const {
0605 #ifdef DD4HEP_USE_TINYXML
0606 if ( m_tag.str()=="*" )
0607 return m_ptr = _XE(m_ptr ? _E(m_ptr)->PreviousSiblingElement() : 0);
0608 return m_ptr = _XE(m_ptr ? _E(m_ptr)->PreviousSiblingElement(m_tag) : 0);
0609 #else
0610 xercesc::DOMElement *elt = Xml(m_ptr).e;
0611 for(elt=elt->getPreviousElementSibling(); elt; elt=elt->getPreviousElementSibling()) {
0612 if ( m_tag.str()=="*" ) return m_ptr=Xml(elt).xe;
0613 std::string child_tag = _toString(elt->getTagName());
0614 if ( child_tag == m_tag ) return m_ptr=Xml(elt).xe;
0615 }
0616 return m_ptr=0;
0617 #endif
0618 }
0619
0620
0621 NodeList& NodeList::operator=(const NodeList& l) {
0622 if (this != &l) {
0623 m_tag = l.m_tag;
0624 m_node = l.m_node;
0625 reset();
0626 }
0627 return *this;
0628 }
0629
0630
0631 const XmlChar* Handle_t::rawTag() const {
0632 return _E(m_node)->getTagName();
0633 }
0634
0635
0636 const XmlChar* Handle_t::rawText() const {
0637 return _E(m_node)->getTextContent();
0638 }
0639
0640
0641 const XmlChar* Handle_t::rawValue() const {
0642 return _N(m_node)->getNodeValue();
0643 }
0644
0645
0646 Handle_t Handle_t::clone(XmlDocument* new_doc) const {
0647 if (m_node) {
0648 #ifdef DD4HEP_USE_TINYXML
0649 if ( new_doc ) {}
0650 if ( _N(m_node)->Type() == ELEMENT_NODE_TYPE ) {
0651 XmlElement* e = _XE(_N(m_node)->Clone()->ToElement());
0652 if ( e ) return e;
0653 }
0654 throw std::runtime_error("TiXml: Handle_t::clone: Invalid source handle type [No element type].");
0655 #else
0656 return Elt_t(_D(new_doc)->importNode(_E(m_node), true));
0657 #endif
0658 }
0659 throw std::runtime_error("Xml: Handle_t::clone: Invalid source handle.");
0660 }
0661
0662
0663 Handle_t Handle_t::parent() const {
0664 return Elt_t(m_node ? _N(m_node)->getParentNode() : 0);
0665 }
0666
0667
0668 Attribute Handle_t::attr_nothrow(const XmlChar* tag_value) const {
0669 return attribute_node(m_node, tag_value);
0670 }
0671
0672
0673 bool Handle_t::hasAttr(const XmlChar* tag_value) const {
0674 return m_node && 0 != _E(m_node)->getAttributeNode(tag_value);
0675 }
0676
0677
0678 std::vector<Attribute> Handle_t::attributes() const {
0679 std::vector < Attribute > attrs;
0680 if (m_node) {
0681 #ifdef DD4HEP_USE_TINYXML
0682 for(TiXmlAttribute* a=_E(m_node)->FirstAttribute(); a; a=a->Next())
0683 attrs.emplace_back(Attribute(a));
0684 #else
0685 xercesc::DOMNamedNodeMap* l = _E(m_node)->getAttributes();
0686 for (XmlSize_t i = 0, n = l->getLength(); i < n; ++i) {
0687 xercesc::DOMNode* attr_node = l->item(i);
0688 attrs.emplace_back(Attribute(attr_node));
0689 }
0690 #endif
0691 }
0692 return attrs;
0693 }
0694
0695 size_t Handle_t::numChildren(const XmlChar* t, bool throw_exception) const {
0696 size_t n = node_count(m_node, t);
0697 if (n == INVALID_NODE && !throw_exception)
0698 return 0;
0699 else if (n != INVALID_NODE)
0700 return n;
0701 std::string msg = "Handle_t::numChildren: ";
0702 if (m_node)
0703 msg += "Element [" + tag() + "] has no children of type '" + _toString(t) + "'";
0704 else
0705 msg += "Element [INVALID] has no children of type '" + _toString(t) + "'";
0706 throw std::runtime_error(msg);
0707 }
0708
0709
0710 Handle_t Handle_t::child(const XmlChar* t, bool throw_exception) const {
0711 Elt_t e = node_first(m_node, t);
0712 if (e || !throw_exception)
0713 return e;
0714 std::string msg = "Handle_t::child: ";
0715 if (m_node)
0716 msg += "Element [" + tag() + "] has no child of type '" + _toString(t) + "'";
0717 else
0718 msg += "Element [INVALID]. Cannot remove child of type: '" + _toString(t) + "'";
0719 throw std::runtime_error(msg);
0720 }
0721
0722 NodeList Handle_t::children(const XmlChar* tag_value) const {
0723 return NodeList(m_node, tag_value);
0724 }
0725
0726
0727 void Handle_t::append(Handle_t e) const {
0728 _N(m_node)->appendChild(_N(e.ptr()));
0729 }
0730
0731
0732 Handle_t Handle_t::remove(Handle_t node) const {
0733 #ifdef DD4HEP_USE_TINYXML
0734 bool e = (m_node && node.ptr() ? _N(m_node)->RemoveChild(_N(node.ptr())) : false);
0735 #else
0736 Elt_t e = Elt_t(m_node && node.ptr() ? _N(m_node)->removeChild(_N(node.ptr())) : 0);
0737 #endif
0738 if (e)
0739 return node.ptr();
0740 std::string msg = "Handle_t::remove: ";
0741 if (m_node && node.ptr())
0742 msg += "Element [" + tag() + "] has no child of type '" + node.tag() + "'";
0743 else if (node)
0744 msg += "Element [INVALID]. Cannot remove child of type: '" + node.tag() + "'";
0745 else if (!node)
0746 msg += "Element [INVALID]. Cannot remove [INVALID] child. Big Shit!!!!";
0747
0748 throw std::runtime_error(msg);
0749 }
0750
0751
0752 void Handle_t::removeChildren(const XmlChar* tag_value) const {
0753 #ifdef DD4HEP_USE_TINYXML
0754 for(TiXmlNode* n=_E(m_node)->FirstChildElement(tag_value);n;n=_E(m_node)->FirstChildElement(tag_value))
0755 n->RemoveChild(n);
0756 #else
0757 xercesc::DOMElement* e = _E(m_node);
0758 xercesc::DOMNodeList* l = e->getElementsByTagName(tag_value);
0759 for (XmlSize_t i = 0, n = l->getLength(); i < n; ++i)
0760 e->removeChild(l->item(i));
0761 #endif
0762 }
0763
0764 bool Handle_t::hasChild(const XmlChar* tag_value) const {
0765 return node_first(m_node, tag_value) != 0;
0766 }
0767
0768
0769 void Handle_t::setValue(const XmlChar* text_value) const {
0770 _N(m_node)->setNodeValue(text_value);
0771 }
0772
0773
0774 void Handle_t::setValue(const std::string& text_value) const {
0775 #ifdef DD4HEP_USE_TINYXML
0776 _N(m_node)->setNodeValue(text_value.c_str());
0777 #else
0778 _N(m_node)->setNodeValue(Strng_t(text_value));
0779 #endif
0780 }
0781
0782
0783 void Handle_t::setText(const XmlChar* text_value) const {
0784 #ifdef DD4HEP_USE_TINYXML
0785 _N(m_node)->LinkEndChild(new TiXmlText(text_value));
0786 #else
0787 _N(m_node)->setTextContent(text_value);
0788 #endif
0789 }
0790
0791
0792 void Handle_t::setText(const std::string& text_value) const {
0793 #ifdef DD4HEP_USE_TINYXML
0794 _N(m_node)->LinkEndChild(new TiXmlText(text_value.c_str()));
0795 #else
0796 _N(m_node)->setTextContent(Strng_t(text_value));
0797 #endif
0798 }
0799
0800
0801 void Handle_t::removeAttrs() const {
0802 #ifdef DD4HEP_USE_TINYXML
0803 _E(m_node)->ClearAttributes();
0804 #else
0805 xercesc::DOMElement* e = _E(m_node);
0806 xercesc::DOMNamedNodeMap* l = e->getAttributes();
0807 for (XmlSize_t i = 0, n = l->getLength(); i < n; ++i) {
0808 xercesc::DOMAttr* a = (xercesc::DOMAttr*) l->item(i);
0809 e->removeAttributeNode(a);
0810 }
0811 #endif
0812 }
0813
0814
0815 #ifdef DD4HEP_USE_TINYXML
0816 void Handle_t::setAttrs(Handle_t elt) const {
0817 removeAttrs();
0818 TiXmlElement* e = Xml(elt).e;
0819 for(TiXmlAttribute* a=e->FirstAttribute(); a; a=a->Next())
0820 e->SetAttribute(a->Name(),a->Value());
0821 }
0822 #else
0823 void Handle_t::setAttrs(Handle_t ) const {
0824 removeAttrs();
0825 xercesc::DOMElement* e = _E(m_node);
0826 xercesc::DOMNamedNodeMap* l = e->getAttributes();
0827 for (XmlSize_t i = 0, len = l->getLength(); i < len; ++i) {
0828 xercesc::DOMNode* n = l->item(i);
0829 if (n->getNodeType() == xercesc::DOMNode::ATTRIBUTE_NODE) {
0830 xercesc::DOMAttr* a = (xercesc::DOMAttr*) n;
0831 e->setAttribute(a->getName(), a->getValue());
0832 }
0833 }
0834 }
0835 #endif
0836
0837
0838 Attribute Handle_t::attr_ptr(const XmlChar* t) const {
0839 Attribute a = attribute_node(m_node, t);
0840 if (0 != a)
0841 return a;
0842 std::string msg = "Handle_t::attr_ptr: ";
0843 if (m_node)
0844 msg += "Element [" + tag() + "] has no attribute of type '" + _toString(t) + "'";
0845 else
0846 msg += "Element [INVALID] has no attribute of type '" + _toString(t) + "'";
0847 throw std::runtime_error(msg);
0848 }
0849
0850
0851 const XmlChar* Handle_t::attr_name(const Attribute a) const {
0852 if (a) {
0853 return Xml(a).a->getName();
0854 }
0855 throw std::runtime_error("Attempt to access invalid XML attribute object!");
0856 }
0857
0858
0859 const XmlChar* Handle_t::attr_value(const XmlChar* attr_tag) const {
0860 return attribute_value(attr_ptr(attr_tag));
0861 }
0862
0863
0864 const XmlChar* Handle_t::attr_value(const Attribute attr_val) const {
0865 return attribute_value(attr_val);
0866 }
0867
0868
0869 const XmlChar* Handle_t::attr_value_nothrow(const XmlChar* attr_tag) const {
0870 Attribute a = attr_nothrow(attr_tag);
0871 return a ? attribute_value(a) : 0;
0872 }
0873
0874
0875 Attribute Handle_t::setAttr(const XmlChar* nam, int val) const {
0876 char txt[32];
0877 ::snprintf(txt, sizeof(txt), "%d", val);
0878 return setAttr(nam, Strng_t(txt));
0879 }
0880
0881
0882 Attribute Handle_t::setAttr(const XmlChar* name, bool val) const {
0883 char txt[32];
0884 ::snprintf(txt, sizeof(txt), "%s", val ? "true" : "false");
0885 return setAttr(name, Strng_t(txt));
0886 }
0887
0888
0889 Attribute Handle_t::setAttr(const XmlChar* name, float val) const {
0890 char txt[32];
0891 ::snprintf(txt, sizeof(txt), "%.8e", val);
0892 return setAttr(name, Strng_t(txt));
0893 }
0894
0895
0896 Attribute Handle_t::setAttr(const XmlChar* name, double val) const {
0897 char txt[32];
0898 ::snprintf(txt, sizeof(txt), "%.8e", val);
0899 return setAttr(name, Strng_t(txt));
0900 }
0901
0902
0903 Attribute Handle_t::setAttr(const XmlChar* name, const std::string& val) const {
0904 return setAttr(name, Strng_t(val.c_str()));
0905 }
0906
0907 #ifndef DD4HEP_USE_TINYXML
0908 Attribute Handle_t::setAttr(const XmlChar* name, const char* v) const {
0909 return setAttr(name, Strng_t(v));
0910 }
0911 #endif
0912
0913
0914 Attribute Handle_t::setAttr(const XmlChar* nam, const Attribute v) const {
0915 return v ? setAttr(nam, attribute_value(v)) : 0;
0916 }
0917
0918
0919 Attribute Handle_t::setAttr(const XmlChar* nam, const XmlChar* val) const {
0920 #ifdef DD4HEP_USE_TINYXML
0921 TiXmlElement* e = Xml(m_node).e;
0922 e->SetAttribute(nam,val);
0923 return Attribute(e->AttributeNode(nam));
0924 #else
0925 xercesc::DOMElement* e = _E(m_node);
0926 xercesc::DOMAttr* a = e->getAttributeNode(nam);
0927 if (!a) {
0928 a = e->getOwnerDocument()->createAttribute(nam);
0929 e->setAttributeNode(a);
0930 }
0931 a->setValue(val);
0932 return Attribute(a);
0933 #endif
0934 }
0935
0936
0937 Handle_t Handle_t::setRef(const XmlChar* tag_value, const XmlChar* ref_name) {
0938 Element me(*this);
0939 Element ref(me.document(), tag_value);
0940 ref.setAttr(Unicode_ref, ref_name);
0941 me.append(ref);
0942 return ref;
0943 }
0944
0945
0946 Handle_t Handle_t::setRef(const XmlChar* tag_value, const std::string& ref_name) {
0947 return setRef(tag_value, Strng_t(ref_name).ptr());
0948 }
0949
0950
0951 static unsigned int adler32(unsigned int adler, const XmlChar* xml_buff, size_t len) {
0952 #define DO1(buf,i) {s1 +=(unsigned char)buf[i]; s2 += s1;}
0953 #define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
0954 #define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
0955 #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
0956 #define DO16(buf) DO8(buf,0); DO8(buf,8);
0957
0958 static const unsigned int BASE = 65521;
0959
0960 static const unsigned int NMAX = 5550;
0961 unsigned int s1 = adler & 0xffff;
0962 unsigned int s2 = (adler >> 16) & 0xffff;
0963 const char* buf = (const char*)xml_buff;
0964
0965 if (buf == NULL)
0966 return 1;
0967
0968 while (len > 0) {
0969 int k = len < NMAX ? (int) len : NMAX;
0970 len -= k;
0971 while (k >= 16) {
0972 DO16(buf);
0973 buf += 16;
0974 k -= 16;
0975 }
0976 if (k != 0)
0977 do {
0978 s1 += (unsigned char) *buf++;
0979 s2 += s1;
0980 } while (--k);
0981 s1 %= BASE;
0982 s2 %= BASE;
0983 }
0984 unsigned int result = (s2 << 16) | s1;
0985 return result;
0986 }
0987
0988
0989 typedef unsigned int (fcn_t)(unsigned int, const XmlChar*, size_t);
0990 unsigned int Handle_t::checksum(unsigned int param, fcn_t fcn) const {
0991 #ifdef DD4HEP_USE_TINYXML
0992 typedef std::map<std::string, std::string> StringMap;
0993 TiXmlNode* n = Xml(m_node).n;
0994 if ( n ) {
0995 if ( 0 == fcn ) fcn = adler32;
0996 switch (n->Type()) {
0997 case TiXmlNode::ELEMENT: {
0998 std::map<std::string,std::string> m;
0999 TiXmlElement* e = n->ToElement();
1000 TiXmlAttribute* p=e->FirstAttribute();
1001 for(; p; p=p->Next()) m.emplace(p->Name(),p->Value());
1002 param = (*fcn)(param,e->Value(),::strlen(e->Value()));
1003 for(StringMap::const_iterator i=m.begin();i!=m.end();++i) {
1004 param = (*fcn)(param,(*i).first.c_str(),(*i).first.length());
1005 param = (*fcn)(param,(*i).second.c_str(),(*i).second.length());
1006 }
1007 break;
1008 }
1009 case TiXmlNode::TEXT:
1010 param = (*fcn)(param,n->ToText()->Value(),::strlen(n->ToText()->Value()));
1011 break;
1012 case TiXmlNode::UNKNOWN:
1013 case TiXmlNode::COMMENT:
1014 case TiXmlNode::DOCUMENT:
1015 case TiXmlNode::DECLARATION:
1016 default:
1017 break;
1018 }
1019 for(TiXmlNode* c=n->FirstChild(); c; c=c->NextSibling())
1020 param = Handle_t((XmlElement*)c->ToElement()).checksum(param,fcn);
1021 }
1022 #else
1023 if ( 0 == fcn ) fcn = adler32;
1024 if ( 0 == fcn ) {
1025 }
1026 #endif
1027 return param;
1028 }
1029
1030
1031 Handle_t Document::createElt(const XmlChar* tag_value) const {
1032 #ifdef DD4HEP_USE_TINYXML
1033 return _XE(new TiXmlElement(tag_value));
1034 #else
1035 return _XE(_D(m_doc)->createElement(tag_value));
1036 #endif
1037 }
1038
1039
1040 Handle_t Document::root() const {
1041 if (m_doc)
1042 return _XE(_D(m_doc)->getDocumentElement());
1043 throw std::runtime_error("Document::root: Invalid handle!");
1044 }
1045
1046
1047 std::string Document::uri() const {
1048 if (m_doc) {
1049 Tag_t val(_D(m_doc)->getDocumentURI());
1050 return val;
1051 }
1052 throw std::runtime_error("Document::uri: Invalid handle!");
1053 }
1054
1055
1056 DocumentHolder& DocumentHolder::assign(DOC d) {
1057 if (m_doc) {
1058 printout(DEBUG,"DocumentHolder","+++ Release DOM document....");
1059 #ifdef DD4HEP_USE_TINYXML
1060 delete _D(m_doc);
1061 #else
1062 _D(m_doc)->release();
1063 #endif
1064 }
1065 m_doc = d;
1066 return *this;
1067 }
1068
1069
1070 DocumentHolder::~DocumentHolder() {
1071 assign(0);
1072 }
1073
1074
1075 Element::Element(const Document& doc, const XmlChar* type)
1076 : m_element(Xml(doc.createElt(type)).xe) {
1077 }
1078
1079
1080 Element::Elt_t Element::parentElement() const {
1081 Handle_t p = m_element.parent();
1082 if ( p && _N(p.ptr())->getNodeType() == ELEMENT_NODE_TYPE ) {
1083 return Elt_t(p);
1084 }
1085 return Elt_t(0);
1086 }
1087
1088
1089 Document Element::document() const {
1090 return Document((XmlDocument*) (m_element ? _N(m_element)->getOwnerDocument() : 0));
1091 }
1092
1093
1094 Handle_t Element::clone(Handle_t h) const {
1095 if (m_element && h) {
1096 return h.clone(Document::DOC(document()));
1097 }
1098 throw std::runtime_error("Element::clone: Invalid element pointer -- unable to clone node!");
1099 }
1100
1101 Attribute Element::getAttr(const XmlChar* name) const {
1102 return m_element ? attribute_node(m_element, name) : 0;
1103 }
1104
1105
1106 Attribute Element::setRef(const XmlChar* tag_value, const XmlChar* ref_name) const {
1107 return setChild(tag_value).setAttr(Unicode_ref, ref_name);
1108 }
1109
1110
1111 Attribute Element::setRef(const XmlChar* tag_value, const std::string& ref_name) const {
1112 return setRef(tag_value, Strng_t(ref_name).ptr());
1113 }
1114
1115
1116 const XmlChar* Element::getRef(const XmlChar* tag_value) const {
1117 return child(tag_value).attr < cpXmlChar > (Unicode_ref);
1118 }
1119
1120
1121 Handle_t Element::addChild(const XmlChar* tag_value) const {
1122 Handle_t e = document().createElt(tag_value);
1123 m_element.append(e);
1124 return e;
1125 }
1126
1127
1128 Handle_t Element::setChild(const XmlChar* t) const {
1129 Elt_t e = m_element.child(t, false);
1130 return e ? Handle_t(e) : addChild(t);
1131 }
1132
1133 #ifndef DD4HEP_USE_TINYXML
1134
1135 void Element::addComment(const XmlChar* text_value) const {
1136 _N(m_element)->appendChild(_D(document().m_doc)->createComment(text_value));
1137 }
1138 #endif
1139
1140
1141 void Element::addComment(const char* text_value) const {
1142 #ifdef DD4HEP_USE_TINYXML
1143 _N(m_element)->appendChild(new TiXmlComment(text_value));
1144 #else
1145 _N(m_element)->appendChild(_D(document().m_doc)->createComment(Strng_t(text_value)));
1146 #endif
1147 }
1148
1149
1150 void Element::addComment(const std::string& text_value) const {
1151 addComment(text_value.c_str());
1152 }
1153
1154
1155 RefElement::RefElement(const Document& doc, const XmlChar* typ, const XmlChar* nam)
1156 : Element(doc, typ) {
1157 m_name = nam ? setAttr(_U(name), nam) : 0;
1158 }
1159
1160
1161 RefElement::RefElement(const Handle_t& e)
1162 : Element(e) {
1163 m_name = m_element ? getAttr(_U(name)) : 0;
1164 }
1165
1166
1167 RefElement::RefElement(const RefElement& e)
1168 : Element(e), m_name(e.m_name) {
1169 }
1170
1171
1172 RefElement& RefElement::operator=(const RefElement& e) {
1173 m_element = e.m_element;
1174 return *this;
1175 }
1176
1177 const XmlChar* RefElement::name() const {
1178 if (0 == m_name)
1179 std::cout << "Error:tag=" << m_element.tag() << std::endl;
1180 return attribute_value(m_name);
1181 }
1182
1183 const XmlChar* RefElement::refName() const {
1184 if (0 == m_name)
1185 std::cout << "Error:tag=" << m_element.tag() << std::endl;
1186 return attribute_value(m_name);
1187 }
1188
1189 void RefElement::setName(const XmlChar* new_name) {
1190 setAttr(_U(name), new_name);
1191 }
1192
1193 #ifndef DD4HEP_USE_TINYXML
1194 Collection_t::Collection_t(Handle_t element, const XmlChar* tag_value)
1195 : m_children(element, tag_value) {
1196 m_node = m_children.reset();
1197 }
1198 #endif
1199
1200 Collection_t::Collection_t(Handle_t element, const char* tag_value)
1201 : m_children(element, Strng_t(tag_value)) {
1202 m_node = m_children.reset();
1203 }
1204
1205
1206 Collection_t::Collection_t(NodeList node_list)
1207 : m_children(node_list) {
1208 m_node = m_children.reset();
1209 }
1210
1211
1212 Collection_t& Collection_t::reset() {
1213 m_node = m_children.reset();
1214 return *this;
1215 }
1216
1217
1218 size_t Collection_t::size() const {
1219 return Handle_t(m_children.m_node).numChildren(m_children.m_tag, false);
1220 }
1221
1222
1223 void Collection_t::throw_loop_exception(const std::exception& e) const {
1224 if (m_node) {
1225 throw std::runtime_error(std::string(e.what()) + "\n" + "dd4hep: Error interpreting XML nodes of type <" + tag() + "/>");
1226 }
1227 throw std::runtime_error(std::string(e.what()) + "\n" + "dd4hep: Error interpreting collections XML nodes.");
1228 }
1229
1230 void Collection_t::operator++() const {
1231 Elt_t e = this->parent();
1232 while (m_node) {
1233 m_node = m_children.next();
1234 if (m_node && _N(m_node)->getNodeType() == ELEMENT_NODE_TYPE) {
1235 if (this->parent() == e)
1236 return;
1237 }
1238 }
1239 }
1240
1241 void Collection_t::operator--() const {
1242 Elt_t e = this->parent();
1243 while (m_node) {
1244 m_node = m_children.previous();
1245 if (m_node && _N(m_node)->getNodeType() == ELEMENT_NODE_TYPE) {
1246 if (this->parent() == e)
1247 return;
1248 }
1249 }
1250 }
1251
1252 void Collection_t::operator++(int) const {
1253 ++(*this);
1254 }
1255
1256 void Collection_t::operator--(int) const {
1257 --(*this);
1258 }
1259
1260 Handle_t Document::clone(Handle_t source) const {
1261 #ifdef DD4HEP_USE_TINYXML
1262 return _XE(source.clone(0));
1263 #else
1264 return _XE(_D(m_doc)->importNode(_E(source.ptr()),true));
1265 #endif
1266 }
1267
1268 #ifdef DD4HEP_USE_TINYXML
1269
1270 #include "tinyxml_inl.h"
1271 #include "tinyxmlerror_inl.h"
1272 #include "tinyxmlparser_inl.h"
1273 #endif