Click here to Skip to main content
15,891,033 members
Articles / Programming Languages / C++

A STL based XML Config Tool

Rate me:
Please Sign up or sign in to vote.
3.19/5 (9 votes)
19 Jun 20051 min read 69.8K   886   38  
Writing multiple enumerated configuration entries.
#include "XmlConfig.h"
#include <stdarg.h>

using namespace std;

TypeDefine XmlConfig::m_TypeDefinition;
XmlConfig::XmlConfig( const char* filename )
{
	DefaultInit();
	assert(filename);
	if(filename)
		readFile( filename );	
}

XmlConfig::XmlConfig()
{
	DefaultInit();
}

string XmlConfig::CheckStringForLineBreaks( const char* pstrInput )
{
	string strInput(pstrInput);
	size_t foundClosing = -1;
	do
	{
		foundClosing = strInput.find( "<", foundClosing+1 );
		if( foundClosing != string::npos )
		{
			size_t TagEnd = strInput.find( ">", foundClosing + 2 );
			if( (TagEnd != string::npos) && (strInput[TagEnd+1] == '<' )  )
			{
				strInput.insert( TagEnd + 1, "\r\n" );
			}
		}
	}
	while( foundClosing != string::npos );
	return strInput;
}

void XmlConfig::RemoveString( string& strInput, string& strSignToRemove )
{
	size_t foundLineBreak = -1;
	do
	{
		foundLineBreak = strInput.find( strSignToRemove, 0 );
		if( foundLineBreak != string::npos )
		{
			strInput.erase( foundLineBreak, 1 );
		}
	}
	while( foundLineBreak != string::npos );	
}

void XmlConfig::SetHeader( char* pstrXmlVersion, char* pstrEncoding )
{
	m_strXmlVersion = pstrXmlVersion;
	m_strEncoding = pstrEncoding;
}

void XmlConfig::writeCompleteStream( std::ostream &os ) const
{
	WriteHeader( os );
	m_ParamIO.writeStream( os );
}

void XmlConfig::DefaultInit(void)
{
	m_strXmlVersion = "1.0";
	m_strEncoding = "ISO-8859-1";
}

XmlConfig::~XmlConfig()
{

}

void XmlConfig::readFile(const char *filename)
{
	if(strlen(filename))
		m_ParamIO.readFile( filename );
}

void XmlConfig::writeFile(const char *filename) const
{
	std::ofstream os(filename);
	writeCompleteStream( os );
}

void XmlConfig::WriteHeader( std::ostream &os ) const
{
	//<?xml version="1.0" encoding="ISO-8859-1"?>
	os << "<?xml version=\"" << m_strXmlVersion << "\" encoding=\"" << m_strEncoding << "\"?>" << '\n';
}

void XmlConfig::readStream(std::istream &is)
{
	m_ParamIO.readStream( is );
}

void XmlConfig::writeStream(std::ostream &os) const
{
	m_ParamIO.writeStream( os );
}

bool XmlConfig::ReadSubtree( const char* strSubTree )
{
	m_ActiveTree.clear();
	m_RedCnfgValues.clear();
	bool bSuccessExtract = m_ParamIO.extract( strSubTree, m_ActiveTree );
	XML_Param_Notify theTree = m_ActiveTree.getTree();
	XML_Node::nodes_iterator NodesIter = theTree.top();
	ExtractElements( *NodesIter );
	return bSuccessExtract;
}

size_t XmlConfig::ReadCurrentTree( void )
{
	m_RedCnfgValues.clear();
	XML_Param_Notify theTree = m_ActiveTree.getTree();
	XML_Node::nodes_iterator NodesIter = theTree.top();
	return ExtractElements( *NodesIter );
}

bool XmlConfig::enterSubTree( std::string& strSubTree )//enters the Subtree named in strSubTree, acoording to current Position
{
	XML_Param_Notify theTree = m_ActiveTree.getTree();
	XML_Node::nodes_iterator NodesIter = theTree.top();
	XML_Node node = *NodesIter;
	string strCurrentNode = node.getName();	
	strCurrentNode += ":" + strSubTree;
	XML_Node* pParent = node.getParent();
	while( pParent )
	{
		string strInsertString = pParent->getName() + ':';
		strCurrentNode.insert( 0, strInsertString );
		pParent = pParent->getParent();
	}
	return m_ParamIO.extract( strCurrentNode.c_str(), m_ActiveTree );
}

bool XmlConfig::leaveSubTree(void)//leaves the current Subtree	
{
	XML_Param_Notify theTree = m_ActiveTree.getTree();
	XML_Node::nodes_iterator NodesIter = theTree.top();
	XML_Node node = *NodesIter;
	string strCurrentNode = node.getName();
	size_t iFoundPos = strCurrentNode.rfind( ":" );
	strCurrentNode = strCurrentNode.substr( iFoundPos, strCurrentNode.size() - iFoundPos );
	return m_ParamIO.extract( strCurrentNode.c_str(), m_ActiveTree );
}

size_t XmlConfig::ExtractElements( XML_Node& theNode )
{
	#ifdef _DEBUG
		size_t iNumElements = theNode.getElementCount();
	#endif
	XML_Node::elements_const_iterator iterBegin = theNode.beginElements();
	XML_Node::elements_const_iterator iterEnd = theNode.endElements();	
	for(XML_Node::elements_const_iterator iter = iterBegin; iter != iterEnd; iter++ )
	{
		std::pair<std::string, Element > aPair = *iter;
		std::string strName = aPair.first;
		//cout << "Element Name : "<< strName << '\n';//TBW :maybe usefull for Debug
		Element aEl = aPair.second;
		//cout << "Element Attributes : "<< aEl.attributes << '\n';//TBW :maybe usefull for Debug
		m_RedCnfgValues.AddValue( strName, aEl );
	}
	return m_RedCnfgValues.size();
}

size_t XmlConfig::ExtractNode( XML_Node& theNode )
{
	XML_Node::nodes_const_iterator iterBegin = theNode.beginNodes();
	XML_Node::nodes_const_iterator iterEnd = theNode.endNodes();
	for( XML_Node::nodes_const_iterator iter = iterBegin;iter != iterEnd; iter++ )
	{
		XML_Node node = (*iter);
		string strNodeName = node.getName();
		//cout << "Found a Node : "<< strNodeName << '\n';
		ExtractElements( node );
		ExtractNode( node );
		//cout << '\n';
	}
	return theNode.getElementCount();
}

bool XmlConfig::erase( char* pstrSubKey )
{
	std::vector<std::string> strs;
	ParamIO::parseAccess( pstrSubKey, strs);
	if(strs.size() == 0)
	{
		return false;
	}
	return m_ParamIO.erase( pstrSubKey );
}

int XmlConfig::erase( char* pstrSubKey, char* pstrAttributeMatchKey, ... )
{
	va_list marker;
	va_start( marker, pstrAttributeMatchKey );
	std::vector<string> vKeyString;
	while( pstrAttributeMatchKey != 0 )
	{
		vKeyString.push_back( std::string( pstrAttributeMatchKey ) );
		pstrAttributeMatchKey = va_arg( marker, char* );  
	}
	va_end( marker );
	return m_ParamIO.erase( pstrSubKey, vKeyString );
}

int XmlConfig::RemoveAttributes( char* pstrKey, char* strAttributeName, char* pstrAttributeMatchKey, ...  )
{
	va_list marker;
	va_start( marker, pstrAttributeMatchKey );
	std::vector<string> vKeyString;
	while( pstrAttributeMatchKey != 0 )
	{
		vKeyString.push_back( std::string( pstrAttributeMatchKey ) );
		pstrAttributeMatchKey = va_arg( marker, char* );  
	}
	va_end( marker );
	return m_ParamIO.removeAttributes( pstrKey, vKeyString, strAttributeName );
}

int XmlConfig::AddAttributeString( char* pstrKey, char* pstrAttributeString, char* pstrAttributeMatchKey, ... )
{
	va_list marker;
	va_start( marker, pstrAttributeMatchKey );
	std::vector<string> vKeyString;
	while( pstrAttributeMatchKey != 0 )
	{
		vKeyString.push_back( std::string( pstrAttributeMatchKey ) );
		pstrAttributeMatchKey = va_arg( marker, char* );  
	}
	va_end( marker );
	return m_ParamIO.addAttributeString( pstrKey, vKeyString, pstrAttributeString );		
}

size_t XmlConfig::hasSubNodes( char* pstrSubKey, string& strFirstNodeName )
{
	m_ActiveTree.clear();
	bool bSuccessExtract = m_ParamIO.extract( pstrSubKey, m_ActiveTree );
	XML_Param_Notify theTree = m_ActiveTree.getTree();
	XML_Node::nodes_iterator NodesIter = theTree.top();
	XML_Node node = *NodesIter;
	size_t iNumSubNodes = node.getNodeCount();
	if(iNumSubNodes)
	{
		node = *node.beginNodes();
		strFirstNodeName = node.getName();
	}
	return iNumSubNodes;
}

void XmlConfig::readBuffer( char* pstrBuffer )
{
	stringstream theStream(pstrBuffer);
	m_ParamIO.readStream( theStream );
}

///////////////////////////////////////////////////////////////////////////////////////////
//CfgValueCont
///////////////////////////////////////////////////////////////////////////////////////////
CfgValueCont::CfgValueCont()
{

}

void CfgValueCont::AddValue( string strKeyName, Element& aEl )
{
	ConfigValue aVal( strKeyName, aEl.value.c_str() );
	m_vReadCnfgValue.push_back(aVal);
}

///////////////////////////////////////////////////////////////////////////////////////////
//ConfigValue
///////////////////////////////////////////////////////////////////////////////////////////
ConfigValue::ConfigValue( string strKeyName, Element& aEl )
{
	strKeyName = strKeyName;
	ParesAttributeString( aEl.attributes );
}

ConfigValue::ConfigValue( string strKeyName, const char* pstrAtribute )
{
	strKeyName = strKeyName;
	ParesAttributeString( string( pstrAtribute ) );
}

void ConfigValue::ParesAttributeString( string& strAttrib )
{
	std::vector<string> vTokens;
	string::size_type TokenBeginPos = 0;
	while( TokenBeginPos != string::npos )
	{
		string::size_type AtribbBeginPos = strAttrib.find( '"', TokenBeginPos );
		string::size_type TokenEndPosPos = strAttrib.find( '"', AtribbBeginPos+1 );
		string strToke = strAttrib.substr( TokenBeginPos, (TokenEndPosPos - TokenBeginPos) );
		if(TokenEndPosPos != string::npos && AtribbBeginPos != string::npos )
		{	
			if( strToke[0] == ' ' )strToke.erase( 0, 1 );// remove preceding Space
			m_vFoundValues.push_back( Attribute(strToke) );
			TokenBeginPos = TokenEndPosPos+1;
		}
		else
			TokenBeginPos = string::npos;
	}
}

///////////////////////////////////////////////////////////////////////////////////////////
//Attribute
///////////////////////////////////////////////////////////////////////////////////////////
Attribute::Attribute( string& strToken )
{
	m_ValType = XmlConfig::m_TypeDefinition.GetType( strToken, m_strAttributeName );
	string::size_type ValueBegin = strToken.find( '"' );
	string::size_type ValueEnd = strToken.find( '"', ValueBegin+1 );
	m_strAttributeValue = strToken.substr( ValueBegin+1, ValueEnd-1 );
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer
Germany Germany
Studying and having a degree of medical engineering, but decided to work as a software developer writing medical applications for image processing.

Comments and Discussions