Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 14:22:49

0001 #include <iostream>
0002 //#include <algorithm>
0003 //#include <utility>
0004 using namespace std;
0005 
0006 #include "L1Trigger/L1TCommon/interface/XmlConfigParser.h"
0007 #include "L1Trigger/L1TCommon/interface/TriggerSystem.h"
0008 
0009 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0010 #include "Utilities/Xerces/interface/XercesStrUtils.h"
0011 
0012 #include "xercesc/util/PlatformUtils.hpp"
0013 
0014 XERCES_CPP_NAMESPACE_USE
0015 
0016 using namespace l1t;
0017 
0018 //inline std::string _toString(XMLCh const* toTranscode) {
0019 //    char *c = xercesc::XMLString::transcode(toTranscode);
0020 //    std::string retval = c;
0021 //    xercesc::XMLString::release(&c);
0022 //    return retval;
0023 //}
0024 //
0025 //inline XMLCh* _toDOMS(std::string temp) {
0026 //  XMLCh* buff = XMLString::transcode(temp.c_str());
0027 //  return  buff;
0028 //}
0029 
0030 XmlConfigParser::XmlConfigParser()
0031     : kTagHw(nullptr),
0032       kTagAlgo(nullptr),
0033       kTagRunSettings(nullptr),
0034       kTagDb(nullptr),
0035       kTagKey(nullptr),
0036       kTagLoad(nullptr),
0037       kTagContext(nullptr),
0038       kTagParam(nullptr),
0039       kTagMask(nullptr),
0040       kTagDisable(nullptr),
0041       kTagExclBoards(nullptr),
0042       kTagExclude(nullptr),
0043       kTagColumns(nullptr),
0044       kTagTypes(nullptr),
0045       kTagRow(nullptr),
0046       kTagProcessor(nullptr),
0047       kTagRole(nullptr),
0048       kTagCrate(nullptr),
0049       kTagSlot(nullptr),
0050       kTagDaqTtc(nullptr),
0051       kAttrId(nullptr),
0052       kAttrType(nullptr),
0053       kAttrDelim(nullptr),
0054       kAttrModule(nullptr),
0055       kTypeTable("table") {
0056   XMLPlatformUtils::Initialize();
0057 
0058   kTagHw = XMLString::transcode("system");
0059   kTagAlgo = XMLString::transcode("algo");
0060   kTagRunSettings = XMLString::transcode("run-settings");
0061   kTagDb = XMLString::transcode("db");
0062   kTagKey = XMLString::transcode("key");
0063   kTagLoad = XMLString::transcode("load");
0064   kTagContext = XMLString::transcode("context");
0065   kTagParam = XMLString::transcode("param");
0066   kTagMask = XMLString::transcode("mask");
0067   kTagDisable = XMLString::transcode("disable");
0068   kTagExclBoards = XMLString::transcode("excluded-boards");
0069   kTagExclude = XMLString::transcode("exclude");
0070   kTagColumns = XMLString::transcode("columns");
0071   kTagTypes = XMLString::transcode("types");
0072   kTagRow = XMLString::transcode("row");
0073   kTagProcessor = XMLString::transcode("processor");
0074   kTagRole = XMLString::transcode("role");
0075   kTagCrate = XMLString::transcode("crate");
0076   kTagSlot = XMLString::transcode("slot");
0077   kTagDaqTtc = XMLString::transcode("daqttc-mgr");
0078   kAttrId = XMLString::transcode("id");
0079   kAttrType = XMLString::transcode("type");
0080   kAttrDelim = XMLString::transcode("delimiter");
0081   kAttrModule = XMLString::transcode("module");
0082 
0083   ///Initialise XML parser
0084   parser_ = new XercesDOMParser();
0085   parser_->setValidationScheme(XercesDOMParser::Val_Auto);
0086   parser_->setDoNamespaces(false);
0087 
0088   doc_ = nullptr;
0089 }
0090 
0091 XmlConfigParser::XmlConfigParser(DOMDocument* doc)
0092     : kTagHw(nullptr),
0093       kTagAlgo(nullptr),
0094       kTagRunSettings(nullptr),
0095       kTagDb(nullptr),
0096       kTagKey(nullptr),
0097       kTagLoad(nullptr),
0098       kTagContext(nullptr),
0099       kTagParam(nullptr),
0100       kTagMask(nullptr),
0101       kTagDisable(nullptr),
0102       kTagExclBoards(nullptr),
0103       kTagExclude(nullptr),
0104       kTagColumns(nullptr),
0105       kTagTypes(nullptr),
0106       kTagRow(nullptr),
0107       kTagProcessor(nullptr),
0108       kTagRole(nullptr),
0109       kTagCrate(nullptr),
0110       kTagSlot(nullptr),
0111       kTagDaqTtc(nullptr),
0112       kAttrId(nullptr),
0113       kAttrType(nullptr),
0114       kAttrDelim(nullptr),
0115       kAttrModule(nullptr),
0116       kTypeTable("table") {
0117   XMLPlatformUtils::Initialize();
0118 
0119   kTagHw = XMLString::transcode("system");
0120   kTagAlgo = XMLString::transcode("algo");
0121   kTagRunSettings = XMLString::transcode("run-settings");
0122   kTagDb = XMLString::transcode("db");
0123   kTagKey = XMLString::transcode("key");
0124   kTagLoad = XMLString::transcode("load");
0125   kTagContext = XMLString::transcode("context");
0126   kTagParam = XMLString::transcode("param");
0127   kTagMask = XMLString::transcode("mask");
0128   kTagDisable = XMLString::transcode("disable");
0129   kTagExclBoards = XMLString::transcode("excluded-boards");
0130   kTagExclude = XMLString::transcode("exclude");
0131   kTagColumns = XMLString::transcode("columns");
0132   kTagTypes = XMLString::transcode("types");
0133   kTagRow = XMLString::transcode("row");
0134   kTagProcessor = XMLString::transcode("processor");
0135   kTagRole = XMLString::transcode("role");
0136   kTagCrate = XMLString::transcode("crate");
0137   kTagSlot = XMLString::transcode("slot");
0138   kTagDaqTtc = XMLString::transcode("daqttc-mgr");
0139   kAttrId = XMLString::transcode("id");
0140   kAttrType = XMLString::transcode("type");
0141   kAttrDelim = XMLString::transcode("delimiter");
0142   kAttrModule = XMLString::transcode("module");
0143 
0144   parser_ = nullptr;
0145   doc_ = doc;
0146 }
0147 
0148 XmlConfigParser::~XmlConfigParser() {
0149   delete parser_;
0150   XMLPlatformUtils::Terminate();
0151 }
0152 
0153 void XmlConfigParser::readDOMFromString(const std::string& str, DOMDocument*& doc) {
0154   MemBufInputSource xmlstr_buf((const XMLByte*)(str.c_str()), str.size(), "xmlstrbuf");
0155   parser_->parse(xmlstr_buf);
0156   doc = parser_->getDocument();
0157   assert(doc);
0158 }
0159 
0160 void XmlConfigParser::readDOMFromString(const std::string& str) {
0161   MemBufInputSource xmlstr_buf((const XMLByte*)(str.c_str()), str.size(), "xmlstrbuf");
0162   parser_->parse(xmlstr_buf);
0163   doc_ = parser_->getDocument();
0164   assert(doc_);
0165 }
0166 
0167 void XmlConfigParser::readDOMFromFile(const std::string& fName, DOMDocument*& doc) {
0168   parser_->parse(fName.c_str());
0169   doc = parser_->getDocument();
0170 
0171   if (!doc) {
0172     edm::LogError("XmlConfigParser") << "Could not parse file " << fName << "\n";
0173   }
0174 
0175   assert(doc);
0176 }
0177 
0178 void XmlConfigParser::readDOMFromFile(const std::string& fName) {
0179   parser_->parse(fName.c_str());
0180   doc_ = parser_->getDocument();
0181 
0182   if (!doc_) {
0183     edm::LogError("XmlConfigParser") << "Could not parse file " << fName << "\n";
0184   }
0185 
0186   assert(doc_);
0187 }
0188 
0189 void XmlConfigParser::readRootElement(TriggerSystem& aTriggerSystem, const std::string& sysId) {
0190   DOMElement* rootElement = doc_->getDocumentElement();
0191   if (rootElement) {
0192     if (rootElement->getNodeType() == DOMNode::ELEMENT_NODE) {
0193       readElement(rootElement, aTriggerSystem, sysId);
0194     }
0195   } else {
0196     throw std::runtime_error("No xml root element found");
0197   }
0198 }
0199 
0200 void XmlConfigParser::readElement(const DOMElement* element, TriggerSystem& aTriggerSystem, const std::string& sysId) {
0201   if (XMLString::equals(element->getTagName(), kTagHw)) {
0202     // in case this is a HW description
0203     readHwDescription(element, aTriggerSystem, sysId);
0204   } else if (XMLString::equals(element->getTagName(), kTagAlgo) ||
0205              XMLString::equals(element->getTagName(), kTagRunSettings)) {
0206     // in case this is a configuration snippet
0207     readContext(element, sysId, aTriggerSystem);
0208   }
0209 }
0210 
0211 void XmlConfigParser::readHwDescription(const DOMElement* element,
0212                                         TriggerSystem& aTriggerSystem,
0213                                         const std::string& sysId) {
0214   // if sysId == "" set the systemId of the trigsystem from the xml sytem id
0215   if (!sysId.empty()) {
0216     std::string sId = cms::xerces::toString(element->getAttribute(kAttrId));
0217     pruneString(sId);
0218     if (sId != sysId)
0219       return;
0220   }
0221 
0222   char* sysId_ = xercesc::XMLString::transcode(element->getAttribute(kAttrId));
0223   aTriggerSystem.setSystemId(pruneString(sysId_));
0224   xercesc::XMLString::release(&sysId_);
0225 
0226   // handle processors
0227   DOMNodeList* processors = element->getElementsByTagName(kTagProcessor);
0228   XMLSize_t nodeCount = processors->getLength();
0229   for (XMLSize_t xx = 0; xx < nodeCount; ++xx) {
0230     DOMNode* currentNode = processors->item(xx);
0231     if (currentNode->getNodeType() && currentNode->getNodeType() == DOMNode::ELEMENT_NODE) {  //no null and is element
0232       DOMElement* currentElement = static_cast<DOMElement*>(currentNode);
0233 
0234       string proc = cms::xerces::toString(currentElement->getAttribute(kAttrId));
0235       pruneString(proc);
0236       string role, crate, slot;
0237 
0238       DOMNodeList* roles = currentElement->getElementsByTagName(kTagRole);
0239       // roles of this processor (should be only one)
0240       if (roles->getLength() != 1)
0241         throw std::runtime_error(string("Configutration specify not exactly one role"));
0242       //      for (XMLSize_t i = 0; i < roles->getLength(); ++i) {
0243       {
0244         XMLSize_t i = 0;
0245         DOMNodeList* roleChilds = roles->item(i)->getChildNodes();
0246         if (roleChilds->getLength() != 1)
0247           throw std::runtime_error(string("Configutration specify not exactly one role"));
0248         {
0249           //        for (XMLSize_t j = 0; j < roleChilds->getLength(); ++j) {
0250           XMLSize_t j = 0;
0251           if (roleChilds->item(j)->getNodeType() == DOMNode::TEXT_NODE) {
0252             role = cms::xerces::toString(roleChilds->item(j)->getNodeValue());
0253             pruneString(role);
0254           }
0255         }
0256       }
0257 
0258       DOMNodeList* crates = currentElement->getElementsByTagName(kTagCrate);
0259       // crates of this processor (should be only one)
0260       if (crates->getLength() != 1)
0261         throw std::runtime_error(string("Configutration specify not exactly one crate"));
0262       //      for (XMLSize_t i = 0; i < crates->getLength(); ++i) {
0263       {
0264         XMLSize_t i = 0;
0265         DOMNodeList* crateChilds = crates->item(i)->getChildNodes();
0266         if (crateChilds->getLength() != 1)
0267           throw std::runtime_error(string("Configutration specify not exactly one crate"));
0268         {
0269           XMLSize_t j = 0;
0270           //        for (XMLSize_t j = 0; j < crateChilds->getLength(); ++j) {
0271           if (crateChilds->item(j)->getNodeType() == DOMNode::TEXT_NODE) {
0272             crate = cms::xerces::toString(crateChilds->item(j)->getNodeValue());
0273             pruneString(crate);
0274           }
0275         }
0276       }
0277 
0278       DOMNodeList* slots = currentElement->getElementsByTagName(kTagSlot);
0279       // slots of this processor (should be only one)
0280       if (slots->getLength() != 1)
0281         throw std::runtime_error(string("Configutration specify not exactly one slot"));
0282       //      for (XMLSize_t i = 0; i < slots->getLength(); ++i) {
0283       {
0284         XMLSize_t i = 0;
0285         DOMNodeList* slotChilds = slots->item(i)->getChildNodes();
0286         if (slotChilds->getLength() != 1)
0287           throw std::runtime_error(string("Configutration specify not exactly one slot"));
0288         //        for (XMLSize_t j = 0; j < slotChilds->getLength(); ++j) {
0289         {
0290           XMLSize_t j = 0;
0291           if (slotChilds->item(j)->getNodeType() == DOMNode::TEXT_NODE) {
0292             slot = cms::xerces::toString(slotChilds->item(j)->getNodeValue());
0293             pruneString(slot);
0294           }
0295         }
0296       }
0297 
0298       aTriggerSystem.addProcessor(proc.c_str(), role.c_str(), crate.c_str(), slot.c_str());
0299     }
0300   }
0301 
0302   // handle DAQ TTC managers
0303   DOMNodeList* daqttcs = element->getElementsByTagName(kTagDaqTtc);
0304   nodeCount = daqttcs->getLength();
0305   for (XMLSize_t xx = 0; xx < nodeCount; ++xx) {
0306     DOMNode* currentNode = daqttcs->item(xx);
0307     if (currentNode->getNodeType() && currentNode->getNodeType() == DOMNode::ELEMENT_NODE) {  //no null and is element
0308       DOMElement* currentElement = static_cast<DOMElement*>(currentNode);
0309       string daqttc = cms::xerces::toString(currentElement->getAttribute(kAttrId));
0310       string role, crate;
0311 
0312       DOMNodeList* roles = currentElement->getElementsByTagName(kTagRole);
0313       // roles of this DAQ TTC manager (should be only one)
0314       if (roles->getLength() != 1)
0315         throw std::runtime_error(string("Configutration specify not exactly one role"));
0316       //      for (XMLSize_t i = 0; i < roles->getLength(); ++i) {
0317       {
0318         XMLSize_t i = 0;
0319         DOMNodeList* roleChilds = roles->item(i)->getChildNodes();
0320         if (roleChilds->getLength() != 1)
0321           throw std::runtime_error(string("Configutration specify not exactly one role"));
0322         //        for (XMLSize_t j = 0; j < roleChilds->getLength(); ++j) {
0323         {
0324           XMLSize_t j = 0;
0325           if (roleChilds->item(j)->getNodeType() == DOMNode::TEXT_NODE) {
0326             role = cms::xerces::toString(roleChilds->item(j)->getNodeValue());
0327             pruneString(role);
0328           }
0329         }
0330       }
0331 
0332       DOMNodeList* crates = currentElement->getElementsByTagName(kTagCrate);
0333       // crates of this DAQ TTC manager (should be only one)
0334       if (crates->getLength() != 1)
0335         throw std::runtime_error(string("Configutration specify not exactly one crate"));
0336       //      for (XMLSize_t i = 0; i < crates->getLength(); ++i) {
0337       {
0338         XMLSize_t i = 0;
0339         DOMNodeList* crateChilds = crates->item(i)->getChildNodes();
0340         if (crateChilds->getLength() != 1)
0341           throw std::runtime_error(string("Configutration specify not exactly one crate"));
0342         //        for (XMLSize_t j = 0; j < crateChilds->getLength(); ++j) {
0343         {
0344           XMLSize_t j = 0;
0345           if (crateChilds->item(j)->getNodeType() == DOMNode::TEXT_NODE) {
0346             crate = cms::xerces::toString(crateChilds->item(j)->getNodeValue());
0347             pruneString(crate);
0348           }
0349         }
0350       }
0351 
0352       aTriggerSystem.addDaq(daqttc.c_str(), role.c_str(), crate.c_str());
0353     }
0354   }
0355 
0356   // handle excluded boards
0357   DOMNodeList* exclBoards = element->getElementsByTagName(kTagExclBoards);
0358   for (XMLSize_t xx = 0; xx < exclBoards->getLength(); ++xx) {
0359     DOMElement* exclBoardElem = static_cast<DOMElement*>(exclBoards->item(xx));
0360 
0361     for (DOMElement* elem = static_cast<DOMElement*>(exclBoardElem->getFirstChild()); elem;
0362          elem = static_cast<DOMElement*>(elem->getNextSibling())) {
0363       if (elem->getNodeType() == DOMNode::ELEMENT_NODE) {
0364         if (XMLString::equals(elem->getTagName(), kTagExclude)) {
0365           // found an excluded board
0366           std::string id = cms::xerces::toString(elem->getAttribute(kAttrId));
0367           pruneString(id);
0368           aTriggerSystem.disableProcOrRoleOrDaq(
0369               id.c_str());  // handle in the same way as disabled ids in the run-settings
0370         }
0371       }
0372     }
0373   }
0374 }
0375 
0376 void XmlConfigParser::readContext(const DOMElement* element, const std::string& sysId, TriggerSystem& aTriggerSystem) {
0377   std::string systemId = sysId;
0378   if (systemId.empty()) {
0379     systemId = aTriggerSystem.systemId();
0380   }
0381   if (cms::xerces::toString(element->getAttribute(kAttrId)) == systemId) {
0382     DOMNodeList* contextElements = element->getElementsByTagName(kTagContext);
0383 
0384     for (XMLSize_t i = 0; i < contextElements->getLength(); ++i) {
0385       DOMElement* contextElement = static_cast<DOMElement*>(contextElements->item(i));
0386       std::string contextId = cms::xerces::toString(contextElement->getAttribute(kAttrId));
0387       pruneString(contextId);
0388 
0389       for (DOMElement* elem = static_cast<DOMElement*>(contextElement->getFirstChild()); elem;
0390            elem = static_cast<DOMElement*>(elem->getNextSibling())) {
0391         if (elem->getNodeType() == DOMNode::ELEMENT_NODE) {
0392           if (XMLString::equals(elem->getTagName(), kTagParam)) {
0393             // found a parameter
0394             string id = cms::xerces::toString(elem->getAttribute(kAttrId));
0395             string type = cms::xerces::toString(elem->getAttribute(kAttrType));
0396             string delim = cms::xerces::toString(elem->getAttribute(kAttrDelim));
0397             pruneString(id);
0398             pruneString(type);
0399             pruneString(delim);
0400 
0401             // the type table needs special treatment since it consists of child nodes
0402             if (type == kTypeTable) {
0403               // get the columns string
0404               std::string columnsStr = "";
0405               DOMNodeList* colElements = elem->getElementsByTagName(kTagColumns);
0406               for (XMLSize_t j = 0; j < colElements->getLength(); ++j) {
0407                 DOMNodeList* colChilds = colElements->item(j)->getChildNodes();
0408                 for (XMLSize_t k = 0; k < colChilds->getLength(); ++k) {
0409                   if (colChilds->item(k)->getNodeType() == DOMNode::TEXT_NODE) {
0410                     ///                    columnsStr = cms::xerces::toString(colChilds->item(k)->getNodeValue());
0411                     ///                    pruneString(columnsStr);
0412                     char* cStr = xercesc::XMLString::transcode(colChilds->item(k)->getNodeValue());
0413                     char *saveptr, first = 1;
0414                     for (char* item = strtok_r(cStr, delim.c_str(), &saveptr); item != nullptr;
0415                          item = strtok_r(nullptr, delim.c_str(), &saveptr), first = 0)
0416                       columnsStr += (first ? std::string("") : delim) + pruneString(item);
0417                     xercesc::XMLString::release(&cStr);
0418                   }
0419                 }
0420               }
0421 
0422               // get the column type string
0423               std::string typesStr = "";
0424               DOMNodeList* colTypesElements = elem->getElementsByTagName(kTagTypes);
0425               for (XMLSize_t j = 0; j < colTypesElements->getLength(); ++j) {
0426                 DOMNodeList* colTypesChilds = colTypesElements->item(j)->getChildNodes();
0427                 for (XMLSize_t k = 0; k < colTypesChilds->getLength(); ++k) {
0428                   if (colTypesChilds->item(k)->getNodeType() == DOMNode::TEXT_NODE) {
0429                     ///                    typesStr = cms::xerces::toString(colTypesChilds->item(k)->getNodeValue());
0430                     ///                    pruneString(typesStr);
0431                     char* tStr = xercesc::XMLString::transcode(colTypesChilds->item(k)->getNodeValue());
0432                     char *saveptr, first = 1;
0433                     for (char* item = strtok_r(tStr, delim.c_str(), &saveptr); item != nullptr;
0434                          item = strtok_r(nullptr, delim.c_str(), &saveptr), first = 0)
0435                       typesStr += (first ? std::string("") : delim) + pruneString(item);
0436                     xercesc::XMLString::release(&tStr);
0437                   }
0438                 }
0439               }
0440 
0441               // get the rows
0442               std::vector<std::string> rowStrs;
0443               DOMNodeList* rowElements = elem->getElementsByTagName(kTagRow);
0444               for (XMLSize_t j = 0; j < rowElements->getLength(); ++j) {
0445                 DOMNodeList* rowChilds = rowElements->item(j)->getChildNodes();
0446                 for (XMLSize_t k = 0; k < rowChilds->getLength(); ++k) {
0447                   if (rowChilds->item(k)->getNodeType() == DOMNode::TEXT_NODE) {
0448                     ///                    std::string rowStr = cms::xerces::toString(rowChilds->item(k)->getNodeValue());
0449                     ///                    pruneString(rowStr);
0450                     ///                    rowStrs.push_back(rowStr);
0451                     char* rStr = xercesc::XMLString::transcode(rowChilds->item(k)->getNodeValue());
0452                     char *saveptr, first = 1;
0453                     std::string row;
0454                     for (char* item = strtok_r(rStr, delim.c_str(), &saveptr); item != nullptr;
0455                          item = strtok_r(nullptr, delim.c_str(), &saveptr), first = 0)
0456                       row += (first ? std::string("") : delim) + pruneString(item);
0457 
0458                     rowStrs.push_back(row);
0459                     xercesc::XMLString::release(&rStr);
0460                   }
0461                 }
0462               }
0463               //         std::cout << "param element node with id attribute " << id << " and type attribute " << typesStr << std::endl;
0464               aTriggerSystem.addTable(
0465                   id.c_str(), contextId.c_str(), columnsStr.c_str(), typesStr.c_str(), rowStrs, delim.c_str());
0466 
0467             } else {  // all types other than table
0468               std::string value = "";
0469               DOMNodeList* valNodes = elem->getChildNodes();
0470               for (XMLSize_t j = 0; j < valNodes->getLength(); ++j) {
0471                 if (valNodes->item(j)->getNodeType() == DOMNode::TEXT_NODE) {
0472                   value += cms::xerces::toString(valNodes->item(j)->getNodeValue());  // should we prune?
0473                 }
0474               }
0475 
0476               // strip leading and trailing line breaks and spaces
0477               pruneString(value);
0478 
0479               //              std::cout << "param element node with id attribute " << id << " and type attribute " << type << " with value: [" << value << "]" << std::endl;
0480               aTriggerSystem.addParameter(id.c_str(), contextId.c_str(), type.c_str(), value.c_str(), delim.c_str());
0481             }
0482 
0483           } else if (XMLString::equals(elem->getTagName(), kTagMask)) {
0484             // found a Mask
0485             std::string id = cms::xerces::toString(elem->getAttribute(kAttrId));
0486             //std::cout << "Mask element node with id attribute " << id << std::endl;
0487             pruneString(id);
0488             aTriggerSystem.addMask(id.c_str(), contextId.c_str());
0489 
0490           } else if (XMLString::equals(elem->getTagName(), kTagDisable)) {
0491             // found a disable
0492             std::string id = cms::xerces::toString(elem->getAttribute(kAttrId));
0493             pruneString(id);
0494             aTriggerSystem.disableProcOrRoleOrDaq(id.c_str());
0495           }
0496         }
0497       }
0498     }
0499   }
0500 }
0501 
0502 void XmlConfigParser::readContexts(const std::string& key, const std::string& sysId, TriggerSystem& aTriggerSystem) {
0503   DOMElement* keyElement = getKeyElement(key);
0504   if (keyElement) {
0505     for (DOMElement* elem = static_cast<DOMElement*>(keyElement->getFirstChild()); elem;
0506          elem = static_cast<DOMElement*>(elem->getNextSibling())) {
0507       if (elem->getNodeType() == DOMNode::ELEMENT_NODE) {
0508         if (XMLString::equals(elem->getTagName(), kTagAlgo) || XMLString::equals(elem->getTagName(), kTagRunSettings)) {
0509           readContext(elem, sysId, aTriggerSystem);
0510         }
0511       }
0512     }
0513   } else {
0514     throw std::runtime_error("Key not found: " + key);
0515   }
0516 }
0517 
0518 DOMElement* XmlConfigParser::getKeyElement(const std::string& key) {
0519   DOMElement* rootElement = doc_->getDocumentElement();
0520   if (XMLString::equals(rootElement->getTagName(), kTagDb)) {
0521     DOMNodeList* keyElements = rootElement->getElementsByTagName(kTagKey);
0522 
0523     for (XMLSize_t i = 0; i < keyElements->getLength(); ++i) {
0524       DOMElement* keyElement = static_cast<DOMElement*>(keyElements->item(i));
0525       if (cms::xerces::toString(keyElement->getAttribute(kAttrId)) == key) {  // we found the key we were looking for
0526         return keyElement;
0527       }
0528     }
0529   }
0530   return nullptr;
0531 }
0532 
0533 void XmlConfigParser::buildGlobalDoc(const std::string& key, const std::string& topPath) {
0534   DOMElement* keyElement = getKeyElement(key);
0535   if (keyElement) {
0536     DOMNodeList* loadElements = keyElement->getElementsByTagName(kTagLoad);
0537     for (XMLSize_t i = 0; i < loadElements->getLength(); ++i) {
0538       DOMElement* loadElement = static_cast<DOMElement*>(loadElements->item(i));
0539       std::string fileName = cms::xerces::toString(loadElement->getAttribute(kAttrModule));
0540       if (fileName.find('/') != 0) {  // load element has a relative path
0541         // build an absolute path with directory of top xml file
0542         size_t pos;
0543         std::string topDir = "";
0544         pos = topPath.find_last_of('/');
0545         if (pos != std::string::npos) {
0546           topDir = topPath.substr(0, pos + 1);
0547         }
0548         fileName = topDir + fileName;
0549       }
0550       //std::cout << "loading file " << fileName << std::endl;
0551       DOMDocument* subDoc = nullptr;
0552       readDOMFromFile(fileName, subDoc);
0553       if (subDoc) {
0554         appendNodesFromSubDoc(keyElement, subDoc);
0555       }
0556     }
0557   }
0558 }
0559 
0560 void XmlConfigParser::appendNodesFromSubDoc(DOMNode* parentNode, DOMDocument* subDoc) {
0561   DOMElement* subDocRootElement = subDoc->getDocumentElement();
0562   //std::cout << "root element tag: " << cms::xerces::toString(subDocRootElement->getTagName()) << std::endl;
0563   if (XMLString::equals(subDocRootElement->getTagName(), kTagAlgo) ||
0564       XMLString::equals(subDocRootElement->getTagName(), kTagRunSettings)) {
0565     DOMNode* importedNode = doc_->importNode(subDocRootElement, true);
0566     parentNode->appendChild(importedNode);
0567   }
0568 }
0569 
0570 // the small static look up table below indicates in O(1) time if the symbol is '\n', (ascii code 10) '\t' (code 9), or ' ' (code 32)
0571 const char XmlConfigParser_reject_symbols[256] = {
0572     0, 0, 0, 0, 0, 0, 0, 0, 0, 1,                                // '\n'
0573     1, 0, 0, 0, 0, 0, 0, 0, 0, 0,                                // '\t'
0574     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,  // ' '
0575     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0576     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0577     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0578     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0579     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0580     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
0581 
0582 char* XmlConfigParser::pruneString(char*& str) {
0583   size_t alphanumBegin = 0, alphanumEnd = strlen(str) - 1;
0584 
0585   while (str[alphanumBegin] && XmlConfigParser_reject_symbols[unsigned(str[alphanumBegin])])
0586     alphanumBegin++;
0587   while (alphanumEnd >= alphanumBegin && XmlConfigParser_reject_symbols[unsigned(str[alphanumEnd])])
0588     alphanumEnd--;
0589 
0590   str[alphanumEnd + 1] = '\0';
0591   return str + alphanumBegin;
0592 }
0593 
0594 void XmlConfigParser::pruneString(std::string& str) {
0595   std::size_t alphanumBegin = str.find_first_not_of("\n\t ");
0596   std::size_t alphanumEnd = str.find_last_not_of("\n\t ");
0597   if (alphanumBegin != std::string::npos) {
0598     if (alphanumEnd != std::string::npos) {
0599       str = str.substr(alphanumBegin, alphanumEnd - alphanumBegin + 1);
0600     } else {
0601       str = str.substr(alphanumBegin);
0602     }
0603   }
0604 }