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