00001 #include "XMLNode.h"
00002 #include "Error.h"
00003
00004 namespace RenderTools {
00005
00006 bool XMLNode::s_verbose = false;
00007
00008 XMLNode::XMLNode( void ){
00009 }
00010
00011 XMLNode::XMLNode( const string tagname ){
00012 m_tagName = tagname;
00013 }
00014
00015 void XMLNode::load( const string file ){
00016 Error::assertNoErrors( __FILE__, __LINE__ );
00017
00018 string cleanName = cleanup( file );
00019
00020 char * text = 0;
00021
00022 bool maybeFile = true;
00023 if( cleanName.size() && cleanName[0] =='<' ){
00025 maybeFile = false;
00026 }
00027 else if( findFile( cleanName, s_verbose ) == "" ){
00029 maybeFile = false;
00030
00032 if( cleanName[0] != '<' ){
00034 cleanName = "<" + cleanName + "/>";
00035 }
00036 }
00037
00039 FILE * fp = 0;
00040 if( maybeFile && ( fp = fopen( findFile( cleanName, s_verbose ).c_str(), "rb" ) ) != 0 ){
00041
00042 fseek( fp, 0, SEEK_END );
00043 int len = ftell( fp );
00044 fseek( fp, 0, SEEK_SET );
00045
00046 text = (char *)calloc( len + 1, 1 );
00047 if( ! text ){
00048 Error::error( Error::MEMORY_ALLOCATION_FAILED, __FILE__, __LINE__ );
00049 }
00050 fread( text, 1, len, fp );
00052 fflush( fp );
00053 fclose( fp );
00055 text[ len ] = '\0';
00056 }
00057 else{
00059 text = (char *)calloc( cleanName.size() + 1, 1 );
00060 if( ! text ){
00061 Error::error( Error::MEMORY_ALLOCATION_FAILED, __FILE__, __LINE__ );
00062 }
00063 memcpy( text, cleanName.c_str(), cleanName.size() );
00065 text[ cleanName.size() ] = '\0';
00066 }
00067
00068 if( text ){
00069 #ifdef RT_RAPIDXML
00070 xml_document<> doc;
00071
00072 doc.parse<0>( text );
00073
00074 m_tagName = doc.first_node()->name();
00075 populate( doc.first_node() );
00076
00078 doc.clear();
00079
00080 free( text );
00081
00082 #elif WIN32
00083 # pragma message( "\twarning: XMLNode constructor not complete due to missing RT_RAPIDXML" )
00084 #elif APPLE
00085 # warning ( "\twarning: XMLNode constructor not complete due to missing RT_RAPIDXML" )
00086 #endif
00087 }
00088 else{
00089 Error::error( Error::NULL_POINTER, __FILE__, __LINE__ );
00090 }
00091 }
00092
00093 XMLNode::~XMLNode(){
00094 }
00095
00096 bool XMLNode::save( const string filename ){
00097 FILE * fp;
00098 if( ( fp = fopen( filename.c_str(), "wb" ) ) != 0 ){
00099 fprintf( fp, "%s", toString().c_str() );
00100 fflush( fp );
00101 fclose( fp );
00102 return( true );
00103 }
00104 return( false );
00105 }
00106
00107 const string XMLNode::toString( void ) const {
00108 string tag;
00110 tag += string( "<" ) + m_tagName + string( " " );
00111
00113 map< string, string >::const_iterator i = m_attributes.begin();
00114 for( ; i != m_attributes.end(); i++ ){
00115 tag += i->first + string( "=\"" ) + i->second + string( "\" " );
00116 }
00117
00118 if( ! m_children.size() ){
00120 tag += string( "/>\n" );
00121 }
00122 else{
00124 tag += string( ">\n" );
00126 for( unsigned int j = 0; j < m_children.size(); j++ ){
00127 tag += m_children[ j ]->toString();
00128 }
00130 tag += string( "</" ) + m_tagName + string( ">\n" );
00131 }
00132
00133 return( tag );
00134 }
00135
00136 #ifdef RT_RAPIDXML
00137 void XMLNode::populate( const xml_node<> * node ){
00138 for( xml_attribute<> * attr = node->first_attribute(); attr; attr = attr->next_attribute() ){
00139 m_attributes[ attr->name() ] = attr->value();
00140 }
00141 for( xml_node<> * child = node->first_node(); child; child = child->next_sibling() ){
00142 addChild( child->name() )->populate( child );
00143 }
00144 }
00145 #endif
00146
00147 void XMLNode::setTagName( const string name ){
00148 m_tagName = name;
00149 }
00150
00151 void XMLNode::setParent( const XMLNodePtr parent ){
00152 m_parent = parent;
00153 }
00154
00155 const XMLNodePtr XMLNode::getParent( void ) const {
00156 return( m_parent.lock() );
00157 }
00158
00159 const XMLNodePtr XMLNode::findRoot( void ){
00160 XMLNodePtr root = getSharedPtr< XMLNode >();
00161 XMLNodePtr parent = getParent();
00162 while( parent ){
00163 root = parent;
00164 parent = parent->getParent();
00165 }
00166 return( root );
00167 }
00168
00169 const string XMLNode::getTagName( void ) const {
00170 return( m_tagName );
00171 }
00172
00173 bool XMLNode::hasChildren( void ) const {
00174 return( m_children.size() != 0 );
00175 }
00176
00177 const XMLNodePtr XMLNode::getChild( const string name ) const {
00178 string cleanName = cleanup( name );
00179 for( unsigned int i = 0; i < m_children.size(); i++ ){
00180 if( m_children[ i ]->getTagName() == cleanName ){
00181 return( m_children[ i ] );
00182 }
00183 }
00184 return( XMLNodePtr() );
00185 }
00186
00187 const XMLNodePtr XMLNode::nextChild( const XMLNodePtr previous ) const {
00188 if( m_children.size() ){
00189 if( ! previous ){
00190 return( m_children[ 0 ] );
00191 }
00192 for( unsigned int i = 0; i < m_children.size() - 1; i++ ){
00193 if( m_children[ i ] == previous ){
00194 return( m_children[ i + 1 ] );
00195 }
00196 }
00197 }
00198 return( XMLNodePtr() );
00199 }
00200
00201 XMLNodePtr XMLNode::nextChild( XMLNodePtr previous ){
00202 if( m_children.size() ){
00203 if( ! previous ){
00204 return( m_children[ 0 ] );
00205 }
00206 for( unsigned int i = 0; i < m_children.size() - 1; i++ ){
00207 if( m_children[ i ] == previous ){
00208 return( m_children[ i + 1 ] );
00209 }
00210 }
00211 }
00212 return( XMLNodePtr() );
00213 }
00214
00215 bool XMLNode::hasAttrib( const string name ) const {
00216 return( m_attributes.find( name ) != m_attributes.end() );
00217 }
00218
00219 const string XMLNode::getFullName( void ){
00220 string name;
00222 if( hasAttrib( "type" ) ){
00223 name += getAttrib<string>( "type" ) + "::";
00224 }
00225 return( name + m_tagName );
00226 }
00227
00228 const XMLNodePtr XMLNode::addChild( const string name, const string value ){
00230 XMLNodePtr child( new XMLNode() );
00231 child->setParent( getSharedPtr< XMLNode >() );
00232 child->setTagName( cleanup( name ) );
00233 child->setAttrib<string>( "value", cleanup( value ) );
00234 m_children.push_back( child );
00235 return( child );
00236 }
00237
00238 const XMLNodePtr XMLNode::addChild( const string name ){
00239 XMLNodePtr child( new XMLNode() );
00240 child->setParent( getSharedPtr< XMLNode >() );
00241 child->setTagName( cleanup( name ) );
00242 m_children.push_back( child );
00243 return( child );
00244 }
00245
00246 const XMLNodePtr XMLNode::addChild( XMLNodePtr child ){
00247 child->setParent( getSharedPtr< XMLNode >() );
00248 m_children.push_back( child );
00249 return( child );
00250 }
00251
00252 bool XMLNode::isChild( const XMLNodePtr lookForChild ) const {
00253 for( unsigned int i = 0; i < m_children.size(); i++ ){
00254 if( m_children[ i ] == lookForChild || m_children[ i ]->isChild( lookForChild ) ){
00255 return( true );
00256 }
00257 }
00258 return( false );
00259 }
00260
00261 bool XMLNode::isParent( const XMLNodePtr lookForParent ) const {
00262 XMLNodePtr thisPtr = getSharedPtr< XMLNode >();
00263 XMLNodePtr parent = getParent();
00264 while( parent ){
00265 if( parent == lookForParent ){
00266 return( true );
00267 }
00268 parent = parent->getParent();
00269 }
00270 return( false );
00271 }
00272
00273 const XMLNodePtr XMLNode::findByFullName( const string className, const string propertyName, const XMLNodePtr inXml ){
00274 return( findByFullName( className + "::" + propertyName ) );
00275 }
00276
00277 const XMLNodePtr XMLNode::findByFullName( const string fullname, const XMLNodePtr inXml ){
00278 XMLNodePtr xml = inXml;
00279 if( ! xml ){
00280 xml = findRoot();
00281 }
00282
00284 if( xml->getFullName() == fullname && xml->hasChildren() ){
00285 return( xml );
00286 }
00287
00288 XMLNodePtr child = XMLNodePtr();
00289 while( ( child = xml->nextChild( child ) ) ){
00290 if( findByFullName( fullname, child ) ){
00291 return( child );
00292 }
00293 }
00294 return( XMLNodePtr() );
00295 }
00296
00297 void XMLNode::setVerbose( bool state ){
00298 s_verbose = state;
00299 }
00300
00301 bool XMLNode::isVerbose( void ){
00302 return( s_verbose );
00303 }
00304
00305 };