#include <cppunit/tools/StringTools.h>
#include <cppunit/tools/XmlElement.h>
#include <stdexcept>
CPPUNIT_NS_BEGIN
XmlElement::XmlElement( std::string elementName,
std::string content )
: m_name( elementName )
, m_content( content )
, m_attributes()
, m_elements()
{
}
XmlElement::XmlElement( std::string elementName,
int numericContent )
: m_name( elementName )
, m_content()
, m_attributes()
, m_elements()
{
setContent( numericContent );
}
XmlElement::~XmlElement()
{
Elements::iterator itNode = m_elements.begin();
while ( itNode != m_elements.end() )
{
XmlElement *element = *itNode++;
delete element;
}
}
std::string
XmlElement::name() const
{
return m_name;
}
std::string
XmlElement::content() const
{
return m_content;
}
void
XmlElement::setName( const std::string &name )
{
m_name = name;
}
void
XmlElement::setContent( const std::string &content )
{
m_content = content;
}
void
XmlElement::setContent( int numericContent )
{
m_content = StringTools::toString( numericContent );
}
void
XmlElement::addAttribute( std::string attributeName,
std::string value )
{
m_attributes.push_back( Attribute( attributeName, value ) );
}
void
XmlElement::addAttribute( std::string attributeName,
int numericValue )
{
addAttribute( attributeName, StringTools::toString( numericValue ) );
}
void
XmlElement::addElement( XmlElement *node )
{
m_elements.push_back( node );
}
int
XmlElement::elementCount() const
{
return m_elements.size();
}
XmlElement *
XmlElement::elementAt( int index ) const
{
if ( index < 0 || index >= elementCount() )
throw std::invalid_argument( "XmlElement::elementAt(), out of range index" );
return m_elements[ index ];
}
XmlElement *
XmlElement::elementFor( const std::string &name ) const
{
Elements::const_iterator itElement = m_elements.begin();
for ( ; itElement != m_elements.end(); ++itElement )
{
if ( (*itElement)->name() == name )
return *itElement;
}
throw std::invalid_argument( "XmlElement::elementFor(), not matching child element found" );
return NULL; // make some compilers happy.
}
std::string
XmlElement::toString( const std::string &indent ) const
{
std::string element( indent );
element += "<";
element += m_name;
if ( !m_attributes.empty() )
{
element += " ";
element += attributesAsString();
}
element += ">";
if ( !m_elements.empty() )
{
element += "\n";
std::string subNodeIndent( indent + " " );
Elements::const_iterator itNode = m_elements.begin();
while ( itNode != m_elements.end() )
{
const XmlElement *node = *itNode++;
element += node->toString( subNodeIndent );
}
element += indent;
}
if ( !m_content.empty() )
{
element += escape( m_content );
if ( !m_elements.empty() )
{
element += "\n";
element += indent;
}
}
element += "</";
element += m_name;
element += ">\n";
return element;
}
std::string
XmlElement::attributesAsString() const
{
std::string attributes;
Attributes::const_iterator itAttribute = m_attributes.begin();
while ( itAttribute != m_attributes.end() )
{
if ( !attributes.empty() )
attributes += " ";
const Attribute &attribute = *itAttribute++;
attributes += attribute.first;
attributes += "=\"";
attributes += escape( attribute.second );
attributes += "\"";
}
return attributes;
}
std::string
XmlElement::escape( std::string value ) const
{
std::string escaped;
for ( unsigned int index =0; index < value.length(); ++index )
{
char c = value[index ];
switch ( c ) // escape all predefined XML entity (safe?)
{
case '<':
escaped += "<";
break;
case '>':
escaped += ">";
break;
case '&':
escaped += "&";
break;
case '\'':
escaped += "'";
break;
case '"':
escaped += """;
break;
default:
escaped += c;
}
}
return escaped;
}
CPPUNIT_NS_END