tinyxml.cpp
Go to the documentation of this file.
00001 /*
00002    www.sourceforge.net/projects/tinyxml
00003    Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com)
00004 
00005    This software is provided 'as-is', without any express or implied
00006    warranty. In no event will the authors be held liable for any
00007    damages arising from the use of this software.
00008 
00009    Permission is granted to anyone to use this software for any
00010    purpose, including commercial applications, and to alter it and
00011    redistribute it freely, subject to the following restrictions:
00012 
00013    1. The origin of this software must not be misrepresented; you must
00014    not claim that you wrote the original software. If you use this
00015    software in a product, an acknowledgment in the product documentation
00016    would be appreciated but is not required.
00017 
00018    2. Altered source versions must be plainly marked as such, and
00019    must not be misrepresented as being the original software.
00020 
00021    3. This notice may not be removed or altered from any source
00022    distribution.
00023    */
00024 
00025 #include <ctype.h>
00026 
00027 #ifdef TIXML_USE_STL
00028 #include <sstream>
00029 #include <iostream>
00030 #endif
00031 
00032 #include "tinyxml.h"
00033 
00034 bool TiXmlBase::condenseWhiteSpace = true;
00035 
00036 // Microsoft compiler security
00037     FILE* TiXmlFOpen(const char* filename, const char* mode) {
00038 #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
00039         FILE* fp = 0;
00040         errno_t err = fopen_s( &fp, filename, mode );
00041         if ( !err && fp )
00042             return fp;
00043         return 0;
00044 #else
00045         return fopen(filename, mode);
00046 #endif
00047     }
00048 
00049 void TiXmlBase::EncodeString(const TIXML_STRING& str, TIXML_STRING* outString) {
00050     int i = 0;
00051 
00052     while (i < (int) str.length()) {
00053         unsigned char c = (unsigned char) str[i];
00054 
00055         if (c == '&' && i < ((int) str.length() - 2) && str[i + 1] == '#'
00056                 && str[i + 2] == 'x') {
00057             // Hexadecimal character reference.
00058             // Pass through unchanged.
00059             // &#xA9;   -- copyright symbol, for example.
00060             //
00061             // The -1 is a bug fix from Rob Laveaux. It keeps
00062             // an overflow from happening if there is no ';'.
00063             // There are actually 2 ways to exit this loop -
00064             // while fails (error case) and break (semicolon found).
00065             // However, there is no mechanism (currently) for
00066             // this function to return an error.
00067             while (i < (int) str.length() - 1) {
00068                 outString->append(str.c_str() + i, 1);
00069                 ++i;
00070                 if (str[i] == ';')
00071                     break;
00072             }
00073         } else if (c == '&') {
00074             outString->append(entity[0].str, entity[0].strLength);
00075             ++i;
00076         } else if (c == '<') {
00077             outString->append(entity[1].str, entity[1].strLength);
00078             ++i;
00079         } else if (c == '>') {
00080             outString->append(entity[2].str, entity[2].strLength);
00081             ++i;
00082         } else if (c == '\"') {
00083             outString->append(entity[3].str, entity[3].strLength);
00084             ++i;
00085         } else if (c == '\'') {
00086             outString->append(entity[4].str, entity[4].strLength);
00087             ++i;
00088         } else if (c < 32) {
00089             // Easy pass at non-alpha/numeric/symbol
00090             // Below 32 is symbolic.
00091             char buf[32];
00092 
00093 #if defined(TIXML_SNPRINTF)
00094             TIXML_SNPRINTF(buf, sizeof(buf), "&#x%02X;", (unsigned) (c & 0xff));
00095 #else
00096             sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) );
00097 #endif
00098 
00099             //*ME:      warning C4267: convert 'size_t' to 'int'
00100             //*ME:      Int-Cast to make compiler happy ...
00101             outString->append(buf, (int) strlen(buf));
00102             ++i;
00103         } else {
00104             //char realc = (char) c;
00105             //outString->append( &realc, 1 );
00106             *outString += (char) c; // somewhat more efficient function call.
00107             ++i;
00108         }
00109     }
00110 }
00111 
00112 TiXmlNode::TiXmlNode(NodeType _type) :
00113     TiXmlBase() {
00114         parent = 0;
00115         type = _type;
00116         firstChild = 0;
00117         lastChild = 0;
00118         prev = 0;
00119         next = 0;
00120     }
00121 
00122 TiXmlNode::~TiXmlNode() {
00123     TiXmlNode* node = firstChild;
00124     TiXmlNode* temp = 0;
00125 
00126     while (node) {
00127         temp = node;
00128         node = node->next;
00129         delete temp;
00130     }
00131 }
00132 
00133 void TiXmlNode::CopyTo(TiXmlNode* target) const {
00134     target->SetValue(value.c_str());
00135     target->userData = userData;
00136 }
00137 
00138 void TiXmlNode::Clear() {
00139     TiXmlNode* node = firstChild;
00140     TiXmlNode* temp = 0;
00141 
00142     while (node) {
00143         temp = node;
00144         node = node->next;
00145         delete temp;
00146     }
00147 
00148     firstChild = 0;
00149     lastChild = 0;
00150 }
00151 
00152 TiXmlNode* TiXmlNode::LinkEndChild(TiXmlNode* node) {
00153     assert( node->parent == 0 || node->parent == this );
00154     assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() );
00155 
00156     if (node->Type() == TiXmlNode::DOCUMENT) {
00157         delete node;
00158         if (GetDocument())
00159             GetDocument()->SetError(TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0,
00160                     TIXML_ENCODING_UNKNOWN);
00161         return 0;
00162     }
00163 
00164     node->parent = this;
00165 
00166     node->prev = lastChild;
00167     node->next = 0;
00168 
00169     if (lastChild)
00170         lastChild->next = node;
00171     else
00172         firstChild = node; // it was an empty list.
00173 
00174     lastChild = node;
00175     return node;
00176 }
00177 
00178 TiXmlNode* TiXmlNode::InsertEndChild(const TiXmlNode& addThis) {
00179     if (addThis.Type() == TiXmlNode::DOCUMENT) {
00180         if (GetDocument())
00181             GetDocument()->SetError(TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0,
00182                     TIXML_ENCODING_UNKNOWN);
00183         return 0;
00184     }
00185     TiXmlNode* node = addThis.Clone();
00186     if (!node)
00187         return 0;
00188 
00189     return LinkEndChild(node);
00190 }
00191 
00192 TiXmlNode* TiXmlNode::InsertBeforeChild(TiXmlNode* beforeThis,
00193         const TiXmlNode& addThis) {
00194     if (!beforeThis || beforeThis->parent != this) {
00195         return 0;
00196     }
00197     if (addThis.Type() == TiXmlNode::DOCUMENT) {
00198         if (GetDocument())
00199             GetDocument()->SetError(TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0,
00200                     TIXML_ENCODING_UNKNOWN);
00201         return 0;
00202     }
00203 
00204     TiXmlNode* node = addThis.Clone();
00205     if (!node)
00206         return 0;
00207     node->parent = this;
00208 
00209     node->next = beforeThis;
00210     node->prev = beforeThis->prev;
00211     if (beforeThis->prev) {
00212         beforeThis->prev->next = node;
00213     } else {
00214         assert( firstChild == beforeThis );
00215         firstChild = node;
00216     }
00217     beforeThis->prev = node;
00218     return node;
00219 }
00220 
00221 TiXmlNode* TiXmlNode::InsertAfterChild(TiXmlNode* afterThis,
00222         const TiXmlNode& addThis) {
00223     if (!afterThis || afterThis->parent != this) {
00224         return 0;
00225     }
00226     if (addThis.Type() == TiXmlNode::DOCUMENT) {
00227         if (GetDocument())
00228             GetDocument()->SetError(TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0,
00229                     TIXML_ENCODING_UNKNOWN);
00230         return 0;
00231     }
00232 
00233     TiXmlNode* node = addThis.Clone();
00234     if (!node)
00235         return 0;
00236     node->parent = this;
00237 
00238     node->prev = afterThis;
00239     node->next = afterThis->next;
00240     if (afterThis->next) {
00241         afterThis->next->prev = node;
00242     } else {
00243         assert( lastChild == afterThis );
00244         lastChild = node;
00245     }
00246     afterThis->next = node;
00247     return node;
00248 }
00249 
00250 TiXmlNode* TiXmlNode::ReplaceChild(TiXmlNode* replaceThis,
00251         const TiXmlNode& withThis) {
00252     if (replaceThis->parent != this)
00253         return 0;
00254 
00255     TiXmlNode* node = withThis.Clone();
00256     if (!node)
00257         return 0;
00258 
00259     node->next = replaceThis->next;
00260     node->prev = replaceThis->prev;
00261 
00262     if (replaceThis->next)
00263         replaceThis->next->prev = node;
00264     else
00265         lastChild = node;
00266 
00267     if (replaceThis->prev)
00268         replaceThis->prev->next = node;
00269     else
00270         firstChild = node;
00271 
00272     delete replaceThis;
00273     node->parent = this;
00274     return node;
00275 }
00276 
00277 bool TiXmlNode::RemoveChild(TiXmlNode* removeThis) {
00278     if (removeThis->parent != this) {
00279         assert( 0 );
00280         return false;
00281     }
00282 
00283     if (removeThis->next)
00284         removeThis->next->prev = removeThis->prev;
00285     else
00286         lastChild = removeThis->prev;
00287 
00288     if (removeThis->prev)
00289         removeThis->prev->next = removeThis->next;
00290     else
00291         firstChild = removeThis->next;
00292 
00293     delete removeThis;
00294     return true;
00295 }
00296 
00297 const TiXmlNode* TiXmlNode::FirstChild(const char * _value) const {
00298     const TiXmlNode* node;
00299     for (node = firstChild; node; node = node->next) {
00300         if (strcmp(node->Value(), _value) == 0)
00301             return node;
00302     }
00303     return 0;
00304 }
00305 
00306 const TiXmlNode* TiXmlNode::LastChild(const char * _value) const {
00307     const TiXmlNode* node;
00308     for (node = lastChild; node; node = node->prev) {
00309         if (strcmp(node->Value(), _value) == 0)
00310             return node;
00311     }
00312     return 0;
00313 }
00314 
00315 const TiXmlNode* TiXmlNode::IterateChildren(const TiXmlNode* previous) const {
00316     if (!previous) {
00317         return FirstChild();
00318     } else {
00319         assert( previous->parent == this );
00320         return previous->NextSibling();
00321     }
00322 }
00323 
00324 const TiXmlNode* TiXmlNode::IterateChildren(const char * val,
00325         const TiXmlNode* previous) const {
00326     if (!previous) {
00327         return FirstChild(val);
00328     } else {
00329         assert( previous->parent == this );
00330         return previous->NextSibling(val);
00331     }
00332 }
00333 
00334 const TiXmlNode* TiXmlNode::NextSibling(const char * _value) const {
00335     const TiXmlNode* node;
00336     for (node = next; node; node = node->next) {
00337         if (strcmp(node->Value(), _value) == 0)
00338             return node;
00339     }
00340     return 0;
00341 }
00342 
00343 const TiXmlNode* TiXmlNode::PreviousSibling(const char * _value) const {
00344     const TiXmlNode* node;
00345     for (node = prev; node; node = node->prev) {
00346         if (strcmp(node->Value(), _value) == 0)
00347             return node;
00348     }
00349     return 0;
00350 }
00351 
00352 void TiXmlElement::RemoveAttribute(const char * name) {
00353 #ifdef TIXML_USE_STL
00354     TIXML_STRING str( name );
00355     TiXmlAttribute* node = attributeSet.Find( str );
00356 #else
00357     TiXmlAttribute* node = attributeSet.Find(name);
00358 #endif
00359     if (node) {
00360         attributeSet.Remove(node);
00361         delete node;
00362     }
00363 }
00364 
00365 const TiXmlElement* TiXmlNode::FirstChildElement() const {
00366     const TiXmlNode* node;
00367 
00368     for (node = FirstChild(); node; node = node->NextSibling()) {
00369         if (node->ToElement())
00370             return node->ToElement();
00371     }
00372     return 0;
00373 }
00374 
00375 const TiXmlElement* TiXmlNode::FirstChildElement(const char * _value) const {
00376     const TiXmlNode* node;
00377 
00378     for (node = FirstChild(_value); node; node = node->NextSibling(_value)) {
00379         if (node->ToElement())
00380             return node->ToElement();
00381     }
00382     return 0;
00383 }
00384 
00385 const TiXmlElement* TiXmlNode::NextSiblingElement() const {
00386     const TiXmlNode* node;
00387 
00388     for (node = NextSibling(); node; node = node->NextSibling()) {
00389         if (node->ToElement())
00390             return node->ToElement();
00391     }
00392     return 0;
00393 }
00394 
00395 const TiXmlElement* TiXmlNode::NextSiblingElement(const char * _value) const {
00396     const TiXmlNode* node;
00397 
00398     for (node = NextSibling(_value); node; node = node->NextSibling(_value)) {
00399         if (node->ToElement())
00400             return node->ToElement();
00401     }
00402     return 0;
00403 }
00404 
00405 const TiXmlDocument* TiXmlNode::GetDocument() const {
00406     const TiXmlNode* node;
00407 
00408     for (node = this; node; node = node->parent) {
00409         if (node->ToDocument())
00410             return node->ToDocument();
00411     }
00412     return 0;
00413 }
00414 
00415 TiXmlElement::TiXmlElement(const char * _value) :
00416     TiXmlNode(TiXmlNode::ELEMENT) {
00417         firstChild = lastChild = 0;
00418         value = _value;
00419     }
00420 
00421 #ifdef TIXML_USE_STL
00422     TiXmlElement::TiXmlElement( const std::string& _value )
00423 : TiXmlNode( TiXmlNode::ELEMENT )
00424 {
00425     firstChild = lastChild = 0;
00426     value = _value;
00427 }
00428 #endif
00429 
00430 TiXmlElement::TiXmlElement(const TiXmlElement& copy) :
00431     TiXmlNode(TiXmlNode::ELEMENT) {
00432         firstChild = lastChild = 0;
00433         copy.CopyTo(this);
00434     }
00435 
00436 void TiXmlElement::operator=(const TiXmlElement& base) {
00437     ClearThis();
00438     base.CopyTo(this);
00439 }
00440 
00441 TiXmlElement::~TiXmlElement() {
00442     ClearThis();
00443 }
00444 
00445 void TiXmlElement::ClearThis() {
00446     Clear();
00447     while (attributeSet.First()) {
00448         TiXmlAttribute* node = attributeSet.First();
00449         attributeSet.Remove(node);
00450         delete node;
00451     }
00452 }
00453 
00454 const char* TiXmlElement::Attribute(const char* name) const {
00455     const TiXmlAttribute* node = attributeSet.Find(name);
00456     if (node)
00457         return node->Value();
00458     return 0;
00459 }
00460 
00461 #ifdef TIXML_USE_STL
00462 const std::string* TiXmlElement::Attribute( const std::string& name ) const
00463 {
00464     const TiXmlAttribute* node = attributeSet.Find( name );
00465     if ( node )
00466         return &node->ValueStr();
00467     return 0;
00468 }
00469 #endif
00470 
00471 const char* TiXmlElement::Attribute(const char* name, int* i) const {
00472     const char* s = Attribute(name);
00473     if (i) {
00474         if (s) {
00475             *i = atoi(s);
00476         } else {
00477             *i = 0;
00478         }
00479     }
00480     return s;
00481 }
00482 
00483 #ifdef TIXML_USE_STL
00484 const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const
00485 {
00486     const std::string* s = Attribute( name );
00487     if ( i )
00488     {
00489         if ( s ) {
00490             *i = atoi( s->c_str() );
00491         }
00492         else {
00493             *i = 0;
00494         }
00495     }
00496     return s;
00497 }
00498 #endif
00499 
00500 const char* TiXmlElement::Attribute(const char* name, double* d) const {
00501     const char* s = Attribute(name);
00502     if (d) {
00503         if (s) {
00504             *d = atof(s);
00505         } else {
00506             *d = 0;
00507         }
00508     }
00509     return s;
00510 }
00511 
00512 #ifdef TIXML_USE_STL
00513 const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const
00514 {
00515     const std::string* s = Attribute( name );
00516     if ( d )
00517     {
00518         if ( s ) {
00519             *d = atof( s->c_str() );
00520         }
00521         else {
00522             *d = 0;
00523         }
00524     }
00525     return s;
00526 }
00527 #endif
00528 
00529 int TiXmlElement::QueryIntAttribute(const char* name, int* ival) const {
00530     const TiXmlAttribute* node = attributeSet.Find(name);
00531     if (!node)
00532         return TIXML_NO_ATTRIBUTE;
00533     return node->QueryIntValue(ival);
00534 }
00535 
00536 #ifdef TIXML_USE_STL
00537 int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const
00538 {
00539     const TiXmlAttribute* node = attributeSet.Find( name );
00540     if ( !node )
00541         return TIXML_NO_ATTRIBUTE;
00542     return node->QueryIntValue( ival );
00543 }
00544 #endif
00545 
00546 int TiXmlElement::QueryDoubleAttribute(const char* name, double* dval) const {
00547     const TiXmlAttribute* node = attributeSet.Find(name);
00548     if (!node)
00549         return TIXML_NO_ATTRIBUTE;
00550     return node->QueryDoubleValue(dval);
00551 }
00552 
00553 #ifdef TIXML_USE_STL
00554 int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const
00555 {
00556     const TiXmlAttribute* node = attributeSet.Find( name );
00557     if ( !node )
00558         return TIXML_NO_ATTRIBUTE;
00559     return node->QueryDoubleValue( dval );
00560 }
00561 #endif
00562 
00563 void TiXmlElement::SetAttribute(const char * name, int val) {
00564     char buf[64];
00565 #if defined(TIXML_SNPRINTF)
00566     TIXML_SNPRINTF(buf, sizeof(buf), "%d", val);
00567 #else
00568     sprintf( buf, "%d", val );
00569 #endif
00570     SetAttribute(name, buf);
00571 }
00572 
00573 #ifdef TIXML_USE_STL
00574 void TiXmlElement::SetAttribute( const std::string& name, int val )
00575 {
00576     std::ostringstream oss;
00577     oss << val;
00578     SetAttribute( name, oss.str() );
00579 }
00580 #endif
00581 
00582 void TiXmlElement::SetDoubleAttribute(const char * name, double val) {
00583     char buf[256];
00584 #if defined(TIXML_SNPRINTF)
00585     TIXML_SNPRINTF(buf, sizeof(buf), "%f", val);
00586 #else
00587     sprintf( buf, "%f", val );
00588 #endif
00589     SetAttribute(name, buf);
00590 }
00591 
00592 void TiXmlElement::SetAttribute(const char * cname, const char * cvalue) {
00593 #ifdef TIXML_USE_STL
00594     TIXML_STRING _name( cname );
00595     TIXML_STRING _value( cvalue );
00596 #else
00597     const char* _name = cname;
00598     const char* _value = cvalue;
00599 #endif
00600 
00601     TiXmlAttribute* node = attributeSet.Find(_name);
00602     if (node) {
00603         node->SetValue(_value);
00604         return;
00605     }
00606 
00607     TiXmlAttribute* attrib = new TiXmlAttribute(cname, cvalue);
00608     if (attrib) {
00609         attributeSet.Add(attrib);
00610     } else {
00611         TiXmlDocument* document = GetDocument();
00612         if (document)
00613             document->SetError(TIXML_ERROR_OUT_OF_MEMORY, 0, 0,
00614                     TIXML_ENCODING_UNKNOWN);
00615     }
00616 }
00617 
00618 #ifdef TIXML_USE_STL
00619 void TiXmlElement::SetAttribute( const std::string& name, const std::string& _value )
00620 {
00621     TiXmlAttribute* node = attributeSet.Find( name );
00622     if ( node )
00623     {
00624         node->SetValue( _value );
00625         return;
00626     }
00627 
00628     TiXmlAttribute* attrib = new TiXmlAttribute( name, _value );
00629     if ( attrib )
00630     {
00631         attributeSet.Add( attrib );
00632     }
00633     else
00634     {
00635         TiXmlDocument* document = GetDocument();
00636         if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
00637     }
00638 }
00639 #endif
00640 
00641 void TiXmlElement::Print(FILE* cfile, int depth) const {
00642     int i;
00643     assert( cfile );
00644     for (i = 0; i < depth; i++) {
00645         fprintf(cfile, "    ");
00646     }
00647 
00648     fprintf(cfile, "<%s", value.c_str());
00649 
00650     const TiXmlAttribute* attrib;
00651     for (attrib = attributeSet.First(); attrib; attrib = attrib->Next()) {
00652         fprintf(cfile, " ");
00653         attrib->Print(cfile, depth);
00654     }
00655 
00656     // There are 3 different formatting approaches:
00657     // 1) An element without children is printed as a <foo /> node
00658     // 2) An element with only a text child is printed as <foo> text </foo>
00659     // 3) An element with children is printed on multiple lines.
00660     TiXmlNode* node;
00661     if (!firstChild) {
00662         fprintf(cfile, " />");
00663     } else if (firstChild == lastChild && firstChild->ToText()) {
00664         fprintf(cfile, ">");
00665         firstChild->Print(cfile, depth + 1);
00666         fprintf(cfile, "</%s>", value.c_str());
00667     } else {
00668         fprintf(cfile, ">");
00669 
00670         for (node = firstChild; node; node = node->NextSibling()) {
00671             if (!node->ToText()) {
00672                 fprintf(cfile, "\n");
00673             }
00674             node->Print(cfile, depth + 1);
00675         }
00676         fprintf(cfile, "\n");
00677         for (i = 0; i < depth; ++i) {
00678             fprintf(cfile, "    ");
00679         }
00680         fprintf(cfile, "</%s>", value.c_str());
00681     }
00682 }
00683 
00684 void TiXmlElement::CopyTo(TiXmlElement* target) const {
00685     // superclass:
00686     TiXmlNode::CopyTo(target);
00687 
00688     // Element class:
00689     // Clone the attributes, then clone the children.
00690     const TiXmlAttribute* attribute = 0;
00691     for (attribute = attributeSet.First(); attribute; attribute
00692             = attribute->Next()) {
00693         target->SetAttribute(attribute->Name(), attribute->Value());
00694     }
00695 
00696     TiXmlNode* node = 0;
00697     for (node = firstChild; node; node = node->NextSibling()) {
00698         target->LinkEndChild(node->Clone());
00699     }
00700 }
00701 
00702 bool TiXmlElement::Accept(TiXmlVisitor* visitor) const {
00703     if (visitor->VisitEnter(*this, attributeSet.First())) {
00704         for (const TiXmlNode* node = FirstChild(); node; node
00705                 = node->NextSibling()) {
00706             if (!node->Accept(visitor))
00707                 break;
00708         }
00709     }
00710     return visitor->VisitExit(*this);
00711 }
00712 
00713 TiXmlNode* TiXmlElement::Clone() const {
00714     TiXmlElement* clone = new TiXmlElement(Value());
00715     if (!clone)
00716         return 0;
00717 
00718     CopyTo(clone);
00719     return clone;
00720 }
00721 
00722 const char* TiXmlElement::GetText() const {
00723     const TiXmlNode* child = this->FirstChild();
00724     if (child) {
00725         const TiXmlText* childText = child->ToText();
00726         if (childText) {
00727             return childText->Value();
00728         }
00729     }
00730     return 0;
00731 }
00732 
00733 TiXmlDocument::TiXmlDocument() :
00734     TiXmlNode(TiXmlNode::DOCUMENT) {
00735         tabsize = 4;
00736         useMicrosoftBOM = false;
00737         ClearError();
00738     }
00739 
00740 TiXmlDocument::TiXmlDocument(const char * documentName) :
00741     TiXmlNode(TiXmlNode::DOCUMENT) {
00742         tabsize = 4;
00743         useMicrosoftBOM = false;
00744         value = documentName;
00745         ClearError();
00746     }
00747 
00748 #ifdef TIXML_USE_STL
00749 TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
00750 {
00751     tabsize = 4;
00752     useMicrosoftBOM = false;
00753     value = documentName;
00754     ClearError();
00755 }
00756 #endif
00757 
00758 TiXmlDocument::TiXmlDocument(const TiXmlDocument& copy) :
00759     TiXmlNode(TiXmlNode::DOCUMENT) {
00760         copy.CopyTo(this);
00761     }
00762 
00763 void TiXmlDocument::operator=(const TiXmlDocument& copy) {
00764     Clear();
00765     copy.CopyTo(this);
00766 }
00767 
00768 bool TiXmlDocument::LoadFile(TiXmlEncoding encoding) {
00769     // See STL_STRING_BUG below.
00770     //StringToBuffer buf( value );
00771 
00772     return LoadFile(Value(), encoding);
00773 }
00774 
00775 bool TiXmlDocument::SaveFile() const {
00776     // See STL_STRING_BUG below.
00777     //  StringToBuffer buf( value );
00778     //
00779     //  if ( buf.buffer && SaveFile( buf.buffer ) )
00780     //          return true;
00781     //
00782     //  return false;
00783     return SaveFile(Value());
00784 }
00785 
00786 bool TiXmlDocument::LoadFile(const char* _filename, TiXmlEncoding encoding) {
00787     // There was a really terrifying little bug here. The code:
00788     //          value = filename
00789     // in the STL case, cause the assignment method of the std::string to
00790     // be called. What is strange, is that the std::string had the same
00791     // address as it's c_str() method, and so bad things happen. Looks
00792     // like a bug in the Microsoft STL implementation.
00793     // Add an extra string to avoid the crash.
00794     TIXML_STRING filename(_filename);
00795     value = filename;
00796 
00797     // reading in binary mode so that tinyxml can normalize the EOL
00798     FILE* file = TiXmlFOpen(value.c_str(), "rb");
00799 
00800     if (file) {
00801         bool result = LoadFile(file, encoding);
00802         fclose(file);
00803         return result;
00804     } else {
00805         SetError(TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN);
00806         return false;
00807     }
00808 }
00809 
00810 bool TiXmlDocument::LoadFile(FILE* file, TiXmlEncoding encoding) {
00811     if (!file) {
00812         SetError(TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN);
00813         return false;
00814     }
00815 
00816     // Delete the existing data:
00817     Clear();
00818     location.Clear();
00819 
00820     // Get the file size, so we can pre-allocate the string. HUGE speed impact.
00821     long length = 0;
00822     fseek(file, 0, SEEK_END );
00823     length = ftell(file);
00824     fseek(file, 0, SEEK_SET );
00825 
00826     // Strange case, but good to handle up front.
00827     if (length <= 0) {
00828         SetError(TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN);
00829         return false;
00830     }
00831     // If we have a file, assume it is all one big XML file, and read it in.
00832     // The document parser may decide the document ends sooner than the entire file, however.
00833     TIXML_STRING data;
00834     data.reserve(length);
00835 
00836     // Subtle bug here. TinyXml did use fgets. But from the XML spec:
00837     // 2.11 End-of-Line Handling
00838     // <snip>
00839     // <quote>
00840     // ...the XML processor MUST behave as if it normalized all line breaks in external
00841     // parsed entities (including the document entity) on input, before parsing, by translating
00842     // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to
00843     // a single #xA character.
00844     // </quote>
00845     //
00846     // It is not clear fgets does that, and certainly isn't clear it works cross platform.
00847     // Generally, you expect fgets to translate from the convention of the OS to the c/unix
00848     // convention, and not work generally.
00849 
00850     /*
00851        while( fgets( buf, sizeof(buf), file ) )
00852        {
00853        data += buf;
00854        }
00855        */
00856 
00857     char* buf = new char[length + 1];
00858     buf[0] = 0;
00859 
00860     if (fread(buf, length, 1, file) != 1) {
00861         delete[] buf;
00862         SetError(TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN);
00863         return false;
00864     }
00865 
00866     const char* lastPos = buf;
00867     const char* p = buf;
00868 
00869     buf[length] = 0;
00870     while (*p) {
00871         assert( p < (buf+length) );
00872         if (*p == 0xa) {
00873             // Newline character. No special rules for this. Append all the characters
00874             // since the last string, and include the newline.
00875             data.append(lastPos, (p - lastPos + 1)); // append, include the newline
00876             ++p; // move past the newline
00877             lastPos = p; // and point to the new buffer (may be 0)
00878             assert( p <= (buf+length) );
00879         } else if (*p == 0xd) {
00880             // Carriage return. Append what we have so far, then
00881             // handle moving forward in the buffer.
00882             if ((p - lastPos) > 0) {
00883                 data.append(lastPos, p - lastPos); // do not add the CR
00884             }
00885             data += (char) 0xa; // a proper newline
00886 
00887             if (*(p + 1) == 0xa) {
00888                 // Carriage return - new line sequence
00889                 p += 2;
00890                 lastPos = p;
00891                 assert( p <= (buf+length) );
00892             } else {
00893                 // it was followed by something else...that is presumably characters again.
00894                 ++p;
00895                 lastPos = p;
00896                 assert( p <= (buf+length) );
00897             }
00898         } else {
00899             ++p;
00900         }
00901     }
00902     // Handle any left over characters.
00903     if (p - lastPos) {
00904         data.append(lastPos, p - lastPos);
00905     }
00906     delete[] buf;
00907     buf = 0;
00908 
00909     Parse(data.c_str(), 0, encoding);
00910 
00911     if (Error())
00912         return false;
00913     else
00914         return true;
00915 }
00916 
00917 bool TiXmlDocument::SaveFile(const char * filename) const {
00918     // The old c stuff lives on...
00919     FILE* fp = TiXmlFOpen(filename, "w");
00920     if (fp) {
00921         bool result = SaveFile(fp);
00922         fclose(fp);
00923         return result;
00924     }
00925     return false;
00926 }
00927 
00928 bool TiXmlDocument::SaveFile(FILE* fp) const {
00929     if (useMicrosoftBOM) {
00930         const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
00931         const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
00932         const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
00933 
00934         fputc(TIXML_UTF_LEAD_0, fp);
00935         fputc(TIXML_UTF_LEAD_1, fp);
00936         fputc(TIXML_UTF_LEAD_2, fp);
00937     }
00938     Print(fp, 0);
00939     return (ferror(fp) == 0);
00940 }
00941 
00942 void TiXmlDocument::CopyTo(TiXmlDocument* target) const {
00943     TiXmlNode::CopyTo(target);
00944 
00945     target->error = error;
00946     target->errorId = errorId;
00947     target->errorDesc = errorDesc;
00948     target->tabsize = tabsize;
00949     target->errorLocation = errorLocation;
00950     target->useMicrosoftBOM = useMicrosoftBOM;
00951 
00952     TiXmlNode* node = 0;
00953     for (node = firstChild; node; node = node->NextSibling()) {
00954         target->LinkEndChild(node->Clone());
00955     }
00956 }
00957 
00958 TiXmlNode* TiXmlDocument::Clone() const {
00959     TiXmlDocument* clone = new TiXmlDocument();
00960     if (!clone)
00961         return 0;
00962 
00963     CopyTo(clone);
00964     return clone;
00965 }
00966 
00967 void TiXmlDocument::Print(FILE* cfile, int depth) const {
00968     assert( cfile );
00969     for (const TiXmlNode* node = FirstChild(); node; node = node->NextSibling()) {
00970         node->Print(cfile, depth);
00971         fprintf(cfile, "\n");
00972     }
00973 }
00974 
00975 bool TiXmlDocument::Accept(TiXmlVisitor* visitor) const {
00976     if (visitor->VisitEnter(*this)) {
00977         for (const TiXmlNode* node = FirstChild(); node; node
00978                 = node->NextSibling()) {
00979             if (!node->Accept(visitor))
00980                 break;
00981         }
00982     }
00983     return visitor->VisitExit(*this);
00984 }
00985 
00986 const TiXmlAttribute* TiXmlAttribute::Next() const {
00987     // We are using knowledge of the sentinel. The sentinel
00988     // have a value or name.
00989     if (next->value.empty() && next->name.empty())
00990         return 0;
00991     return next;
00992 }
00993 
00994 /*
00995    TiXmlAttribute* TiXmlAttribute::Next()
00996    {
00997 // We are using knowledge of the sentinel. The sentinel
00998 // have a value or name.
00999 if ( next->value.empty() && next->name.empty() )
01000 return 0;
01001 return next;
01002 }
01003 */
01004 
01005 const TiXmlAttribute* TiXmlAttribute::Previous() const {
01006     // We are using knowledge of the sentinel. The sentinel
01007     // have a value or name.
01008     if (prev->value.empty() && prev->name.empty())
01009         return 0;
01010     return prev;
01011 }
01012 
01013 /*
01014    TiXmlAttribute* TiXmlAttribute::Previous()
01015    {
01016 // We are using knowledge of the sentinel. The sentinel
01017 // have a value or name.
01018 if ( prev->value.empty() && prev->name.empty() )
01019 return 0;
01020 return prev;
01021 }
01022 */
01023 
01024 void TiXmlAttribute::Print(FILE* cfile, int /*depth*/, TIXML_STRING* str) const {
01025     TIXML_STRING n, v;
01026 
01027     EncodeString(name, &n);
01028     EncodeString(value, &v);
01029 
01030     if (value.find('\"') == TIXML_STRING::npos) {
01031         if (cfile) {
01032             fprintf(cfile, "%s=\"%s\"", n.c_str(), v.c_str());
01033         }
01034         if (str) {
01035             (*str) += n;
01036             (*str) += "=\"";
01037             (*str) += v;
01038             (*str) += "\"";
01039         }
01040     } else {
01041         if (cfile) {
01042             fprintf(cfile, "%s='%s'", n.c_str(), v.c_str());
01043         }
01044         if (str) {
01045             (*str) += n;
01046             (*str) += "='";
01047             (*str) += v;
01048             (*str) += "'";
01049         }
01050     }
01051 }
01052 
01053 int TiXmlAttribute::QueryIntValue(int* ival) const {
01054     if (TIXML_SSCANF(value.c_str(), "%d", ival) == 1)
01055         return TIXML_SUCCESS;
01056     return TIXML_WRONG_TYPE;
01057 }
01058 
01059 int TiXmlAttribute::QueryDoubleValue(double* dval) const {
01060     if (TIXML_SSCANF(value.c_str(), "%lf", dval) == 1)
01061         return TIXML_SUCCESS;
01062     return TIXML_WRONG_TYPE;
01063 }
01064 
01065 void TiXmlAttribute::SetIntValue(int _value) {
01066     char buf[64];
01067 #if defined(TIXML_SNPRINTF)
01068     TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value);
01069 #else
01070     sprintf (buf, "%d", _value);
01071 #endif
01072     SetValue(buf);
01073 }
01074 
01075 void TiXmlAttribute::SetDoubleValue(double _value) {
01076     char buf[256];
01077 #if defined(TIXML_SNPRINTF)
01078     TIXML_SNPRINTF(buf, sizeof(buf), "%lf", _value);
01079 #else
01080     sprintf (buf, "%lf", _value);
01081 #endif
01082     SetValue(buf);
01083 }
01084 
01085 int TiXmlAttribute::IntValue() const {
01086     return atoi(value.c_str());
01087 }
01088 
01089 double TiXmlAttribute::DoubleValue() const {
01090     return atof(value.c_str());
01091 }
01092 
01093 TiXmlComment::TiXmlComment(const TiXmlComment& copy) :
01094     TiXmlNode(TiXmlNode::COMMENT) {
01095         copy.CopyTo(this);
01096     }
01097 
01098 void TiXmlComment::operator=(const TiXmlComment& base) {
01099     Clear();
01100     base.CopyTo(this);
01101 }
01102 
01103 void TiXmlComment::Print(FILE* cfile, int depth) const {
01104     assert( cfile );
01105     for (int i = 0; i < depth; i++) {
01106         fprintf(cfile, "    ");
01107     }
01108     fprintf(cfile, "<!--%s-->", value.c_str());
01109 }
01110 
01111 void TiXmlComment::CopyTo(TiXmlComment* target) const {
01112     TiXmlNode::CopyTo(target);
01113 }
01114 
01115 bool TiXmlComment::Accept(TiXmlVisitor* visitor) const {
01116     return visitor->Visit(*this);
01117 }
01118 
01119 TiXmlNode* TiXmlComment::Clone() const {
01120     TiXmlComment* clone = new TiXmlComment();
01121 
01122     if (!clone)
01123         return 0;
01124 
01125     CopyTo(clone);
01126     return clone;
01127 }
01128 
01129 void TiXmlText::Print(FILE* cfile, int depth) const {
01130     assert( cfile );
01131     if (cdata) {
01132         int i;
01133         fprintf(cfile, "\n");
01134         for (i = 0; i < depth; i++) {
01135             fprintf(cfile, "    ");
01136         }
01137         fprintf(cfile, "<![CDATA[%s]]>\n", value.c_str()); // unformatted output
01138     } else {
01139         TIXML_STRING buffer;
01140         EncodeString(value, &buffer);
01141         fprintf(cfile, "%s", buffer.c_str());
01142     }
01143 }
01144 
01145 void TiXmlText::CopyTo(TiXmlText* target) const {
01146     TiXmlNode::CopyTo(target);
01147     target->cdata = cdata;
01148 }
01149 
01150 bool TiXmlText::Accept(TiXmlVisitor* visitor) const {
01151     return visitor->Visit(*this);
01152 }
01153 
01154 TiXmlNode* TiXmlText::Clone() const {
01155     TiXmlText* clone = 0;
01156     clone = new TiXmlText("");
01157 
01158     if (!clone)
01159         return 0;
01160 
01161     CopyTo(clone);
01162     return clone;
01163 }
01164 
01165 TiXmlDeclaration::TiXmlDeclaration(const char * _version,
01166         const char * _encoding, const char * _standalone) :
01167     TiXmlNode(TiXmlNode::DECLARATION) {
01168         version = _version;
01169         encoding = _encoding;
01170         standalone = _standalone;
01171     }
01172 
01173 #ifdef TIXML_USE_STL
01174 TiXmlDeclaration::TiXmlDeclaration( const std::string& _version,
01175         const std::string& _encoding,
01176         const std::string& _standalone )
01177 : TiXmlNode( TiXmlNode::DECLARATION )
01178 {
01179     version = _version;
01180     encoding = _encoding;
01181     standalone = _standalone;
01182 }
01183 #endif
01184 
01185 TiXmlDeclaration::TiXmlDeclaration(const TiXmlDeclaration& copy) :
01186     TiXmlNode(TiXmlNode::DECLARATION) {
01187         copy.CopyTo(this);
01188     }
01189 
01190 void TiXmlDeclaration::operator=(const TiXmlDeclaration& copy) {
01191     Clear();
01192     copy.CopyTo(this);
01193 }
01194 
01195     void TiXmlDeclaration::Print(FILE* cfile, int /*depth*/, TIXML_STRING* str) const {
01196         if (cfile)
01197             fprintf(cfile, "<?xml ");
01198         if (str)
01199             (*str) += "<?xml ";
01200 
01201         if (!version.empty()) {
01202             if (cfile)
01203                 fprintf(cfile, "version=\"%s\" ", version.c_str());
01204             if (str) {
01205                 (*str) += "version=\"";
01206                 (*str) += version;
01207                 (*str) += "\" ";
01208             }
01209         }
01210         if (!encoding.empty()) {
01211             if (cfile)
01212                 fprintf(cfile, "encoding=\"%s\" ", encoding.c_str());
01213             if (str) {
01214                 (*str) += "encoding=\"";
01215                 (*str) += encoding;
01216                 (*str) += "\" ";
01217             }
01218         }
01219         if (!standalone.empty()) {
01220             if (cfile)
01221                 fprintf(cfile, "standalone=\"%s\" ", standalone.c_str());
01222             if (str) {
01223                 (*str) += "standalone=\"";
01224                 (*str) += standalone;
01225                 (*str) += "\" ";
01226             }
01227         }
01228         if (cfile)
01229             fprintf(cfile, "?>");
01230         if (str)
01231             (*str) += "?>";
01232     }
01233 
01234 void TiXmlDeclaration::CopyTo(TiXmlDeclaration* target) const {
01235     TiXmlNode::CopyTo(target);
01236 
01237     target->version = version;
01238     target->encoding = encoding;
01239     target->standalone = standalone;
01240 }
01241 
01242 bool TiXmlDeclaration::Accept(TiXmlVisitor* visitor) const {
01243     return visitor->Visit(*this);
01244 }
01245 
01246 TiXmlNode* TiXmlDeclaration::Clone() const {
01247     TiXmlDeclaration* clone = new TiXmlDeclaration();
01248 
01249     if (!clone)
01250         return 0;
01251 
01252     CopyTo(clone);
01253     return clone;
01254 }
01255 
01256 void TiXmlUnknown::Print(FILE* cfile, int depth) const {
01257     for (int i = 0; i < depth; i++)
01258         fprintf(cfile, "    ");
01259     fprintf(cfile, "<%s>", value.c_str());
01260 }
01261 
01262 void TiXmlUnknown::CopyTo(TiXmlUnknown* target) const {
01263     TiXmlNode::CopyTo(target);
01264 }
01265 
01266 bool TiXmlUnknown::Accept(TiXmlVisitor* visitor) const {
01267     return visitor->Visit(*this);
01268 }
01269 
01270 TiXmlNode* TiXmlUnknown::Clone() const {
01271     TiXmlUnknown* clone = new TiXmlUnknown();
01272 
01273     if (!clone)
01274         return 0;
01275 
01276     CopyTo(clone);
01277     return clone;
01278 }
01279 
01280 TiXmlAttributeSet::TiXmlAttributeSet() {
01281     sentinel.next = &sentinel;
01282     sentinel.prev = &sentinel;
01283 }
01284 
01285 TiXmlAttributeSet::~TiXmlAttributeSet() {
01286     assert( sentinel.next == &sentinel );
01287     assert( sentinel.prev == &sentinel );
01288 }
01289 
01290 void TiXmlAttributeSet::Add(TiXmlAttribute* addMe) {
01291 #ifdef TIXML_USE_STL
01292     assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set.
01293 #else
01294     assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set.
01295 #endif
01296 
01297     addMe->next = &sentinel;
01298     addMe->prev = sentinel.prev;
01299 
01300     sentinel.prev->next = addMe;
01301     sentinel.prev = addMe;
01302 }
01303 
01304 void TiXmlAttributeSet::Remove(TiXmlAttribute* removeMe) {
01305     TiXmlAttribute* node;
01306 
01307     for (node = sentinel.next; node != &sentinel; node = node->next) {
01308         if (node == removeMe) {
01309             node->prev->next = node->next;
01310             node->next->prev = node->prev;
01311             node->next = 0;
01312             node->prev = 0;
01313             return;
01314         }
01315     }
01316     assert( 0 ); // we tried to remove a non-linked attribute.
01317 }
01318 
01319 #ifdef TIXML_USE_STL
01320 const TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const
01321 {
01322     for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
01323     {
01324         if ( node->name == name )
01325             return node;
01326     }
01327     return 0;
01328 }
01329 
01330 /*
01331    TiXmlAttribute*      TiXmlAttributeSet::Find( const std::string& name )
01332    {
01333    for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
01334    {
01335    if ( node->name == name )
01336    return node;
01337    }
01338    return 0;
01339    }
01340    */
01341 #endif
01342 
01343 const TiXmlAttribute* TiXmlAttributeSet::Find(const char* name) const {
01344     for (const TiXmlAttribute* node = sentinel.next; node != &sentinel; node
01345             = node->next) {
01346         if (strcmp(node->name.c_str(), name) == 0)
01347             return node;
01348     }
01349     return 0;
01350 }
01351 
01352 /*
01353    TiXmlAttribute*      TiXmlAttributeSet::Find( const char* name )
01354    {
01355    for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
01356    {
01357    if ( strcmp( node->name.c_str(), name ) == 0 )
01358    return node;
01359    }
01360    return 0;
01361    }
01362    */
01363 
01364 #ifdef TIXML_USE_STL
01365 std::istream& operator>> (std::istream & in, TiXmlNode & base)
01366 {
01367     TIXML_STRING tag;
01368     tag.reserve( 8 * 1000 );
01369     base.StreamIn( &in, &tag );
01370 
01371     base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING );
01372     return in;
01373 }
01374 #endif
01375 
01376 #ifdef TIXML_USE_STL
01377 std::ostream& operator<< (std::ostream & out, const TiXmlNode & base)
01378 {
01379     TiXmlPrinter printer;
01380     printer.SetStreamPrinting();
01381     base.Accept( &printer );
01382     out << printer.Str();
01383 
01384     return out;
01385 }
01386 
01387 std::string& operator<< (std::string& out, const TiXmlNode& base )
01388 {
01389     TiXmlPrinter printer;
01390     printer.SetStreamPrinting();
01391     base.Accept( &printer );
01392     out.append( printer.Str() );
01393 
01394     return out;
01395 }
01396 #endif
01397 
01398 TiXmlHandle TiXmlHandle::FirstChild() const {
01399     if (node) {
01400         TiXmlNode* child = node->FirstChild();
01401         if (child)
01402             return TiXmlHandle(child);
01403     }
01404     return TiXmlHandle(0);
01405 }
01406 
01407 TiXmlHandle TiXmlHandle::FirstChild(const char * value) const {
01408     if (node) {
01409         TiXmlNode* child = node->FirstChild(value);
01410         if (child)
01411             return TiXmlHandle(child);
01412     }
01413     return TiXmlHandle(0);
01414 }
01415 
01416 TiXmlHandle TiXmlHandle::FirstChildElement() const {
01417     if (node) {
01418         TiXmlElement* child = node->FirstChildElement();
01419         if (child)
01420             return TiXmlHandle(child);
01421     }
01422     return TiXmlHandle(0);
01423 }
01424 
01425 TiXmlHandle TiXmlHandle::FirstChildElement(const char * value) const {
01426     if (node) {
01427         TiXmlElement* child = node->FirstChildElement(value);
01428         if (child)
01429             return TiXmlHandle(child);
01430     }
01431     return TiXmlHandle(0);
01432 }
01433 
01434 TiXmlHandle TiXmlHandle::Child(int count) const {
01435     if (node) {
01436         int i;
01437         TiXmlNode* child = node->FirstChild();
01438         for (i = 0; child && i < count; child = child->NextSibling(), ++i) {
01439             // nothing
01440         }
01441         if (child)
01442             return TiXmlHandle(child);
01443     }
01444     return TiXmlHandle(0);
01445 }
01446 
01447 TiXmlHandle TiXmlHandle::Child(const char* value, int count) const {
01448     if (node) {
01449         int i;
01450         TiXmlNode* child = node->FirstChild(value);
01451         for (i = 0; child && i < count; child = child->NextSibling(value), ++i) {
01452             // nothing
01453         }
01454         if (child)
01455             return TiXmlHandle(child);
01456     }
01457     return TiXmlHandle(0);
01458 }
01459 
01460 TiXmlHandle TiXmlHandle::ChildElement(int count) const {
01461     if (node) {
01462         int i;
01463         TiXmlElement* child = node->FirstChildElement();
01464         for (i = 0; child && i < count; child = child->NextSiblingElement(), ++i) {
01465             // nothing
01466         }
01467         if (child)
01468             return TiXmlHandle(child);
01469     }
01470     return TiXmlHandle(0);
01471 }
01472 
01473 TiXmlHandle TiXmlHandle::ChildElement(const char* value, int count) const {
01474     if (node) {
01475         int i;
01476         TiXmlElement* child = node->FirstChildElement(value);
01477         for (i = 0; child && i < count; child
01478                 = child->NextSiblingElement(value), ++i) {
01479             // nothing
01480         }
01481         if (child)
01482             return TiXmlHandle(child);
01483     }
01484     return TiXmlHandle(0);
01485 }
01486 
01487 bool TiXmlPrinter::VisitEnter(const TiXmlDocument&) {
01488     return true;
01489 }
01490 
01491 bool TiXmlPrinter::VisitExit(const TiXmlDocument&) {
01492     return true;
01493 }
01494 
01495 bool TiXmlPrinter::VisitEnter(const TiXmlElement& element,
01496         const TiXmlAttribute* firstAttribute) {
01497     DoIndent();
01498     buffer += "<";
01499     buffer += element.Value();
01500 
01501     for (const TiXmlAttribute* attrib = firstAttribute; attrib; attrib
01502             = attrib->Next()) {
01503         buffer += " ";
01504         attrib->Print(0, 0, &buffer);
01505     }
01506 
01507     if (!element.FirstChild()) {
01508         buffer += " />";
01509         DoLineBreak();
01510     } else {
01511         buffer += ">";
01512         if (element.FirstChild()->ToText() && element.LastChild()
01513                 == element.FirstChild()
01514                 && element.FirstChild()->ToText()->CDATA() == false) {
01515             simpleTextPrint = true;
01516             // no DoLineBreak()!
01517         } else {
01518             DoLineBreak();
01519         }
01520     }
01521     ++depth;
01522     return true;
01523 }
01524 
01525 bool TiXmlPrinter::VisitExit(const TiXmlElement& element) {
01526     --depth;
01527     if (!element.FirstChild()) {
01528         // nothing.
01529     } else {
01530         if (simpleTextPrint) {
01531             simpleTextPrint = false;
01532         } else {
01533             DoIndent();
01534         }
01535         buffer += "</";
01536         buffer += element.Value();
01537         buffer += ">";
01538         DoLineBreak();
01539     }
01540     return true;
01541 }
01542 
01543 bool TiXmlPrinter::Visit(const TiXmlText& text) {
01544     if (text.CDATA()) {
01545         DoIndent();
01546         buffer += "<![CDATA[";
01547         buffer += text.Value();
01548         buffer += "]]>";
01549         DoLineBreak();
01550     } else if (simpleTextPrint) {
01551         TIXML_STRING str;
01552         TiXmlBase::EncodeString(text.ValueTStr(), &str);
01553         buffer += str;
01554     } else {
01555         DoIndent();
01556         TIXML_STRING str;
01557         TiXmlBase::EncodeString(text.ValueTStr(), &str);
01558         buffer += str;
01559         DoLineBreak();
01560     }
01561     return true;
01562 }
01563 
01564 bool TiXmlPrinter::Visit(const TiXmlDeclaration& declaration) {
01565     DoIndent();
01566     declaration.Print(0, 0, &buffer);
01567     DoLineBreak();
01568     return true;
01569 }
01570 
01571 bool TiXmlPrinter::Visit(const TiXmlComment& comment) {
01572     DoIndent();
01573     buffer += "<!--";
01574     buffer += comment.Value();
01575     buffer += "-->";
01576     DoLineBreak();
01577     return true;
01578 }
01579 
01580 bool TiXmlPrinter::Visit(const TiXmlUnknown& unknown) {
01581     DoIndent();
01582     buffer += "<";
01583     buffer += unknown.Value();
01584     buffer += ">";
01585     DoLineBreak();
01586     return true;
01587 }
01588 


appl
Author(s): petercai
autogenerated on Tue Jan 7 2014 11:02:29