diff --git a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsPLC.cpp b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsPLC.cpp index 48e00f9ed01e91c7d29c20dfff4a91c95ccf6f6c..6b08a4956922a5550d1448a0340324a5cc3dfa1f 100644 --- a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsPLC.cpp +++ b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsPLC.cpp @@ -337,20 +337,19 @@ namespace Silecs XMLParser xmlParser(parameterFile_,true); // Extract general information =========================================== - ElementXML rootNode = xmlParser.getFirstElementFromXPath("/SILECS-Param"); + ElementXML rootNode = xmlParser.getSingleElementFromXPath("/SILECS-Param"); localRelease_ = rootNode.getAttribute("silecs-version"); - - ElementXML ownerNode = xmlParser.getFirstElementFromXPath("/SILECS-Param/Mapping-Info/Owner"); + ElementXML ownerNode = xmlParser.getSingleElementFromXPath("/SILECS-Param/Mapping-Info/Owner"); localOwner_ = ownerNode.getAttribute("user-login"); - ElementXML generationNode = xmlParser.getFirstElementFromXPath("/SILECS-Param/Mapping-Info/Generation"); + ElementXML generationNode = xmlParser.getSingleElementFromXPath("/SILECS-Param/Mapping-Info/Generation"); localDate_ = generationNode.getAttribute("date"); - ElementXML deploymentNode = xmlParser.getFirstElementFromXPath("/SILECS-Param/Mapping-Info/Deployment"); + ElementXML deploymentNode = xmlParser.getSingleElementFromXPath("/SILECS-Param/Mapping-Info/Deployment"); StringUtilities::fromString(localChecksum_,deploymentNode.getAttribute("checksum") ); // Extract PLC general configuration ====================================== - ElementXML mappingNode = xmlParser.getFirstElementFromXPath("/SILECS-Param/SILECS-Mapping"); + ElementXML mappingNode = xmlParser.getSingleElementFromXPath("/SILECS-Param/SILECS-Mapping"); //name_ = pEl->getStringAttribute("name"); already done before domain_ = mappingNode.getAttribute("domain"); brand_ = mappingNode.getAttribute("plc-brand"); diff --git a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsRegister.cpp b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsRegister.cpp index 901fb367450958b58b6e146ca5b3fd2771f6ff93..c38f7e631b4db5bd4759700121e7d9403eb6bf42 100644 --- a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsRegister.cpp +++ b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsRegister.cpp @@ -29,30 +29,42 @@ namespace Silecs { - Register::Register(Device* theDevice,const boost::shared_ptr<ElementXML>& registerNode) : theDevice_ (theDevice) - { + Register::Register(Device* theDevice,const boost::shared_ptr<ElementXML>& registerNode) : theDevice_ (theDevice) + { name_ = registerNode->getAttribute("name"); - format_ = whichFormatType(registerNode->getAttribute("format")); - StringUtilities::fromString(dimension1_,registerNode->getAttribute("array-dim1") ); - StringUtilities::fromString(dimension2_,registerNode->getAttribute("array-dim2") ); - StringUtilities::fromString(size_,registerNode->getAttribute("size") ); - StringUtilities::fromString(memSize_,registerNode->getAttribute("mem-size") ); - StringUtilities::fromString(address_,registerNode->getAttribute("address") ); - synchro_ = Service::whichSynchroType(registerNode->getAttribute("synchro")); - isInitialized_ = false; //register not initialized yet (used for output registers) - - // if format is string, retrieve also string-len attribute - if (format_ == String) - { - StringUtilities::fromString(length_,registerNode->getAttribute("string-len") ); - if (DEBUG & Log::topics_) LOG(ALLOC) << "Register (create): " << name_ << ", format: " << getFormatAsString() << ", string-len: " << length_ << ", dim: " << dimension1_ << ", dim2: " << dimension2_ << ", synchro: " << getSynchroTypeAsString() << ", offset: " << address_; - } - else - { - length_ = 1; - if (DEBUG & Log::topics_) LOG(ALLOC) << "Register (create): " << name_ << ", format: " << getFormatAsString() << ", dim: " << dimension1_ << ", dim2: " << dimension2_ << ", synchro: " << getSynchroTypeAsString() << ", offset: " << address_; - } - } + length_ = 1; + dimension1_ = 1; + dimension2_ = 1; + std::vector< boost::shared_ptr<ElementXML> > childNodes = registerNode->childList_; + std::vector< boost::shared_ptr<ElementXML> >::const_iterator childIter; + for(childIter = childNodes.begin(); childIter != childNodes.end(); childIter++) + { + // We have to loop, since there is as well the description-element + format_ = whichFormatType((*childIter)->getAttribute("format")); + if( (*childIter)->hasAttribute("dim") ) + StringUtilities::fromString(dimension1_,(*childIter)->getAttribute("dim") );// dim is used for 1d-arrays + if( (*childIter)->hasAttribute("dim1") ) + StringUtilities::fromString(dimension1_,(*childIter)->getAttribute("dim1") ); + if( (*childIter)->hasAttribute("dim2") ) + StringUtilities::fromString(dimension2_,(*childIter)->getAttribute("dim2") ); + if( (*childIter)->hasAttribute("string-length") ) + StringUtilities::fromString(length_,(*childIter)->getAttribute("string-length") ); + } + StringUtilities::fromString(size_,registerNode->getAttribute("size") ); + StringUtilities::fromString(memSize_,registerNode->getAttribute("mem-size") ); + StringUtilities::fromString(address_,registerNode->getAttribute("address") ); + synchro_ = Service::whichSynchroType(registerNode->getAttribute("synchro")); + isInitialized_ = false; //register not initialized yet (used for output registers) + + if (length_ > 1) + { + LOG(DEBUG) << "Register (create): " << name_ << ", format: " << getFormatAsString() << ", string-length: " << length_ << ", dim: " << dimension1_ << ", dim2: " << dimension2_ << ", synchro: " << getSynchroTypeAsString() << ", offset: " << address_; + } + else + { + LOG(DEBUG) << "Register (create): " << name_ << ", format: " << getFormatAsString() << ", dim: " << dimension1_ << ", dim2: " << dimension2_ << ", synchro: " << getSynchroTypeAsString() << ", offset: " << address_; + } + } Register::~Register() { diff --git a/silecs-communication-cpp/src/silecs-communication/interface/utility/XMLParser.cpp b/silecs-communication-cpp/src/silecs-communication/interface/utility/XMLParser.cpp index 488c853229c3fa7dca24e3f971361a7865cb9bad..a3192240f1f3fdb57d29a6dbb5ffe51c391caead 100644 --- a/silecs-communication-cpp/src/silecs-communication/interface/utility/XMLParser.cpp +++ b/silecs-communication-cpp/src/silecs-communication/interface/utility/XMLParser.cpp @@ -187,6 +187,18 @@ ElementXML XMLParser::getFirstElementFromXPath(const std::string& xpathExpressio return result.get()[0]; } +ElementXML XMLParser::getSingleElementFromXPath(const std::string& xpathExpression) const +{ + boost::optional<boost::ptr_vector<ElementXML> > result = getElementsFromXPath_throwIfEmpty(xpathExpression); + if (result.get().size() > 1) + { + std::ostringstream message; + message << "The xpathExpression: '" << xpathExpression << "' returns more than one XML-Elements"; + throw SilecsException(__FILE__, __LINE__, message.str().c_str()); + } + return result.get()[0]; +} + xmlChar* XMLParser::ConvertInput(const char *in, const char *encoding) { xmlChar *out; diff --git a/silecs-communication-cpp/src/silecs-communication/interface/utility/XMLParser.h b/silecs-communication-cpp/src/silecs-communication/interface/utility/XMLParser.h index b403b40026601735079c3aab44dde5904b6c7100..36b7849b11db2de8be06e48491940529a5b38b77 100644 --- a/silecs-communication-cpp/src/silecs-communication/interface/utility/XMLParser.h +++ b/silecs-communication-cpp/src/silecs-communication/interface/utility/XMLParser.h @@ -109,7 +109,7 @@ class ElementXML } } std::ostringstream message; - message << "The XML Attribute " << (*attributeIter)->name_ << " was not found"; + message << "The XML Attribute '" << attributeName << "' was not found"; throw SilecsException(__FILE__, __LINE__, message.str().c_str()); } }; @@ -142,6 +142,8 @@ class XMLParser */ virtual boost::optional<boost::ptr_vector<ElementXML> > getElementsFromXPath(const std::string& xpathExpression) const; + virtual ElementXML getSingleElementFromXPath(const std::string& xpathExpression) const; + virtual ElementXML getFirstElementFromXPath(const std::string& xpathExpression) const; virtual boost::ptr_vector<ElementXML> getElementsFromXPath_throwIfEmpty(const std::string& xpathExpression) const;