#ifndef XML_NODE_H
#define XML_NODE_H
#pragma warning (disable : 4786)
#include <string>
#include <vector>
#include <algorithm>
#include "XmlNotify.h"
class ParamIO;
class Element
{
public:
Element()
{
}
Element(const std::string &v, const std::string &a):
value(v),
attributes(a)
{
}
std::string value;
std::string attributes;
//TBW : Added ==
bool operator==( const Element& aEl )const
{
if( aEl.value == value && aEl.attributes == attributes )
return true;
else
return false;
}
};
//TBW : added to look for Elements specific to their Atttributes
class FindElementByAttribute
{
public:
FindElementByAttribute( const std::string strName, const std::vector<std::string>& vTokensToFindInAttributes ) : m_strName(strName), m_vAttributeTokensToFind(vTokensToFindInAttributes){}
bool operator()(const std::pair<std::string, Element> &p)
{
if( p.first == m_strName )
{
if(m_vAttributeTokensToFind.empty())//ready if nothing else to check
return true;
size_t iFoundPos = 0;// to not find two times the same again
std::vector<std::string>::iterator itBeg = (const std::vector<std::string>::iterator)m_vAttributeTokensToFind.begin();
std::vector<std::string>::iterator itEnd = (const std::vector<std::string>::iterator)m_vAttributeTokensToFind.end();
std::string strAttributes = p.second.attributes;
for( std::vector<std::string>::iterator iter = itBeg; iter != itEnd; iter++ )
{
if( (iFoundPos = strAttributes.find( *iter ) )== std::string::npos )
return false;
else
{
//eliminate the found String to not find it again
strAttributes.erase( iFoundPos, (*iter).size() );
}
}
return true;
}
return false;
}
std::string m_strName;
std::vector<std::string> m_vAttributeTokensToFind;
};
class FindElement//TBW : changed ->only equal, if whole Element matches
{
public:
FindElement( const std::string strName, const Element aElem ) : m_strName(strName), m_Elem(aElem)
{
m_bFullCompare = true;
}
FindElement( std::string strName) : m_strName(strName)
{
m_bFullCompare = false;
}
bool operator()(const std::pair<std::string, Element> &p) const
{
if(!m_bFullCompare)
{
return p.first == m_strName;
}
else
{
return ((p.first == m_strName) && (m_Elem == p.second ));
}
return false;
}
bool m_bFullCompare;//shall both be compared?
std::string m_strName;
Element m_Elem;
};
class FindNode;
class XML_Node
{
public:
typedef std::vector<XML_Node>::const_iterator nodes_const_iterator;
typedef std::vector<XML_Node>::iterator nodes_iterator;
typedef std::vector< std::pair<std::string, Element > >::iterator elements_iterator;
typedef std::vector< std::pair<std::string, Element > >::const_iterator elements_const_iterator;
XML_Node();
XML_Node(const std::string &name, const std::string &attributes, XML_Node *parent);
void set(const std::string &name, const std::string &attributes, XML_Node *parent);
int removeAttributesFromElements(const std::string &name, std::vector<std::string>& vTokensToFindInAttributes, const std::string &AttributesToRemove );//removes Attributes from Elements matching the specified Key in vector
int addAttributesToElements(const std::string &name, std::vector<std::string>& vTokensToFindInAttributes, const std::string &AttributesToAdd );//adds Attributes to Elements matching the specified Key in vector
void addElement(const std::string &name, const std::string &value, const std::string &attributes);
XML_Node *addNode(const std::string &name, const std::string &attributes);
bool getElement(const std::string &name, std::string &value, std::string &attributes);
bool setElementValue(const std::string &name, const std::string &value);
elements_const_iterator beginElements() const;
elements_const_iterator endElements() const;
nodes_const_iterator beginNodesConst() const;
nodes_const_iterator endNodesConst() const;
nodes_iterator beginNodes();
nodes_iterator endNodes();
nodes_const_iterator findNode(const std::string &name) const;
nodes_iterator findNode(const std::string &name);
const std::string &getName() const;
template<class T>
bool extractValue(const std::string &str, T &value) const
{
elements_const_iterator it = std::find_if(_elements.begin(), _elements.end(), FindElement(str));
if(it == endElements())
{
return false;
}
std::stringstream ist(it->second.value);
ist >> value;
return ist.fail()==0;
}
// We need a specific method in std::string case so that
// we can get space-separated words
bool extractValue(const std::string &str, std::string &value) const;
XML_Node *getParent();
void print(std::ostream &os) const;
void clear();
bool eraseElement(const std::string &name);
int eraseElements( const std::string &name, std::vector<std::string>& vTokensToFindInAttributes );//erases all Elements matching the attribute - strings in vector
bool eraseNode(const std::string &name);
~XML_Node();
//Added by TBW for Debug Help
size_t getElementCount(void) const{ return _elements.size(); }
size_t getNodeCount(void) const{ return _nodes.size(); }
private:
// In case we have no child node
std::vector< std::pair<std::string, Element > > _elements;
std::string _name, _attributes;
// In case we have child node
std::vector<XML_Node> _nodes;
// Parent
XML_Node* _parent;
};
class XML_Param_Notify : public XmlNotify
{
public:
XML_Param_Notify();
virtual ~XML_Param_Notify();
void clear();
XML_Node::nodes_iterator top();
template<class T>
bool extractValue(std::vector<std::string> strs, T &value) const
{
// First we need to find the final node
std::string paramName = strs.back();
strs.pop_back();
XML_Node::nodes_const_iterator res = getNodeConst(strs);
if(res == static_cast<XML_Node::nodes_const_iterator>(0))
{
return false;
}
// We found the last node, find the element
return res->extractValue(paramName, value);
}
XML_Node::nodes_const_iterator getNodeConst( std::vector<std::string> &strs ) const;
XML_Node::nodes_iterator getNode(std::vector<std::string> &strs);
template<class T>
bool addElement(std::vector<std::string> &strs, T &value)
{
// First we need to find the final node
XML_Node::nodes_iterator prevRes = GetAddIterator(strs);
std::stringstream stream;
stream << value;/* << std::ends; => adds an useless extra character*/
prevRes->addElement(strs.back(), stream.str(), std::string());
return true;
}
bool compare(const ParamIO &old, std::vector<std::string> &strs) const;
bool extractSubTree(std::vector<std::string> &strs, ParamIO &subTree) const;
bool eraseSubTree(std::vector<std::string> &strs);
//TBW : added
XML_Node::nodes_iterator GetAddIterator(std::vector<std::string> &strs);
int eraseElement( std::vector<std::string> &vNodes, std::vector<std::string>& vTokensToFindInAttributes );//erasese all elements matching name and Attribute strings in vector
int addElementAttributes( std::vector<std::string> &vNodes, std::vector<std::string>& vTokensToFindInAttributes, const std::string& strAttributeVal );
int removeElementAttributes( std::vector<std::string> &vNodes, std::vector<std::string>& vTokensToFindInAttributes, const std::string& strAttributeVal );
bool addElement( std::vector<std::string> &strs, const char* strAttributeString );//creates an Element setting its Attributes
int addAttributeString( std::vector<std::string> &vNodes, std::vector<std::string>& vTokensToFindInAttributes, const char* strAttributeString );//sets the complete Attribute String -> overriding the old one
void print(std::ostream &os) const;
// notify methods
virtual void foundNode( std::string & name, std::string & attributes );
virtual void endNode( std::string & name, std::string & attributes );
virtual void foundElement( std::string & name, std::string & value, std::string & attributes );
private:
bool compareElement(const ParamIO &old, std::vector<std::string> &strs) const;
bool compareSubTree(const ParamIO &old, std::vector<std::string> &strs) const;
bool compareAllElements(XML_Node::nodes_const_iterator it, XML_Node::nodes_const_iterator itOld) const;
bool compareAllChildren(XML_Node::nodes_const_iterator it, XML_Node::nodes_const_iterator itOld) const;
XML_Node _node;
XML_Node *_currentNode;
};
// class used by find_if in findSameName method
// Note : we could have avoided the FindSameName class using a std::string
// converter operator for the XML_Node class. But adding such an operator
// for this purpose didn't seem right.
class FindNode
{
public:
FindNode(const std::string &name):
_name(name)
{
}
bool operator()(const XML_Node &node)
{
return _name.compare(node.getName()) == 0?true:false;
}
std::string _name;
};
#endif