/* Copyright (C) 2014 InfiniDB, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /******************************************************************************* * $Id$ * *******************************************************************************/ /* * we_xmlgetter.cpp * * Created on: Feb 7, 2012 * Author: bpaul */ #include <stdio.h> #include <string.h> #include <unistd.h> #include <stdexcept> #include <iostream> #include <string> #include <vector> using namespace std; #include "we_xmlgetter.h" using namespace std; namespace WriteEngine { //------------------------------------------------------------------------------ // WEXmlgetter constructor //------------------------------------------------------------------------------ WEXmlgetter::WEXmlgetter(std::string& ConfigName): fConfigName(ConfigName), fDoc( NULL ), fpRoot( NULL ) { // xmlNodePtr curPtr; fDoc = xmlParseFile( ConfigName.c_str() ); if (fDoc == NULL ) throw runtime_error("WEXmlgetter::getConfig(): no XML document!"); fpRoot = xmlDocGetRootElement( fDoc ); if ( fpRoot == NULL ) { xmlFreeDoc( fDoc ); fDoc = NULL; throw runtime_error("WEXmlgetter::getConfig(): no XML Root Tag!"); } } //------------------------------------------------------------------------------ // WEXmlgetter destructor //------------------------------------------------------------------------------ WEXmlgetter::~WEXmlgetter() { xmlFreeDoc( fDoc ); fDoc = NULL; } //------------------------------------------------------------------------------ // Get/return the property or attribute value (strVal) for the specified xml tag // (pNode) and property/attribute (pTag) //------------------------------------------------------------------------------ bool WEXmlgetter::getNodeAttribute(const xmlNode* pNode, const char* pTag, std::string& strVal) const { xmlChar* pTmp = NULL; bool bFound = false; pTmp = xmlGetProp( const_cast<xmlNode*>(pNode), (xmlChar*) pTag ); if ( pTmp ) { bFound = true; strVal = (char*)pTmp; xmlFree( pTmp ); } else { strVal.clear(); } // end if return bFound; } //------------------------------------------------------------------------------ // Get/return the node content (strVal) for the specified xml tag (pNode) //------------------------------------------------------------------------------ bool WEXmlgetter::getNodeContent( const xmlNode* pNode, std::string& strVal) const { xmlChar* pTmp = NULL; bool bFound = false; if ( pNode->children != NULL ) { pTmp = xmlNodeGetContent( pNode->children ); if ( pTmp ) { bFound = true; strVal = (char*)pTmp; xmlFree( pTmp ); } else { strVal.clear(); } } else { strVal.clear(); } return bFound; } //------------------------------------------------------------------------------ // Get/returns node content for the "first" child node under each section/name. // Example: // <section> // <name> // <subname1> // </subname1> // </name> // <name> // <subname1> // </subname1> // </name> // </section> // // Looks like xml2 is currently returning the text node as the first child // node under a node. So in the example above, this function is currently // always returning the text node content inside each <name> rather than // any <subname1> node that might be within each <name> tag. //------------------------------------------------------------------------------ void WEXmlgetter::getConfig(const string& section, const string& name, vector<string>& values) const { string res; if (section.length() == 0) throw invalid_argument("Config::getConfig: section must have a length"); xmlNode* pPtr = fpRoot->xmlChildrenNode; while (pPtr != NULL) { //cout << "pPtr->name: " << // (const xmlChar*)pPtr->name << std::endl; if ((!xmlStrcmp(pPtr->name, (const xmlChar*)section.c_str()))) { xmlNodePtr pPtr2 = pPtr->xmlChildrenNode; while (pPtr2 != NULL) { //cout << " pPtr2->name: " << // (const xmlChar*)pPtr2->name << std::endl; if ((!xmlStrcmp(pPtr2->name, (const xmlChar*)name.c_str()))) { xmlNodePtr pPtr3 = pPtr2->xmlChildrenNode; values.push_back((const char*)pPtr3->content); //cout << " pPtr3->name: " << // (const xmlChar*)pPtr3->name << // "; content: " << (const xmlChar*)pPtr3->content << // "; len: " << strlen((char*)pPtr3->content) << std::endl; } pPtr2 = pPtr2->next; } } pPtr = pPtr->next; } } //------------------------------------------------------------------------------ // Returns node content for the last node in the node tree defined by // "sections". So if sections[] were: // sections[0] = "house" // sections[1] = "room" // Then this function would return the node content for the first <room> // tag found under the first <house> tag. // Function assumes that the desired node has no children nodes other than // the text content node. //------------------------------------------------------------------------------ std::string WEXmlgetter::getValue(const vector<string>& sections) const { std::string aRet; const xmlNode* pPtr = fpRoot; int aSize = sections.size(); int aIdx = 0; //cout << aSize << endl; while (aIdx < aSize) { //cout << aIdx <<" "<< sections[aIdx] << endl; pPtr = getNode(pPtr, sections[aIdx]); if ((pPtr == NULL) || (aIdx == aSize - 1)) break; else { //cout << "getValue Name " << (const char*)pPtr->name << endl; pPtr = pPtr->xmlChildrenNode; aIdx++; } } if (pPtr != NULL) { //aRet = (const char*)pPtr->content; std::string aBuff; if (getNodeContent(pPtr, aBuff)) aRet = aBuff; } return aRet; } //------------------------------------------------------------------------------ // Iterate through the sibling nodes starting with pParent, looking for // a node with the specified name (section). The xmlNode (if found) is // returned. //------------------------------------------------------------------------------ const xmlNode* WEXmlgetter::getNode(const xmlNode* pParent, const string& section)const { if (pParent == NULL) return NULL; const xmlNode* pPtr = pParent; while (pPtr != NULL ) { //cout << "getNode Name " << (const char*)pPtr->name << endl; if (!xmlStrcmp(pPtr->name, (const xmlChar*)section.c_str())) return pPtr; else pPtr = pPtr->next; } return pPtr; } //------------------------------------------------------------------------------ // Iterate down through the node tree represented by the sections vector. // In the last child of this tree, we look for the specified attribute tag, // and return its value. //------------------------------------------------------------------------------ std::string WEXmlgetter::getAttribute(const vector<string>& sections, const string& Tag) const { std::string aRet; const xmlNode* pPtr = fpRoot; int aSize = sections.size(); if (aSize == 0) throw invalid_argument("WEXmlgetter::getAttribute(): section must be valid"); int aIdx = 0; //cout << aSize << endl; while (aIdx < aSize) { //cout << aIdx <<" "<< sections[aIdx] << endl; pPtr = getNode(pPtr, sections[aIdx]); if ((pPtr == NULL) || (aIdx == aSize - 1)) break; else { //cout << "getValue Name " << (const char*)pPtr->name << endl; pPtr = pPtr->xmlChildrenNode; aIdx++; } } if (pPtr != NULL) { std::string aBuff; //cout << "attrTagNode Name " << (const char*)pPtr->name << endl; if (getNodeAttribute(pPtr, Tag.c_str(), aBuff)) aRet = aBuff; //aRet = (const char*)pPtr->content; //cout << "Attribute("<<Tag<<") = "<< aRet<< endl; } return aRet; } //------------------------------------------------------------------------------ // Iterate down through the node tree represented by the sections vector. // At the end of the branch, there may be several sibling nodes matching // the node search vector. // For each of the matching children nodes found, we look for the specified // attribute tag, and return its value. Hence a vector of attribute values // is returned. //------------------------------------------------------------------------------ void WEXmlgetter::getAttributeListForAllChildren( const vector<string>& sections, const string& attributeTag, vector<string>& attributeValues) { const xmlNode* pPtr = fpRoot; int aSize = sections.size(); if (aSize == 0) { throw invalid_argument("WEXmlgetter::getAttributeListForAllChildren():" " No XML nodes specified in section search list"); } // Step down the branch that has the nodes of interest int aIdx = 0; while (aIdx < aSize) { pPtr = getNode(pPtr, sections[aIdx]); if ((pPtr == NULL) || (aIdx == aSize - 1)) { break; } else { pPtr = pPtr->xmlChildrenNode; aIdx++; } } // Look for all the "matching" nodes at the end of the branch, and // get the requested attribute value for each matching node. if (pPtr != NULL) { while (pPtr != NULL ) { std::string attrib; if (getNodeAttribute(pPtr, attributeTag.c_str(), attrib)) { attributeValues.push_back(attrib); } pPtr = pPtr->next; } } } } /* namespace WriteEngine */