tinyxml.cpp 18 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007
  1. /*
  2. Copyright (c) 2000 Lee Thomason (www.grinninglizard.com)
  3. This software is provided 'as-is', without any express or implied
  4. warranty. In no event will the authors be held liable for any
  5. damages arising from the use of this software.
  6. Permission is granted to anyone to use this software for any
  7. purpose, including commercial applications, and to alter it and
  8. redistribute it freely, subject to the following restrictions:
  9. 1. The origin of this software must not be misrepresented; you must
  10. not claim that you wrote the original software. If you use this
  11. software in a product, an acknowledgment in the product documentation
  12. would be appreciated but is not required.
  13. 2. Altered source versions must be plainly marked as such, and
  14. must not be misrepresented as being the original software.
  15. 3. This notice may not be removed or altered from any source
  16. distribution.
  17. */
  18. #include <iostream>
  19. #include <sstream>
  20. #include <fstream>
  21. #include "tinyxml.h"
  22. using namespace std;
  23. bool TiXmlBase::condenseWhiteSpace = true;
  24. void TiXmlBase::PutString( const std::string& str, std::ostream* stream )
  25. {
  26. // Scan for the all important '&'
  27. unsigned int i=0, j=0;
  28. while ( i < str.length() )
  29. {
  30. unsigned next = str.find( '&', i );
  31. if ( next == string::npos )
  32. {
  33. stream->write( &str.at( i ), str.length() - i );
  34. return;
  35. }
  36. // We found an entity.
  37. if ( next - i > 0 )
  38. stream->write( &str.at( i ), next - i );
  39. i = next;
  40. // Check for the special "&#x" entitity
  41. if ( i < str.length() - 2
  42. && str[i] == '&'
  43. && str[i+1] == '#'
  44. && str[i+2] == 'x' )
  45. {
  46. stream->put( str[i] );
  47. }
  48. else
  49. {
  50. for ( j=0; j<NUM_ENTITY; ++j )
  51. {
  52. if ( str[i] == entity[j].chr )
  53. {
  54. stream->write( entity[j].str, entity[j].strLength );
  55. break;
  56. }
  57. }
  58. if ( j == NUM_ENTITY )
  59. {
  60. stream->put( str[i] );
  61. }
  62. }
  63. ++i;
  64. }
  65. }
  66. TiXmlNode::TiXmlNode( NodeType _type )
  67. {
  68. parent = 0;
  69. type = _type;
  70. firstChild = 0;
  71. lastChild = 0;
  72. prev = 0;
  73. next = 0;
  74. }
  75. TiXmlNode::~TiXmlNode()
  76. {
  77. TiXmlNode* node = firstChild;
  78. TiXmlNode* temp = 0;
  79. while ( node )
  80. {
  81. temp = node;
  82. node = node->next;
  83. delete temp;
  84. }
  85. }
  86. void TiXmlNode::Clear()
  87. {
  88. TiXmlNode* node = firstChild;
  89. TiXmlNode* temp = 0;
  90. while ( node )
  91. {
  92. temp = node;
  93. node = node->next;
  94. delete temp;
  95. }
  96. firstChild = 0;
  97. lastChild = 0;
  98. }
  99. TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
  100. {
  101. node->parent = this;
  102. node->prev = lastChild;
  103. node->next = 0;
  104. if ( lastChild )
  105. lastChild->next = node;
  106. else
  107. firstChild = node; // it was an empty list.
  108. lastChild = node;
  109. return node;
  110. }
  111. TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis )
  112. {
  113. TiXmlNode* node = addThis.Clone();
  114. if ( !node )
  115. return 0;
  116. return LinkEndChild( node );
  117. }
  118. TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis )
  119. {
  120. if ( beforeThis->parent != this )
  121. return 0;
  122. TiXmlNode* node = addThis.Clone();
  123. if ( !node )
  124. return 0;
  125. node->parent = this;
  126. node->next = beforeThis;
  127. node->prev = beforeThis->prev;
  128. beforeThis->prev->next = node;
  129. beforeThis->prev = node;
  130. return node;
  131. }
  132. TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis )
  133. {
  134. if ( afterThis->parent != this )
  135. return 0;
  136. TiXmlNode* node = addThis.Clone();
  137. if ( !node )
  138. return 0;
  139. node->parent = this;
  140. node->prev = afterThis;
  141. node->next = afterThis->next;
  142. afterThis->next->prev = node;
  143. afterThis->next = node;
  144. return node;
  145. }
  146. TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis )
  147. {
  148. if ( replaceThis->parent != this )
  149. return 0;
  150. TiXmlNode* node = withThis.Clone();
  151. if ( !node )
  152. return 0;
  153. node->next = replaceThis->next;
  154. node->prev = replaceThis->prev;
  155. if ( replaceThis->next )
  156. replaceThis->next->prev = node;
  157. else
  158. lastChild = node;
  159. if ( replaceThis->prev )
  160. replaceThis->prev->next = node;
  161. else
  162. firstChild = node;
  163. delete replaceThis;
  164. node->parent = this;
  165. return node;
  166. }
  167. bool TiXmlNode::RemoveChild( TiXmlNode* removeThis )
  168. {
  169. if ( removeThis->parent != this )
  170. {
  171. assert( 0 );
  172. return false;
  173. }
  174. if ( removeThis->next )
  175. removeThis->next->prev = removeThis->prev;
  176. else
  177. lastChild = removeThis->prev;
  178. if ( removeThis->prev )
  179. removeThis->prev->next = removeThis->next;
  180. else
  181. firstChild = removeThis->next;
  182. delete removeThis;
  183. return true;
  184. }
  185. TiXmlNode* TiXmlNode::FirstChild( const std::string& value ) const
  186. {
  187. TiXmlNode* node;
  188. for ( node = firstChild; node; node = node->next )
  189. {
  190. if ( node->Value() == value )
  191. return node;
  192. }
  193. return 0;
  194. }
  195. TiXmlNode* TiXmlNode::LastChild( const std::string& value ) const
  196. {
  197. TiXmlNode* node;
  198. for ( node = lastChild; node; node = node->prev )
  199. {
  200. if ( node->Value() == value )
  201. return node;
  202. }
  203. return 0;
  204. }
  205. TiXmlNode* TiXmlNode::IterateChildren( TiXmlNode* previous ) const
  206. {
  207. if ( !previous )
  208. {
  209. return FirstChild();
  210. }
  211. else
  212. {
  213. assert( previous->parent == this );
  214. return previous->NextSibling();
  215. }
  216. }
  217. TiXmlNode* TiXmlNode::IterateChildren( const std::string& val, TiXmlNode* previous ) const
  218. {
  219. if ( !previous )
  220. {
  221. return FirstChild( val );
  222. }
  223. else
  224. {
  225. assert( previous->parent == this );
  226. return previous->NextSibling( val );
  227. }
  228. }
  229. TiXmlNode* TiXmlNode::NextSibling( const std::string& value ) const
  230. {
  231. TiXmlNode* node;
  232. for ( node = next; node; node = node->next )
  233. {
  234. if ( node->Value() == value )
  235. return node;
  236. }
  237. return 0;
  238. }
  239. TiXmlNode* TiXmlNode::PreviousSibling( const std::string& value ) const
  240. {
  241. TiXmlNode* node;
  242. for ( node = prev; node; node = node->prev )
  243. {
  244. if ( node->Value() == value )
  245. return node;
  246. }
  247. return 0;
  248. }
  249. void TiXmlElement::RemoveAttribute( const std::string& name )
  250. {
  251. TiXmlAttribute* node = attributeSet.Find( name );
  252. if ( node )
  253. {
  254. attributeSet.Remove( node );
  255. delete node;
  256. }
  257. }
  258. TiXmlElement* TiXmlNode::FirstChildElement() const
  259. {
  260. TiXmlNode* node;
  261. for ( node = FirstChild();
  262. node;
  263. node = node->NextSibling() )
  264. {
  265. if ( node->ToElement() )
  266. return node->ToElement();
  267. }
  268. return 0;
  269. }
  270. TiXmlElement* TiXmlNode::FirstChildElement( const std::string& value ) const
  271. {
  272. TiXmlNode* node;
  273. for ( node = FirstChild( value );
  274. node;
  275. node = node->NextSibling( value ) )
  276. {
  277. if ( node->ToElement() )
  278. return node->ToElement();
  279. }
  280. return 0;
  281. }
  282. TiXmlElement* TiXmlNode::NextSiblingElement() const
  283. {
  284. TiXmlNode* node;
  285. for ( node = NextSibling();
  286. node;
  287. node = node->NextSibling() )
  288. {
  289. if ( node->ToElement() )
  290. return node->ToElement();
  291. }
  292. return 0;
  293. }
  294. TiXmlElement* TiXmlNode::NextSiblingElement( const std::string& value ) const
  295. {
  296. TiXmlNode* node;
  297. for ( node = NextSibling( value );
  298. node;
  299. node = node->NextSibling( value ) )
  300. {
  301. if ( node->ToElement() )
  302. return node->ToElement();
  303. }
  304. return 0;
  305. }
  306. TiXmlDocument* TiXmlNode::GetDocument() const
  307. {
  308. const TiXmlNode* node;
  309. for( node = this; node; node = node->parent )
  310. {
  311. if ( node->ToDocument() )
  312. return node->ToDocument();
  313. }
  314. return 0;
  315. }
  316. // TiXmlElement::TiXmlElement()
  317. // : TiXmlNode( TiXmlNode::ELEMENT )
  318. // {
  319. // }
  320. TiXmlElement::TiXmlElement( const std::string& _value )
  321. : TiXmlNode( TiXmlNode::ELEMENT )
  322. {
  323. firstChild = lastChild = 0;
  324. value = _value;
  325. }
  326. TiXmlElement::~TiXmlElement()
  327. {
  328. while( attributeSet.First() )
  329. {
  330. TiXmlAttribute* node = attributeSet.First();
  331. attributeSet.Remove( node );
  332. delete node;
  333. }
  334. }
  335. const std::string* TiXmlElement::Attribute( const std::string& name ) const
  336. {
  337. TiXmlAttribute* node = attributeSet.Find( name );
  338. if ( node )
  339. return &(node->Value() );
  340. return 0;
  341. }
  342. const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const
  343. {
  344. const std::string* s = Attribute( name );
  345. if ( s )
  346. *i = atoi( s->c_str() );
  347. else
  348. *i = 0;
  349. return s;
  350. }
  351. void TiXmlElement::SetAttribute( const std::string& name, int val )
  352. {
  353. char buf[64];
  354. sprintf( buf, "%d", val );
  355. std::string v = buf;
  356. SetAttribute( name, v );
  357. }
  358. void TiXmlElement::SetAttribute( const std::string& name, const std::string& value )
  359. {
  360. TiXmlAttribute* node = attributeSet.Find( name );
  361. if ( node )
  362. {
  363. node->SetValue( value );
  364. return;
  365. }
  366. TiXmlAttribute* attrib = new TiXmlAttribute( name, value );
  367. if ( attrib )
  368. {
  369. attributeSet.Add( attrib );
  370. }
  371. else
  372. {
  373. TiXmlDocument* document = GetDocument();
  374. if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY );
  375. }
  376. }
  377. void TiXmlElement::Print( FILE* cfile, int depth ) const
  378. {
  379. int i;
  380. for ( i=0; i<depth; i++ )
  381. {
  382. fprintf( cfile, " " );
  383. }
  384. fprintf( cfile, "<%s", value.c_str() );
  385. TiXmlAttribute* attrib;
  386. for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
  387. {
  388. fprintf( cfile, " " );
  389. attrib->Print( cfile, depth );
  390. }
  391. // There are 3 different formatting approaches:
  392. // 1) An element without children is printed as a <foo /> node
  393. // 2) An element with only a text child is printed as <foo> text </foo>
  394. // 3) An element with children is printed on multiple lines.
  395. TiXmlNode* node;
  396. if ( !firstChild )
  397. {
  398. fprintf( cfile, " />" );
  399. }
  400. else if ( firstChild == lastChild && firstChild->ToText() )
  401. {
  402. fprintf( cfile, ">" );
  403. firstChild->Print( cfile, depth + 1 );
  404. fprintf( cfile, "</%s>", value.c_str() );
  405. }
  406. else
  407. {
  408. fprintf( cfile, ">" );
  409. for ( node = firstChild; node; node=node->NextSibling() )
  410. {
  411. if ( !node->ToText() )
  412. {
  413. fprintf( cfile, "\n" );
  414. }
  415. node->Print( cfile, depth+1 );
  416. }
  417. fprintf( cfile, "\n" );
  418. for( i=0; i<depth; ++i )
  419. fprintf( cfile, " " );
  420. fprintf( cfile, "</%s>", value.c_str() );
  421. }
  422. }
  423. void TiXmlElement::StreamOut( std::ostream* stream ) const
  424. {
  425. (*stream) << "<" << value;
  426. TiXmlAttribute* attrib;
  427. for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
  428. {
  429. (*stream) << " ";
  430. attrib->StreamOut( stream );
  431. }
  432. // If this node has children, give it a closing tag. Else
  433. // make it an empty tag.
  434. TiXmlNode* node;
  435. if ( firstChild )
  436. {
  437. (*stream) << ">";
  438. for ( node = firstChild; node; node=node->NextSibling() )
  439. {
  440. node->StreamOut( stream );
  441. }
  442. (*stream) << "</" << value << ">";
  443. }
  444. else
  445. {
  446. (*stream) << " />";
  447. }
  448. }
  449. TiXmlNode* TiXmlElement::Clone() const
  450. {
  451. TiXmlElement* clone = new TiXmlElement( Value() );
  452. if ( !clone )
  453. return 0;
  454. CopyToClone( clone );
  455. // Clone the attributes, then clone the children.
  456. TiXmlAttribute* attribute = 0;
  457. for( attribute = attributeSet.First();
  458. attribute;
  459. attribute = attribute->Next() )
  460. {
  461. clone->SetAttribute( attribute->Name(), attribute->Value() );
  462. }
  463. TiXmlNode* node = 0;
  464. for ( node = firstChild; node; node = node->NextSibling() )
  465. {
  466. clone->LinkEndChild( node->Clone() );
  467. }
  468. return clone;
  469. }
  470. TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT )
  471. {
  472. error = false;
  473. // ignoreWhiteSpace = true;
  474. }
  475. TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
  476. {
  477. // ignoreWhiteSpace = true;
  478. value = documentName;
  479. error = false;
  480. }
  481. bool TiXmlDocument::LoadFile()
  482. {
  483. return LoadFile( value );
  484. }
  485. bool TiXmlDocument::SaveFile() const
  486. {
  487. return SaveFile( value );
  488. }
  489. bool TiXmlDocument::LoadFile( const std::string& filename )
  490. {
  491. // Delete the existing data:
  492. Clear();
  493. value = filename;
  494. FILE* file = fopen( filename.c_str(), "r" );
  495. if ( file )
  496. {
  497. // Get the file size, so we can pre-allocate the string. HUGE speed impact.
  498. long length = 0;
  499. fseek( file, 0, SEEK_END );
  500. length = ftell( file );
  501. fseek( file, 0, SEEK_SET );
  502. // If we have a file, assume it is all one big XML file, and read it in.
  503. // The document parser may decide the document ends sooner than the entire file, however.
  504. std::string data;
  505. data.reserve( length );
  506. const int BUF_SIZE = 2048;
  507. char buf[BUF_SIZE];
  508. while( fgets( buf, BUF_SIZE, file ) )
  509. {
  510. data += buf;
  511. }
  512. fclose( file );
  513. Parse( data.c_str() );
  514. if ( !Error() )
  515. {
  516. return true;
  517. }
  518. }
  519. SetError( TIXML_ERROR_OPENING_FILE );
  520. return false;
  521. }
  522. bool TiXmlDocument::SaveFile( const std::string& filename ) const
  523. {
  524. // The old c stuff lives on...
  525. FILE* fp = fopen( filename.c_str(), "w" );
  526. if ( fp )
  527. {
  528. Print( fp, 0 );
  529. fclose( fp );
  530. return true;
  531. }
  532. return false;
  533. }
  534. TiXmlNode* TiXmlDocument::Clone() const
  535. {
  536. TiXmlDocument* clone = new TiXmlDocument();
  537. if ( !clone )
  538. return 0;
  539. CopyToClone( clone );
  540. clone->error = error;
  541. clone->errorDesc = errorDesc;
  542. TiXmlNode* node = 0;
  543. for ( node = firstChild; node; node = node->NextSibling() )
  544. {
  545. clone->LinkEndChild( node->Clone() );
  546. }
  547. return clone;
  548. }
  549. void TiXmlDocument::Print( FILE* cfile, int depth ) const
  550. {
  551. TiXmlNode* node;
  552. for ( node=FirstChild(); node; node=node->NextSibling() )
  553. {
  554. node->Print( cfile, depth );
  555. fprintf( cfile, "\n" );
  556. }
  557. }
  558. void TiXmlDocument::StreamOut( std::ostream* out ) const
  559. {
  560. TiXmlNode* node;
  561. for ( node=FirstChild(); node; node=node->NextSibling() )
  562. {
  563. node->StreamOut( out );
  564. // Special rule for streams: stop after the root element.
  565. // The stream in code will only read one element, so don't
  566. // write more than one.
  567. if ( node->ToElement() )
  568. break;
  569. }
  570. }
  571. TiXmlAttribute* TiXmlAttribute::Next() const
  572. {
  573. // We are using knowledge of the sentinel. The sentinel
  574. // have a value or name.
  575. if ( next->value.empty() && next->name.empty() )
  576. return 0;
  577. return next;
  578. }
  579. TiXmlAttribute* TiXmlAttribute::Previous() const
  580. {
  581. // We are using knowledge of the sentinel. The sentinel
  582. // have a value or name.
  583. if ( prev->value.empty() && prev->name.empty() )
  584. return 0;
  585. return prev;
  586. }
  587. void TiXmlAttribute::Print( FILE* cfile, int /*depth*/ ) const
  588. {
  589. ostringstream stream( ostringstream::out );
  590. stream.str().reserve( 500 );
  591. StreamOut( &stream );
  592. fprintf( cfile, "%s", stream.str().c_str() );
  593. }
  594. void TiXmlAttribute::StreamOut( std::ostream* stream ) const
  595. {
  596. if ( value.find( '\"' ) != std::string::npos )
  597. {
  598. PutString( name, stream );
  599. (*stream) << "=" << "'";
  600. PutString( value, stream );
  601. (*stream) << "'";
  602. }
  603. else
  604. {
  605. PutString( name, stream );
  606. (*stream) << "=" << "\"";
  607. PutString( value, stream );
  608. (*stream) << "\"";
  609. }
  610. }
  611. void TiXmlAttribute::SetIntValue( int value )
  612. {
  613. std::string s;
  614. std::ostringstream stream( s );
  615. stream << value;
  616. SetValue( stream.str() );
  617. }
  618. void TiXmlAttribute::SetDoubleValue( double value )
  619. {
  620. std::string s;
  621. std::ostringstream stream( s );
  622. stream << value;
  623. SetValue( stream.str() );
  624. }
  625. const int TiXmlAttribute::IntValue() const
  626. {
  627. int v;
  628. std::istringstream string( value );
  629. string >> v;
  630. return v;
  631. }
  632. const double TiXmlAttribute::DoubleValue() const
  633. {
  634. double v;
  635. std::istringstream string( value );
  636. string >> v;
  637. return v;
  638. }
  639. void TiXmlComment::Print( FILE* cfile, int depth ) const
  640. {
  641. ostringstream stream( ostringstream::out );
  642. stream.str().reserve( 1000 );
  643. for ( int i=0; i<depth; i++ )
  644. {
  645. fprintf( cfile, " " );
  646. }
  647. StreamOut( &stream );
  648. fprintf( cfile, "%s", stream.str().c_str() );
  649. }
  650. void TiXmlComment::StreamOut( std::ostream* stream ) const
  651. {
  652. (*stream) << "<!--";
  653. PutString( value, stream );
  654. (*stream) << "-->";
  655. }
  656. TiXmlNode* TiXmlComment::Clone() const
  657. {
  658. TiXmlComment* clone = new TiXmlComment();
  659. if ( !clone )
  660. return 0;
  661. CopyToClone( clone );
  662. return clone;
  663. }
  664. void TiXmlText::Print( FILE* cfile, int depth ) const
  665. {
  666. ostringstream stream( ostringstream::out );
  667. stream.str().reserve( 1000 );
  668. StreamOut( &stream );
  669. fprintf( cfile, "%s", stream.str().c_str() );
  670. }
  671. void TiXmlText::StreamOut( std::ostream* stream ) const
  672. {
  673. PutString( value, stream );
  674. }
  675. TiXmlNode* TiXmlText::Clone() const
  676. {
  677. TiXmlText* clone = 0;
  678. clone = new TiXmlText( "" );
  679. if ( !clone )
  680. return 0;
  681. CopyToClone( clone );
  682. return clone;
  683. }
  684. TiXmlDeclaration::TiXmlDeclaration( const std::string& _version,
  685. const std::string& _encoding,
  686. const std::string& _standalone )
  687. : TiXmlNode( TiXmlNode::DECLARATION )
  688. {
  689. version = _version;
  690. encoding = _encoding;
  691. standalone = _standalone;
  692. }
  693. void TiXmlDeclaration::Print( FILE* cfile, int depth ) const
  694. {
  695. ostringstream stream( ostringstream::out );
  696. stream.str().reserve( 200 );
  697. StreamOut( &stream );
  698. fprintf( cfile, "%s", stream.str().c_str() );
  699. }
  700. void TiXmlDeclaration::StreamOut( std::ostream* stream ) const
  701. {
  702. (*stream) << "<?xml ";
  703. if ( !version.empty() )
  704. {
  705. (*stream) << "version=\"";
  706. PutString( version, stream );
  707. (*stream) << "\" ";
  708. }
  709. if ( !encoding.empty() )
  710. {
  711. (*stream) << "encoding=\"";
  712. PutString( encoding, stream );
  713. (*stream ) << "\" ";
  714. }
  715. if ( !standalone.empty() )
  716. {
  717. (*stream) << "standalone=\"";
  718. PutString( standalone, stream );
  719. (*stream) << "\" ";
  720. }
  721. (*stream) << "?>";
  722. }
  723. TiXmlNode* TiXmlDeclaration::Clone() const
  724. {
  725. TiXmlDeclaration* clone = new TiXmlDeclaration();
  726. if ( !clone )
  727. return 0;
  728. CopyToClone( clone );
  729. clone->version = version;
  730. clone->encoding = encoding;
  731. clone->standalone = standalone;
  732. return clone;
  733. }
  734. void TiXmlUnknown::Print( FILE* cfile, int depth ) const
  735. {
  736. ostringstream stream( ostringstream::out );
  737. stream.str().reserve( 200 );
  738. StreamOut( &stream );
  739. for ( int i=0; i<depth; i++ )
  740. fprintf( cfile, " " );
  741. fprintf( cfile, "%s", stream.str().c_str() );
  742. }
  743. void TiXmlUnknown::StreamOut( std::ostream* stream ) const
  744. {
  745. (*stream) << "<" << value << ">"; // Don't use entities hear! It is unknown.
  746. }
  747. TiXmlNode* TiXmlUnknown::Clone() const
  748. {
  749. TiXmlUnknown* clone = new TiXmlUnknown();
  750. if ( !clone )
  751. return 0;
  752. CopyToClone( clone );
  753. return clone;
  754. }
  755. TiXmlAttributeSet::TiXmlAttributeSet()
  756. {
  757. sentinel.next = &sentinel;
  758. sentinel.prev = &sentinel;
  759. }
  760. TiXmlAttributeSet::~TiXmlAttributeSet()
  761. {
  762. assert( sentinel.next == &sentinel );
  763. assert( sentinel.prev == &sentinel );
  764. }
  765. void TiXmlAttributeSet::Add( TiXmlAttribute* addMe )
  766. {
  767. assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set.
  768. addMe->next = &sentinel;
  769. addMe->prev = sentinel.prev;
  770. sentinel.prev->next = addMe;
  771. sentinel.prev = addMe;
  772. }
  773. void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe )
  774. {
  775. TiXmlAttribute* node;
  776. for( node = sentinel.next; node != &sentinel; node = node->next )
  777. {
  778. if ( node == removeMe )
  779. {
  780. node->prev->next = node->next;
  781. node->next->prev = node->prev;
  782. node->next = 0;
  783. node->prev = 0;
  784. return;
  785. }
  786. }
  787. assert( 0 ); // we tried to remove a non-linked attribute.
  788. }
  789. TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const
  790. {
  791. TiXmlAttribute* node;
  792. for( node = sentinel.next; node != &sentinel; node = node->next )
  793. {
  794. if ( node->Name() == name )
  795. return node;
  796. }
  797. return 0;
  798. }