00001 #ifndef __XML_CPP__
00002 #define __XML_CPP__
00003
00004 #include <list>
00005
00006 #include <loaders/xml.h>
00007 #include <system/file_abstraction.h>
00008 #include <utilities/binary_data.h>
00009 #include <utilities/exception.h>
00010 #include <utilities/file_utilities.h>
00011 #include <utilities/string_utilities.h>
00012
00013 namespace nitro
00014 {
00015 bool IsTagName( std::string Lexemma )
00016 {
00017 if( isdigit( Lexemma[ 0 ] ) )return( false );
00018
00019 if( Lexemma == "/" )return( false );
00020
00021 for( size_t i( 0 ) ; i < Lexemma.size() ; i++ )
00022 {
00023 if( isalnum( ( unsigned char )Lexemma[ i ] ) || Lexemma[ i ] == '_' || Lexemma[ i ] == ':' )
00024 {
00025
00026 }
00027 else
00028 {
00029 return( false );
00030 }
00031 }
00032
00033 return( true );
00034 }
00035
00036 std::size_t XMLTag::CountOfChildTags( void ) const
00037 {
00038 try
00039 {
00040 return( Tags.size() );
00041 }
00042 catch( nitro::exception e )
00043 {
00044 throw( nitro::exception( std::string( "XMLTag::CountOfChildTags( void )::" ) + e.what() , e.code() ) );
00045 }
00046 catch( ... )
00047 {
00048 throw( nitro::exception( std::string( "XMLTag::CountOfChildTags( void )::An error occured" ) , 1 ) );
00049 }
00050 }
00051
00052 std::size_t XMLTag::CountOfAttributes( void ) const
00053 {
00054 try
00055 {
00056 return( Attributes.size() );
00057 }
00058 catch( nitro::exception e )
00059 {
00060 throw( nitro::exception( std::string( "XMLTag::CountOfAttributes( void )::" ) + e.what() , e.code() ) );
00061 }
00062 catch( ... )
00063 {
00064 throw( nitro::exception( std::string( "XMLTag::CountOfAttributes( void )::An error occured" ) , 1 ) );
00065 }
00066 }
00067
00068 const char * XMLTag::GetAttributeName( std::size_t AttributeCursor ) const
00069 {
00070 try
00071 {
00072 if( Attributes.size() >= AttributeCursor )
00073 {
00074 throw( nitro::exception( "Illegal attribute's cursor" , 1 ) );
00075 }
00076
00077 return( Attributes[ AttributeCursor ].c_str() );
00078 }
00079 catch( nitro::exception e )
00080 {
00081 throw( nitro::exception( std::string( "XMLTag::GetAttributeName( std::size_t AttributeCursor )::" ) + e.what() , e.code() ) );
00082 }
00083 catch( ... )
00084 {
00085 throw( nitro::exception( std::string( "XMLTag::GetAttributeName( std::size_t AttributeCursor )::An error occured" ) , 1 ) );
00086 }
00087 }
00088
00089 XMLTag::XMLTag( void )
00090 {
00091 }
00092
00093 XMLTag::XMLTag( const XMLTag & Tag )
00094 {
00095 try
00096 {
00097 for( std::size_t i( 0 ) ; i < Tag.Tags.size() ; i++ )
00098 {
00099 Tags.push_back( new XMLTag( * Tag.Tags[ i ] ) );
00100 }
00101
00102 Name = Tag.Name;
00103
00104 std::copy( Tag.Attributes.begin() , Tag.Attributes.end() , std::back_inserter( Attributes ) );
00105 std::copy( Tag.Values.begin() , Tag.Values.end() , std::back_inserter( Values ) );
00106 }
00107 catch( nitro::exception e )
00108 {
00109 throw( nitro::exception( std::string( "XMLTag::XMLTag( const XMLTag & XMLTag )::" ) + e.what() , e.code() ) );
00110 }
00111 catch( ... )
00112 {
00113 throw( nitro::exception( std::string( "XMLTag::XMLTag( const XMLTag & XMLTag )::An error occured" ) , 1 ) );
00114 }
00115 }
00116
00117 XMLFile::XMLFile( void )
00118 {
00119 try
00120 {
00121 Version = "";
00122 Encoding = "";
00123 OpenFilePath = "";
00124 }
00125 catch( nitro::exception e )
00126 {
00127 throw( nitro::exception( std::string( "XMLFile::XMLFile( void )::" ) + e.what() , e.code() ) );
00128 }
00129 catch( ... )
00130 {
00131 throw( nitro::exception( std::string( "XMLFile::XMLFile( void )::An error occured" ) , 1 ) );
00132 }
00133 }
00134
00135 XMLFile::XMLFile( const char * FilePath )
00136 {
00137 try
00138 {
00139 Version = "";
00140 Encoding = "";
00141
00142 OpenFilePath = FilePath;
00143
00144 LoadXML( FilePath );
00145 }
00146 catch( nitro::exception e )
00147 {
00148 throw( nitro::exception( std::string( "XMLFile::XMLFile( const char * FilePath )::" ) + e.what() , e.code() ) );
00149 }
00150 catch( ... )
00151 {
00152 throw( nitro::exception( std::string( "XMLFile::XMLFile( const char * FilePath )::An error occured" ) , 1 ) );
00153 }
00154 }
00155
00156 XMLFile::XMLFile( const std::string & FilePath )
00157 {
00158 try
00159 {
00160 Version = "";
00161 Encoding = "";
00162
00163 OpenFilePath = FilePath;
00164
00165 LoadXML( FilePath );
00166 }
00167 catch( nitro::exception e )
00168 {
00169 throw( nitro::exception( std::string( "XMLFile::XMLFile( const std::string & FilePath )::" ) + e.what() , e.code() ) );
00170 }
00171 catch( ... )
00172 {
00173 throw( nitro::exception( std::string( "XMLFile::XMLFile( const std::string & FilePath )::An error occured" ) , 1 ) );
00174 }
00175 }
00176
00177 void XMLTag::Release( void )
00178 {
00179 try
00180 {
00181 for( std::size_t i( 0 ) ; i < Tags.size() ; i++ )
00182 {
00183 Tags[ i ]->Release();
00184 }
00185
00186 Tags.clear();
00187 }
00188 catch( nitro::exception e )
00189 {
00190 throw( nitro::exception( std::string( "XMLTag::Release( void )::" ) + e.what() , e.code() ) );
00191 }
00192 catch( ... )
00193 {
00194 throw( nitro::exception( std::string( "XMLTag::Release( void )::An error occured" ) , 1 ) );
00195 }
00196 }
00197
00198 XMLTag::~XMLTag()
00199 {
00200 try
00201 {
00202 Release();
00203 }
00204 catch( ... )
00205 {
00206 }
00207 }
00208
00209 XMLTag & XMLTag::operator[] ( const char * TagName ) const
00210 {
00211 try
00212 {
00213 std::string TagName( TagName );
00214 for( std::size_t i( 0 ) ; i < Tags.size() ; i++ )
00215 {
00216 if( TagName == Tags[ i ]->Name )
00217 {
00218 return( * Tags[ i ] );
00219 }
00220 }
00221 throw( nitro::exception( std::string( "Tag " ) + TagName + " was not found" , 1 ) );
00222 }
00223 catch( nitro::exception e )
00224 {
00225 throw( nitro::exception( std::string( "XMLTag::operator[] ( const char * TagName )::" ) + e.what() , e.code() ) );
00226 }
00227 catch( ... )
00228 {
00229 throw( nitro::exception( std::string( "XMLTag::operator[] ( const char * TagName )::An error occured" ) , 1 ) );
00230 }
00231 }
00232
00233 void XMLTag::AddAttribute( const char * AttributeName , const char * AttributeValue )
00234 {
00235 try
00236 {
00237 Attributes.push_back( std::string( AttributeName ) );
00238 Values.push_back( std::string( AttributeValue ) );
00239 }
00240 catch( nitro::exception e )
00241 {
00242 throw( nitro::exception( std::string( "XMLTag::AddAttribute( const char * AttributeName , const char * AttributeValue )::" ) + e.what() , e.code() ) );
00243 }
00244 catch( ... )
00245 {
00246 throw( nitro::exception( std::string( "XMLTag::AddAttribute( const char * AttributeName , const char * AttributeValue )::An error occured" ) , 1 ) );
00247 }
00248 }
00249
00250 void XMLTag::AddTag( const char * TagName )
00251 {
00252 try
00253 {
00254 Tags.push_back( new XMLTag() );
00255 Tags.back()->Name = TagName;
00256 }
00257 catch( nitro::exception e )
00258 {
00259 throw( nitro::exception( std::string( "XMLTag::AddTag( const char * TagName )::" ) + e.what() , e.code() ) );
00260 }
00261 catch( ... )
00262 {
00263 throw( nitro::exception( std::string( "XMLTag::AddTag( const char * TagName )::An error occured" ) , 1 ) );
00264 }
00265 }
00266
00267 void XMLTag::AddTag( const XMLTag & Tag )
00268 {
00269 try
00270 {
00271 Tags.push_back( new XMLTag( Tag ) );
00272 }
00273 catch( nitro::exception e )
00274 {
00275 throw( nitro::exception( std::string( "XMLTag::AddTag( const XMLTag & XMLTag )::" ) + e.what() , e.code() ) );
00276 }
00277 catch( ... )
00278 {
00279 throw( nitro::exception( std::string( "XMLTag::AddTag( const XMLTag & XMLTag )::An error occured" ) , 1 ) );
00280 }
00281 }
00282
00283 bool XMLTag::AttributeExists( const char * AttributeName ) const
00284 {
00285 try
00286 {
00287 for( std::size_t i( 0 ) ; i < Attributes.size() ; i++ )
00288 {
00289 if( AttributeName == Attributes[ i ] )
00290 {
00291 return( true );
00292 }
00293 }
00294 return( false );
00295 }
00296 catch( nitro::exception e )
00297 {
00298 throw( nitro::exception( std::string( "XMLTag::AttributeExists( const char * AttributeName ) const::" ) + e.what() , e.code() ) );
00299 }
00300 catch( ... )
00301 {
00302 throw( nitro::exception( std::string( "XMLTag::AttributeExists( const char * AttributeName ) const::An error occured" ) , 1 ) );
00303 }
00304 }
00305
00306 bool XMLTag::TagExists( char * TagName ) const
00307 {
00308 try
00309 {
00310 for( std::size_t i( 0 ) ; i < Tags.size() ; i++ )
00311 {
00312 if( Tags[ i ]->Name == TagName )
00313 {
00314 return( true );
00315 }
00316 }
00317 return( false );
00318 }
00319 catch( nitro::exception e )
00320 {
00321 throw( nitro::exception( std::string( "XMLTag::TagExists( char * TagName ) const::" ) + e.what() , e.code() ) );
00322 }
00323 catch( ... )
00324 {
00325 throw( nitro::exception( std::string( "XMLTag::TagExists( char * TagName ) const::An error occured" ) , 1 ) );
00326 }
00327 }
00328
00329 void XMLTag::DeleteTag( std::size_t TagCursor )
00330 {
00331 try
00332 {
00333 Tags[ TagCursor ]->Release();
00334 Tags.erase( Tags.begin() + TagCursor );
00335 }
00336 catch( nitro::exception e )
00337 {
00338 throw( nitro::exception( std::string( "XMLTag::DeleteTag( std::size_t TagCursor )::" ) + e.what() , e.code() ) );
00339 }
00340 catch( ... )
00341 {
00342 throw( nitro::exception( std::string( "XMLTag::DeleteTag( std::size_t TagCursor )::An error occured" ) , 1 ) );
00343 }
00344 }
00345
00346 XMLTag & XMLTag::LastTag( void )
00347 {
00348 try
00349 {
00350 return( *( Tags.back() ) );
00351 }
00352 catch( nitro::exception e )
00353 {
00354 throw( nitro::exception( std::string( "XMLTag::LastTag( void )::" ) + e.what() , e.code() ) );
00355 }
00356 catch( ... )
00357 {
00358 throw( nitro::exception( std::string( "XMLTag::LastTag( void )::An error occured" ) , 1 ) );
00359 }
00360 }
00361
00362 void XMLTag::MoveTag( std::size_t TagCursor , XMLTag &DestTag )
00363 {
00364 try
00365 {
00366 DestTag.Tags.push_back( Tags[ TagCursor ] );
00367 Tags.erase( Tags.begin() + TagCursor );
00368 }
00369 catch( nitro::exception e )
00370 {
00371 throw( nitro::exception( std::string( "XMLTag::MoveTag( std::size_t TagCursor , XMLTag &DestTag )::" ) + e.what() , e.code() ) );
00372 }
00373 catch( ... )
00374 {
00375 throw( nitro::exception( std::string( "XMLTag::MoveTag( std::size_t TagCursor , XMLTag &DestTag )::An error occured" ) , 1 ) );
00376 }
00377 }
00378
00379 XMLTag & XMLTag::operator[] ( const int TagCursor ) const
00380 {
00381 try
00382 {
00383 return( ( * this )[ ( std::size_t )TagCursor ] );
00384 }
00385 catch( nitro::exception e )
00386 {
00387 throw( nitro::exception( std::string( "XMLTag::operator[] ( std::size_t TagCursor )::" ) + e.what() , e.code() ) );
00388 }
00389 catch( ... )
00390 {
00391 throw( nitro::exception( std::string( "XMLTag::operator[] ( std::size_t TagCursor )::An error occured" ) , 1 ) );
00392 }
00393 }
00394
00395 XMLTag & XMLTag::operator[] ( const std::size_t TagCursor ) const
00396 {
00397 try
00398 {
00399 if( Tags.size() <= TagCursor )
00400 {
00401 std::string StrTagCursor;
00402 nitro::Converters::itoa( ( int )TagCursor , StrTagCursor );
00403 throw( nitro::exception( std::string ( "Tag with cursor " ) + StrTagCursor + " was not found" , 1 ) );
00404 }
00405
00406 return( * Tags[ TagCursor ] );
00407 }
00408 catch( nitro::exception e )
00409 {
00410 throw( nitro::exception( std::string( "XMLTag::operator[] ( std::size_t TagCursor )::" ) + e.what() , e.code() ) );
00411 }
00412 catch( ... )
00413 {
00414 throw( nitro::exception( std::string( "XMLTag::operator[] ( std::size_t TagCursor )::An error occured" ) , 1 ) );
00415 }
00416 }
00417
00418 XMLTag & XMLTag::GetTag( std::size_t TagCursor )
00419 {
00420 try
00421 {
00422 return( ( * this )[ TagCursor ] );
00423 }
00424 catch( nitro::exception e )
00425 {
00426 throw( nitro::exception( std::string( "XMLTag::GetTag( std::size_t TagCursor )::" ) + e.what() , e.code() ) );
00427 }
00428 catch( ... )
00429 {
00430 throw( nitro::exception( std::string( "XMLTag::GetTag( std::size_t TagCursor )::An error occured" ) , 1 ) );
00431 }
00432 }
00433
00464 void DispatchBuffer( const char * Buffer , std::vector< std::string > & Lexemmas , std::size_t BufferSize , std::list< nitro::BinaryData > & CDATA )
00465 {
00466 try
00467 {
00468 std::string str;
00469 bool ParamValue( false );
00470 bool HeaderMustBeParsed( false );
00471
00472 if( BufferSize > 5 && strncmp( Buffer , "<?xml" , 5 ) == 0 )
00473 {
00474 HeaderMustBeParsed = true;
00475 }
00476
00477 for( std::size_t i( 0 ) ; i < BufferSize ; i++ )
00478 {
00479
00480 if( BufferSize >= i + 2 && strncmp( Buffer + i , "?>" , 2 ) == 0 && HeaderMustBeParsed )
00481 {
00482
00483 for( std::size_t j( 0 ) ; j < Lexemmas.size() ; j++ )
00484 {
00485 if( Lexemmas[ j ] == "encoding" )
00486 {
00487 setlocale( LC_CTYPE , ".1251" );
00488 }
00489 }
00490 HeaderMustBeParsed = false;
00491 }
00492
00493
00494 if( strncmp( Buffer + i , "<![CDATA[" , 9 ) == 0 )
00495 {
00496 const char * EndCDATA( strstr( Buffer + i + 9 , "]]>" ) );
00497 if( EndCDATA == NULL )
00498 {
00499 throw( nitro::exception( "Illegal XML Structure" , 1 ) );
00500 }
00501
00502 Lexemmas.push_back( std::string( "<![CDATA[" ) );
00503 CDATA.push_back( BinaryData( Buffer + i + 9 , EndCDATA - Buffer - i - 9 ) );
00504 i += EndCDATA - Buffer - 1 + 3;
00505
00506 continue;
00507 }
00508
00509
00510 if( isalnum( ( unsigned char )Buffer[ i ] ) || Buffer[ i ] == ':' || Buffer[ i ] == '_' )
00511 {
00512 str.push_back( Buffer[ i ] );
00513 }
00514 else
00515 {
00516 if( Buffer[ i ] == '"' && !ParamValue )
00517 {
00518 ParamValue = true;
00519 Lexemmas.push_back( "\"" );
00520 continue;
00521 }
00522 if( str.size() && !ParamValue )
00523 {
00524 Lexemmas.push_back( str );
00525 str = "";
00526 }
00527 if( isprint( Buffer[ i ] ) )
00528 {
00529 if( ParamValue )
00530 {
00531 if( Buffer[ i ] == '"' )
00532 {
00533 Lexemmas.push_back( str );
00534 ParamValue = false;
00535 str = "\"";
00536 Lexemmas.push_back( str );
00537 str = "";
00538 }
00539 else
00540 {
00541 str.push_back( Buffer[ i ] );
00542 }
00543 }
00544 else
00545 {
00546 if( str.size() && Buffer[ i ] != ' ' )
00547 {
00548 Lexemmas.push_back( str );
00549 }
00550 if( Buffer[ i ] != ' ' && Buffer[ i ] != '\t' )
00551 {
00552 str = Buffer[ i ];
00553 Lexemmas.push_back( str );
00554 }
00555 str = "";
00556 }
00557 }
00558 }
00559 }
00560
00561 if( ParamValue )
00562 {
00563 throw( nitro::exception( "Illegal XML Structure" , 1 ) );
00564 }
00565 }
00566 catch( nitro::exception e )
00567 {
00568 throw( nitro::exception( std::string( "DispatchBuffer( const char * Buffer , std::vector< std::string > & Lexemmas , std::size_t BufferSize )::" ) + e.what() , e.code() ) );
00569 }
00570 catch( ... )
00571 {
00572 throw( nitro::exception( std::string( "DispatchBuffer( const char * Buffer , std::vector< std::string > & Lexemmas , std::size_t BufferSize )::An error occured" ) , 1 ) );
00573 }
00574 }
00575
00576 void XMLFile::LoadXMLFromANSIString( const char * str )
00577 {
00578 try
00579 {
00580 OpenFilePath = "";
00581
00582 std::vector< std::string > Lexemmas;
00583 std::list< nitro::BinaryData > CDATA;
00584
00585 DispatchBuffer( str , Lexemmas , strlen( str ) , CDATA );
00586
00587 std::size_t i( 0 );
00588 std::list< nitro::BinaryData >::iterator j( CDATA.begin() );
00589
00590 ParseHeader( Lexemmas , i );
00591
00592 XMLTag::LoadXML( Lexemmas , i , CDATA , j );
00593 }
00594 catch( nitro::exception e )
00595 {
00596 throw( nitro::exception( std::string( "XMLFile::LoadXMLFromANSIString( const char * str )::" ) + e.what() , 1 ) );
00597 }
00598 catch( ... )
00599 {
00600 throw( nitro::exception( std::string( "XMLFile::LoadXMLFromANSIString( const char * str )::An error occured" ) , 1 ) );
00601 }
00602 }
00603
00604 XMLTag & XMLFile::GetRoot( void )
00605 {
00606 try
00607 {
00608 return( dynamic_cast< XMLTag & >( *this ) );
00609 }
00610 catch( nitro::exception e )
00611 {
00612 throw( nitro::exception( std::string( "XMLFile::GetRoot( void )::" ) + e.what() , e.code() ) );
00613 }
00614 catch( ... )
00615 {
00616 throw( nitro::exception( std::string( "XMLFile::GetRoot( void )::An error occured" ) , 1 ) );
00617 }
00618 }
00619
00620 void XMLFile::LoadXML( const char * FilePath )
00621 {
00622 try
00623 {
00624 OpenFilePath = FilePath;
00625
00626 std::vector< std::string > ProtoText;
00627 std::vector< std::string > Lexemmas;
00628 std::list< nitro::BinaryData > CDATA;
00629
00630 BinaryData BinaryData;
00631
00632 File::LoadBinDataFromFile( BinaryData , std::string( FilePath ) );
00633
00634 DispatchBuffer( BinaryData.GetBuffer() , Lexemmas , BinaryData.GetBufferLength() , CDATA );
00635
00636 std::size_t i( 0 );
00637 std::list< nitro::BinaryData >::iterator j( CDATA.begin() );
00638
00639 ParseHeader( Lexemmas , i );
00640
00641 XMLTag::LoadXML( Lexemmas , i , CDATA , j );
00642
00643 ProtoText.clear();
00644 Lexemmas.clear();
00645 }
00646 catch( nitro::exception e )
00647 {
00648 throw( nitro::exception( std::string( "XMLFile::LoadXML( const char * FilePath )::" ) + e.what() , e.code() ) );
00649 }
00650 catch( ... )
00651 {
00652 throw( nitro::exception( std::string( "XMLFile::LoadXML( const char * FilePath )::An error occured" ) , 1 ) );
00653 }
00654 }
00655
00656 void XMLFile::LoadXML( const std::string & FilePath )
00657 {
00658 try
00659 {
00660 LoadXML( FilePath.c_str() );
00661 }
00662 catch( nitro::exception e )
00663 {
00664 throw( nitro::exception( std::string( "XMLFile::LoadXML( const std::string & FilePath )::" ) + e.what() , e.code() ) );
00665 }
00666 catch( ... )
00667 {
00668 throw( nitro::exception( std::string( "XMLFile::LoadXML( const std::string & FilePath )::An error occured" ) , 1 ) );
00669 }
00670 }
00671
00672 void XMLTag::SaveXML( nitro::FileAbstraction & File , char * TabSpace ) const
00673 {
00674 try
00675 {
00676 std::string str;
00677 char new_TabSpace[ 2048 ];
00678 str = TabSpace;
00679 str += "<";
00680 str += Name;
00681
00682 for( std::size_t i( 0 ) ; i < Attributes.size() ; i++ )
00683 {
00684 str += " ";
00685 str += Attributes[ i ];
00686 str += "=";
00687 str += "\"";
00688 str += Values[ i ];
00689 str += "\"";
00690 }
00691
00692 if( !Tags.size() )
00693 {
00694 str += " /";
00695 str += ">\n";
00696
00697 File.Write( str.c_str() , str.length() );
00698 }
00699 else
00700 {
00701 str += ">\n";
00702 File.Write( str.c_str() , str.length() );
00703
00704 strcpy( new_TabSpace , TabSpace );
00705 strcat( new_TabSpace , "\t" );
00706
00707 for( std::size_t i( 0 ) ; i < Tags.size() ; i++ )
00708 {
00709 Tags[ i ]->SaveXML( File , new_TabSpace );
00710 }
00711
00712 str = TabSpace;
00713 str += "<";
00714 str += "/";
00715 str += Name;
00716 str += ">\n";
00717
00718 File.Write( str.c_str() , str.length() );
00719 }
00720 }
00721 catch( nitro::exception e )
00722 {
00723 throw( nitro::exception( std::string( "XMLTag::SaveXML( nitro::FileAbstraction & File , char * TabSpace )::" ) + e.what() , e.code() ) );
00724 }
00725 catch( ... )
00726 {
00727 throw( nitro::exception( std::string( "XMLTag::SaveXML( nitro::FileAbstraction & File , char * TabSpace )::An error occured" ) , 1 ) );
00728 }
00729 }
00730
00731 void XMLTag::SetName( const std::string & NewName )
00732 {
00733 try
00734 {
00735 Name = NewName.c_str();
00736 }
00737 catch( nitro::exception e )
00738 {
00739 throw( nitro::exception( std::string( "XMLTag::SetName( const std::string & Name )::" ) + e.what() , e.code() ) );
00740 }
00741 catch( ... )
00742 {
00743 throw( nitro::exception( std::string( "XMLTag::SetName( const std::string & Name )::An error occured" ) , 1 ) );
00744 }
00745 }
00746
00747 void XMLTag::SetAttribute( const char * AttributeName , const char * AttributeValue )
00748 {
00749 try
00750 {
00751 for( std::size_t i( 0 ) ; i < Attributes.size() ; i++ )
00752 {
00753 if( Attributes[ i ] == AttributeName )
00754 {
00755 Values[ i ] = AttributeValue;
00756 return;
00757 }
00758 }
00759 }
00760 catch( nitro::exception e )
00761 {
00762 throw( nitro::exception( std::string( "XMLTag::SetAttribute( const char * AttributeName , const char * AttributeValue )::" ) + e.what() , e.code() ) );
00763 }
00764 catch( ... )
00765 {
00766 throw( nitro::exception( std::string( "XMLTag::SetAttribute( const char * AttributeName , const char * AttributeValue )::An error occured" ) , 1 ) );
00767 }
00768 }
00769
00770 void XMLFile::SaveXML( const char * FilePath )
00771 {
00772 try
00773 {
00774 nitro::FileAbstraction File;
00775
00776 if( FilePath )
00777 {
00778 OpenFilePath = FilePath;
00779 File.Open( FilePath , nitro::FA_FILE_WRITE | nitro::FA_FILE_BINARY | nitro::FA_FILE_TRUNCATE );
00780 }
00781 else
00782 {
00783 File.Open( OpenFilePath.c_str() , nitro::FA_FILE_WRITE | nitro::FA_FILE_BINARY | nitro::FA_FILE_TRUNCATE );
00784 }
00785
00786 if( Version != "" || Encoding != "" )
00787 {
00788 std::string str;
00789
00790 str = "<?xml ";
00791 File.Write( str.c_str() , str.length() );
00792
00793 if( Version != "" )
00794 {
00795 str = "version=\"";
00796 str += Version;
00797 str += "\" ";
00798 File.Write( str.c_str() , str.length() );
00799 }
00800 if( Encoding != "" )
00801 {
00802 str = "encoding=\"";
00803 str += Encoding;
00804 str += "\" ";
00805 File.Write( str.c_str() , str.length() );
00806 }
00807
00808 str = "?>\n";
00809 File.Write( str.c_str() , str.length() );
00810 }
00811
00812 XMLTag::SaveXML( File , "" );
00813 }
00814 catch( nitro::exception e )
00815 {
00816 throw( nitro::exception( std::string( "XMLFile::SaveXML( const char * FilePath /* = NULL */ )::" ) + e.what() , e.code() ) );
00817 }
00818 catch( ... )
00819 {
00820 throw( nitro::exception( std::string( "XMLFile::SaveXML( const char * FilePath /* = NULL */ )::An error occured" ) , 1 ) );
00821 }
00822 }
00823
00824 XMLFile::~XMLFile()
00825 {
00826 try
00827 {
00828 this->Release();
00829 }
00830 catch( ... )
00831 {
00832 }
00833 }
00834
00835 int XMLTag::GetAttribute_int( const char * AttributeName ) const
00836 {
00837 try
00838 {
00839 for( std::size_t i( 0 ) ; i < Attributes.size() ; i++ )
00840 {
00841 if( Attributes[ i ] == AttributeName )
00842 {
00843 return( atoi( Values[ i ].c_str() ) );
00844 }
00845 }
00846
00847 throw( nitro::exception( ( std::string( "Attribute \"" ) + AttributeName + "\" was not found" ).c_str() , 1 ) );
00848 }
00849 catch( nitro::exception e )
00850 {
00851 throw( nitro::exception( std::string( "XMLTag::GetAttribute_int( const char * AttributeName ) const::" ) + e.what() , e.code() ) );
00852 }
00853 catch( ... )
00854 {
00855 throw( nitro::exception( std::string( "XMLTag::GetAttribute_int( const char * AttributeName ) const::An error occured" ) , 1 ) );
00856 }
00857 }
00858
00859 float XMLTag::GetAttribute_float( const char * AttributeName ) const
00860 {
00861 try
00862 {
00863 for( std::size_t i( 0 ) ; i < Attributes.size() ; i++ )
00864 {
00865 if( Attributes[ i ] == AttributeName )
00866 {
00867 return( ( float )atof( Values[ i ].c_str() ) );
00868 }
00869 }
00870
00871 throw( nitro::exception( ( std::string( "Attribute \"" ) + AttributeName + "\" was not found" ).c_str() , 1 ) );
00872 }
00873 catch( nitro::exception e )
00874 {
00875 throw( nitro::exception( std::string( "XMLTag::GetAttribute_float( const char * AttributeName ) const::" ) + e.what() , e.code() ) );
00876 }
00877 catch( ... )
00878 {
00879 throw( nitro::exception( std::string( "XMLTag::GetAttribute_float( const char * AttributeName ) const::An error occured" ) , 1 ) );
00880 }
00881 }
00882
00883 bool XMLTag::GetAttribute_bool( const char * AttributeName ) const
00884 {
00885 try
00886 {
00887 for( std::size_t i( 0 ) ; i < Attributes.size() ; i++ )
00888 {
00889 if( Attributes[ i ] == AttributeName )
00890 {
00891 return( std::string( "true" ) == Values[ i ] );
00892 }
00893 }
00894
00895 throw( nitro::exception( ( std::string( "Attribute \"" ) + AttributeName + "\" was not found" ).c_str() , 1 ) );
00896 }
00897 catch( nitro::exception e )
00898 {
00899 throw( nitro::exception( std::string( "XMLTag::GetAttribute_bool( const char * AttributeName ) const::" ) + e.what() , e.code() ) );
00900 }
00901 catch( ... )
00902 {
00903 throw( nitro::exception( std::string( "XMLTag::GetAttribute_bool( const char * AttributeName ) const::An error occured" ) , 1 ) );
00904 }
00905 }
00906
00907 const char * XMLTag::GetAttribute_string( const char * AttributeName ) const
00908 {
00909 try
00910 {
00911 for( std::size_t i( 0 ) ; i < Attributes.size() ; i++ )
00912 {
00913 if( Attributes[ i ] == AttributeName )
00914 {
00915 return( Values[ i ].c_str() );
00916 }
00917 }
00918
00919 throw( nitro::exception( ( std::string( "Attribute \"" ) + AttributeName + "\" was not found" ).c_str() , 1 ) );
00920 }
00921 catch( nitro::exception e )
00922 {
00923 throw( nitro::exception( std::string( "XMLTag::GetAttribute_string( const char * AttributeName ) const::" ) + e.what() , e.code() ) );
00924 }
00925 catch( ... )
00926 {
00927 throw( nitro::exception( std::string( "XMLTag::GetAttribute_string( const char * AttributeName ) const::An error occured" ) , 1 ) );
00928 }
00929 }
00930
00931 int XMLTag::ProcessAttributes( std::vector< std::string > & Lexemmas , std::size_t & i )
00932 {
00933 try
00934 {
00935 for( ; i < Lexemmas.size() ; )
00936 {
00937
00938 if( i + 4 < Lexemmas.size() )
00939 {
00940 if( IsTagName( Lexemmas[ i ] ) && Lexemmas[ i + 1 ] == "="
00941 && Lexemmas[ i + 2 ] == "\"" && Lexemmas[ i + 4 ] == "\"" )
00942 {
00943 Attributes.push_back( Lexemmas[ i ] );
00944 Values.push_back( Lexemmas[ i + 3 ] );
00945
00946 i += 5;
00947 goto end;
00948 }
00949 }
00950
00951 if( i + 1 < Lexemmas.size() )
00952 {
00953 if( Lexemmas[ i ] == "/" && Lexemmas[ i + 1 ] == ">" )
00954 {
00955 i += 2;
00956 return( 0 );
00957 }
00958 }
00959
00960 if( Lexemmas[ i ] == ">" )
00961 {
00962 i += 1;
00963 return( 1 );
00964 }
00965
00966 throw( nitro::exception( "Bad XML structure" , 1 ) );
00967 end:;
00968 }
00969 return( 2 );
00970 }
00971 catch( nitro::exception e )
00972 {
00973 throw( nitro::exception( std::string( "XMLTag::ProcessAttributes( std::vector< std::string > & Lexemmas , std::size_t & i )::" ) + e.what() , e.code() ) );
00974 }
00975 catch( ... )
00976 {
00977 throw( nitro::exception( std::string( "XMLTag::ProcessAttributes( std::vector< std::string > & Lexemmas , std::size_t & i )::An error occured" ) , 1 ) );
00978 }
00979 }
00980
00981 bool XMLTag::IsClosingTag( std::vector< std::string > & Lexemmas , std::size_t & i )
00982 {
00983 try
00984 {
00985 if( i + 3 < Lexemmas.size() )
00986 {
00987 if( Lexemmas[ i ] == "<" && Lexemmas[ i + 1 ] == "/" && Lexemmas[ i + 2 ] == Name && Lexemmas[ i + 3 ] == ">" )
00988 {
00989 i += 4;
00990 return( true );
00991 }
00992 else
00993 {
00994 if( Lexemmas[ i ] == "<" && IsTagName( Lexemmas[ i + 1 ] ) )
00995 {
00996 return( false );
00997 }
00998 else
00999 {
01000 throw( nitro::exception( std::string( "Bad XML structure #" ) + Lexemmas[ i ] + "#" + Lexemmas[ i + 1 ] , 1 ) );
01001 }
01002 }
01003 }
01004 return( false );
01005 }
01006 catch( nitro::exception e )
01007 {
01008 throw( nitro::exception( std::string( "XMLTag::IsClosingTag( std::vector< std::string > & Lexemmas , std::size_t & i )::" ) + e.what() , e.code() ) );
01009 }
01010 catch( ... )
01011 {
01012 throw( nitro::exception( std::string( "XMLTag::IsClosingTag( std::vector< std::string > & Lexemmas , std::size_t & i )::An error occured" ) , 1 ) );
01013 }
01014 }
01015
01016 void XMLFile::ParseHeader( std::vector< std::string > & Lexemmas , std::size_t & i )
01017 {
01018 try
01019 {
01020 if( Lexemmas.size() < 6 )
01021 {
01022 throw( nitro::exception( "Bad XML structure" , 1 ) );
01023 }
01024 if( Lexemmas[ 0 ] != "<" || Lexemmas[ 1 ] != "?" || Lexemmas[ 2 ] != "xml" )
01025 {
01026 return;
01027 }
01028
01029 i = 3;
01030
01031 for( std::size_t k( 3 ) ; k < Lexemmas.size() ; k += 5 , i += 5 )
01032 {
01033 if( IsTagName( Lexemmas[ k ] ) && Lexemmas[ k + 1 ] == "=" && Lexemmas[ k + 2 ] == "\"" )
01034 {
01035 if( Lexemmas[ k ] == "version" )
01036 {
01037 Version = Lexemmas[ k + 3 ];
01038 goto next_iter;
01039 }
01040 if( Lexemmas[ k ] == "encoding" )
01041 {
01042 Encoding = Lexemmas[ k + 3 ];
01043 goto next_iter;
01044 }
01045 }
01046 else
01047 {
01048 if( Lexemmas[ k ] == "?" && Lexemmas[ k + 1 ] == ">" )
01049 {
01050 i += 2;
01051 return;
01052 }
01053 else
01054 {
01055 throw( nitro::exception( "Bad XML structure" , 1 ) );
01056 }
01057 }
01058 next_iter:;
01059 }
01060 }
01061 catch( nitro::exception e )
01062 {
01063 throw( nitro::exception( std::string( "XMLFile::ParseHeader( std::vector< std::string > & Lexemmas , std::size_t & i )::" ) + e.what() , e.code() ) );
01064 }
01065 catch( ... )
01066 {
01067 throw( nitro::exception( std::string( "XMLFile::ParseHeader( std::vector< std::string > & Lexemmas , std::size_t & i )::An error occured" ) , 1 ) );
01068 }
01069 }
01070
01071 void XMLTag::SaveXMLToANSIString( std::string & Str , char * TabSpace )
01072 {
01073 try
01074 {
01075 char new_TabSpace[ 2048 ];
01076 Str += "\r\n";
01077 Str += TabSpace;
01078 Str += "<";
01079 Str += Name;
01080
01081 if( Attributes.size() )
01082 {
01083 Str += " ";
01084 for( std::size_t i( 0 ) ; i < Attributes.size() ; i++ )
01085 {
01086 Str += Attributes[ i ];
01087 Str += " ";
01088 Str += "=";
01089 Str += " ";
01090 Str += "\"";
01091 Str += Values[ i ];
01092 Str += "\"";
01093 }
01094 }
01095 else
01096 {
01097 Str += "/";
01098 }
01099
01100 Str += ">";
01101
01102 strcpy( new_TabSpace , TabSpace );
01103 strcat( new_TabSpace , "\t" );
01104
01105 for( std::size_t i( 0 ) ; i < Tags.size() ; i++ )
01106 {
01107 Tags[ i ]->SaveXMLToANSIString( Str , new_TabSpace );
01108 }
01109
01110 Str += "\r\n";
01111 Str += TabSpace;
01112 Str += "<";
01113 Str += "/";
01114 Str += Name;
01115 Str += ">";
01116 }
01117 catch( nitro::exception e )
01118 {
01119 throw( nitro::exception( std::string( "XMLTag::SaveXMLToANSIString( std::string & Str , char * TabSpace )::" ) + e.what() , e.code() ) );
01120 }
01121 catch( ... )
01122 {
01123 throw( nitro::exception( std::string( "XMLTag::SaveXMLToANSIString( std::string & Str , char * TabSpace )::An error occured" ) , 1 ) );
01124 }
01125 }
01126
01127 void XMLTag::LoadXML( std::vector< std::string > & Lexemmas , std::size_t & i , std::list< nitro::BinaryData > & CDATA , std::list< nitro::BinaryData >::iterator & j )
01128 {
01129 try
01130 {
01131 if( IsClosingTag( Lexemmas , i ) )
01132 {
01133 return;
01134 }
01135 if( Lexemmas[ i ] == "<" )
01136 {
01137 if( i + 1 < Lexemmas.size() )
01138 {
01139 if( IsTagName( Lexemmas[ i + 1 ] ) )
01140 {
01141 Name = Lexemmas[ i + 1 ];
01142 i += 2;
01143 if( !ProcessAttributes( Lexemmas , i ) )
01144 {
01145 return;
01146 }
01147 }
01148 else
01149 {
01150 throw( nitro::exception( "Bad XML structure" , 1 ) );
01151 }
01152 }
01153 }
01154 else
01155 {
01156 throw( nitro::exception( "Bad XML structure" , 1 ) );
01157 }
01158
01159 if( IsClosingTag( Lexemmas , i ) )
01160 {
01161 return;
01162 }
01163
01164 for( ; i < Lexemmas.size() ; )
01165 {
01166 Tags.push_back( new XMLTag() );
01167
01168 if( Lexemmas[ i ] == "<![CDATA[" )
01169 {
01170 Tags.back()->InnerData.AppendData( j->GetBuffer() , j->GetBufferLength() );
01171 Tags.back()->Name = "cdata";
01172 j++;
01173 i++;
01174
01175 continue;
01176 }
01177
01178 Tags.back()->LoadXML( Lexemmas , i , CDATA , j );
01179 if( IsClosingTag( Lexemmas , i ) )
01180 {
01181 return;
01182 }
01183 }
01184 }
01185 catch( nitro::exception e )
01186 {
01187 throw( nitro::exception( std::string( "XMLTag::LoadXML( std::vector< std::string > & Lexemmas , std::size_t & i , std::list< nitro::BinaryData > & CDATA , std::list< nitro::BinaryData >::iterator & j )::" ) + e.what() , e.code() ) );
01188 }
01189 catch( ... )
01190 {
01191 throw( nitro::exception( std::string( "XMLTag::LoadXML( std::vector< std::string > & Lexemmas , std::size_t & i , std::list< nitro::BinaryData > & CDATA , std::list< nitro::BinaryData >::iterator & j )::An error occured" ) , 1 ) );
01192 }
01193 }
01194 }
01195
01196 #endif