ferencd@0: /* ferencd@0: www.sourceforge.net/projects/tinyxml ferencd@0: Original code by Lee Thomason (www.grinninglizard.com) ferencd@0: ferencd@0: This software is provided 'as-is', without any express or implied ferencd@0: warranty. In no event will the authors be held liable for any ferencd@0: damages arising from the use of this software. ferencd@0: ferencd@0: Permission is granted to anyone to use this software for any ferencd@0: purpose, including commercial applications, and to alter it and ferencd@0: redistribute it freely, subject to the following restrictions: ferencd@0: ferencd@0: 1. The origin of this software must not be misrepresented; you must ferencd@0: not claim that you wrote the original software. If you use this ferencd@0: software in a product, an acknowledgment in the product documentation ferencd@0: would be appreciated but is not required. ferencd@0: ferencd@0: 2. Altered source versions must be plainly marked as such, and ferencd@0: must not be misrepresented as being the original software. ferencd@0: ferencd@0: 3. This notice may not be removed or altered from any source ferencd@0: distribution. ferencd@0: */ ferencd@0: ferencd@0: ferencd@0: #ifndef TINYXML_INCLUDED ferencd@0: #define TINYXML_INCLUDED ferencd@0: ferencd@0: #ifdef _MSC_VER ferencd@0: #pragma warning( push ) ferencd@0: #pragma warning( disable : 4530 ) ferencd@0: #pragma warning( disable : 4786 ) ferencd@0: #endif ferencd@0: ferencd@0: #define TIXML_USE_STL ferencd@0: ferencd@0: ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: ferencd@0: // Help out windows: ferencd@0: #if defined( _DEBUG ) && !defined( DEBUG ) ferencd@0: #define DEBUG ferencd@0: #endif ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: #define TIXML_STRING std::string ferencd@0: #else ferencd@0: #include "tinystr.h" ferencd@0: #define TIXML_STRING TiXmlString ferencd@0: #endif ferencd@0: ferencd@0: // Deprecated library function hell. Compilers want to use the ferencd@0: // new safe versions. This probably doesn't fully address the problem, ferencd@0: // but it gets closer. There are too many compilers for me to fully ferencd@0: // test. If you get compilation troubles, undefine TIXML_SAFE ferencd@0: #define TIXML_SAFE ferencd@0: ferencd@0: #ifdef TIXML_SAFE ferencd@0: #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) ferencd@0: // Microsoft visual studio, version 2005 and higher. ferencd@0: #define TIXML_SNPRINTF _snprintf_s ferencd@0: #define TIXML_SSCANF sscanf_s ferencd@0: #elif defined(_MSC_VER) && (_MSC_VER >= 1200 ) ferencd@0: // Microsoft visual studio, version 6 and higher. ferencd@0: //#pragma message( "Using _sn* functions." ) ferencd@0: #define TIXML_SNPRINTF _snprintf ferencd@0: #define TIXML_SSCANF sscanf ferencd@0: #elif defined(__GNUC__) && (__GNUC__ >= 3 ) ferencd@0: // GCC version 3 and higher.s ferencd@0: //#warning( "Using sn* functions." ) ferencd@0: #define TIXML_SNPRINTF snprintf ferencd@0: #define TIXML_SSCANF sscanf ferencd@0: #else ferencd@0: #define TIXML_SNPRINTF snprintf ferencd@0: #define TIXML_SSCANF sscanf ferencd@0: #endif ferencd@0: #endif ferencd@0: ferencd@0: class TiXmlDocument; ferencd@0: class TiXmlElement; ferencd@0: class TiXmlComment; ferencd@0: class TiXmlUnknown; ferencd@0: class TiXmlAttribute; ferencd@0: class TiXmlText; ferencd@0: class TiXmlDeclaration; ferencd@0: class TiXmlParsingData; ferencd@0: ferencd@0: const int TIXML_MAJOR_VERSION = 2; ferencd@0: const int TIXML_MINOR_VERSION = 6; ferencd@0: const int TIXML_PATCH_VERSION = 2; ferencd@0: ferencd@0: /* Internal structure for tracking location of items ferencd@0: in the XML file. ferencd@0: */ ferencd@0: struct TiXmlCursor ferencd@0: { ferencd@0: TiXmlCursor() { Clear(); } ferencd@0: void Clear() { row = col = -1; } ferencd@0: ferencd@0: int row; // 0 based. ferencd@0: int col; // 0 based. ferencd@0: }; ferencd@0: ferencd@0: ferencd@0: /** ferencd@0: Implements the interface to the "Visitor pattern" (see the Accept() method.) ferencd@0: If you call the Accept() method, it requires being passed a TiXmlVisitor ferencd@0: class to handle callbacks. For nodes that contain other nodes (Document, Element) ferencd@0: you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves ferencd@0: are simply called with Visit(). ferencd@0: ferencd@0: If you return 'true' from a Visit method, recursive parsing will continue. If you return ferencd@0: false, no children of this node or its sibilings will be Visited. ferencd@0: ferencd@0: All flavors of Visit methods have a default implementation that returns 'true' (continue ferencd@0: visiting). You need to only override methods that are interesting to you. ferencd@0: ferencd@0: Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting. ferencd@0: ferencd@0: You should never change the document from a callback. ferencd@0: ferencd@0: @sa TiXmlNode::Accept() ferencd@0: */ ferencd@0: class TiXmlVisitor ferencd@0: { ferencd@0: public: ferencd@0: virtual ~TiXmlVisitor() {} ferencd@0: ferencd@0: /// Visit a document. ferencd@0: virtual bool VisitEnter( const TiXmlDocument& /*doc*/ ) { return true; } ferencd@0: /// Visit a document. ferencd@0: virtual bool VisitExit( const TiXmlDocument& /*doc*/ ) { return true; } ferencd@0: ferencd@0: /// Visit an element. ferencd@0: virtual bool VisitEnter( const TiXmlElement& /*element*/, const TiXmlAttribute* /*firstAttribute*/ ) { return true; } ferencd@0: /// Visit an element. ferencd@0: virtual bool VisitExit( const TiXmlElement& /*element*/ ) { return true; } ferencd@0: ferencd@0: /// Visit a declaration ferencd@0: virtual bool Visit( const TiXmlDeclaration& /*declaration*/ ) { return true; } ferencd@0: /// Visit a text node ferencd@0: virtual bool Visit( const TiXmlText& /*text*/ ) { return true; } ferencd@0: /// Visit a comment node ferencd@0: virtual bool Visit( const TiXmlComment& /*comment*/ ) { return true; } ferencd@0: /// Visit an unknown node ferencd@0: virtual bool Visit( const TiXmlUnknown& /*unknown*/ ) { return true; } ferencd@0: }; ferencd@0: ferencd@0: // Only used by Attribute::Query functions ferencd@0: enum ferencd@0: { ferencd@0: TIXML_SUCCESS, ferencd@0: TIXML_NO_ATTRIBUTE, ferencd@0: TIXML_WRONG_TYPE ferencd@0: }; ferencd@0: ferencd@0: ferencd@0: // Used by the parsing routines. ferencd@0: enum TiXmlEncoding ferencd@0: { ferencd@0: TIXML_ENCODING_UNKNOWN, ferencd@0: TIXML_ENCODING_UTF8, ferencd@0: TIXML_ENCODING_LEGACY ferencd@0: }; ferencd@0: ferencd@0: const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN; ferencd@0: ferencd@0: /** TiXmlBase is a base class for every class in TinyXml. ferencd@0: It does little except to establish that TinyXml classes ferencd@0: can be printed and provide some utility functions. ferencd@0: ferencd@0: In XML, the document and elements can contain ferencd@0: other elements and other types of nodes. ferencd@0: ferencd@0: @verbatim ferencd@0: A Document can contain: Element (container or leaf) ferencd@0: Comment (leaf) ferencd@0: Unknown (leaf) ferencd@0: Declaration( leaf ) ferencd@0: ferencd@0: An Element can contain: Element (container or leaf) ferencd@0: Text (leaf) ferencd@0: Attributes (not on tree) ferencd@0: Comment (leaf) ferencd@0: Unknown (leaf) ferencd@0: ferencd@0: A Decleration contains: Attributes (not on tree) ferencd@0: @endverbatim ferencd@0: */ ferencd@0: class TiXmlBase ferencd@0: { ferencd@0: friend class TiXmlNode; ferencd@0: friend class TiXmlElement; ferencd@0: friend class TiXmlDocument; ferencd@0: ferencd@0: public: ferencd@0: TiXmlBase() : userData(0) {} ferencd@0: virtual ~TiXmlBase() {} ferencd@0: ferencd@0: /** All TinyXml classes can print themselves to a filestream ferencd@0: or the string class (TiXmlString in non-STL mode, std::string ferencd@0: in STL mode.) Either or both cfile and str can be null. ferencd@0: ferencd@0: This is a formatted print, and will insert ferencd@0: tabs and newlines. ferencd@0: ferencd@0: (For an unformatted stream, use the << operator.) ferencd@0: */ ferencd@0: virtual void Print( FILE* cfile, int depth ) const = 0; ferencd@0: virtual void Print( std::string& , int depth ) const = 0; ferencd@0: ferencd@0: /** The world does not agree on whether white space should be kept or ferencd@0: not. In order to make everyone happy, these global, static functions ferencd@0: are provided to set whether or not TinyXml will condense all white space ferencd@0: into a single space or not. The default is to condense. Note changing this ferencd@0: value is not thread safe. ferencd@0: */ ferencd@0: static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; } ferencd@0: ferencd@0: /// Return the current white space setting. ferencd@0: static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; } ferencd@0: ferencd@0: /** Return the position, in the original source file, of this node or attribute. ferencd@0: The row and column are 1-based. (That is the first row and first column is ferencd@0: 1,1). If the returns values are 0 or less, then the parser does not have ferencd@0: a row and column value. ferencd@0: ferencd@0: Generally, the row and column value will be set when the TiXmlDocument::Load(), ferencd@0: TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set ferencd@0: when the DOM was created from operator>>. ferencd@0: ferencd@0: The values reflect the initial load. Once the DOM is modified programmatically ferencd@0: (by adding or changing nodes and attributes) the new values will NOT update to ferencd@0: reflect changes in the document. ferencd@0: ferencd@0: There is a minor performance cost to computing the row and column. Computation ferencd@0: can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value. ferencd@0: ferencd@0: @sa TiXmlDocument::SetTabSize() ferencd@0: */ ferencd@0: int Row() const { return location.row + 1; } ferencd@0: int Column() const { return location.col + 1; } ///< See Row() ferencd@0: ferencd@0: void SetUserData( void* user ) { userData = user; } ///< Set a pointer to arbitrary user data. ferencd@0: void* GetUserData() { return userData; } ///< Get a pointer to arbitrary user data. ferencd@0: const void* GetUserData() const { return userData; } ///< Get a pointer to arbitrary user data. ferencd@0: ferencd@0: // Table that returs, for a given lead byte, the total number of bytes ferencd@0: // in the UTF-8 sequence. ferencd@0: static const int utf8ByteTable[256]; ferencd@0: ferencd@0: virtual const char* Parse( const char* p, ferencd@0: TiXmlParsingData* data, ferencd@0: TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0; ferencd@0: ferencd@0: /** Expands entities in a string. Note this should not contian the tag's '<', '>', etc, ferencd@0: or they will be transformed into entities! ferencd@0: */ ferencd@0: static void EncodeString( const TIXML_STRING& str, TIXML_STRING* out ); ferencd@0: ferencd@0: enum ferencd@0: { ferencd@0: TIXML_NO_ERROR = 0, ferencd@0: TIXML_ERROR, ferencd@0: TIXML_ERROR_OPENING_FILE, ferencd@0: TIXML_ERROR_PARSING_ELEMENT, ferencd@0: TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, ferencd@0: TIXML_ERROR_READING_ELEMENT_VALUE, ferencd@0: TIXML_ERROR_READING_ATTRIBUTES, ferencd@0: TIXML_ERROR_PARSING_EMPTY, ferencd@0: TIXML_ERROR_READING_END_TAG, ferencd@0: TIXML_ERROR_PARSING_UNKNOWN, ferencd@0: TIXML_ERROR_PARSING_COMMENT, ferencd@0: TIXML_ERROR_PARSING_DECLARATION, ferencd@0: TIXML_ERROR_DOCUMENT_EMPTY, ferencd@0: TIXML_ERROR_EMBEDDED_NULL, ferencd@0: TIXML_ERROR_PARSING_CDATA, ferencd@0: TIXML_ERROR_DOCUMENT_TOP_ONLY, ferencd@0: ferencd@0: TIXML_ERROR_STRING_COUNT ferencd@0: }; ferencd@0: ferencd@0: protected: ferencd@0: ferencd@0: static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding ); ferencd@0: ferencd@0: inline static bool IsWhiteSpace( char c ) ferencd@0: { ferencd@0: return ( isspace( static_cast(c) ) || c == '\n' || c == '\r' ); ferencd@0: } ferencd@0: inline static bool IsWhiteSpace( int c ) ferencd@0: { ferencd@0: if ( c < 256 ) ferencd@0: return IsWhiteSpace( static_cast (c) ); ferencd@0: return false; // Again, only truly correct for English/Latin...but usually works. ferencd@0: } ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: static bool StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ); ferencd@0: static bool StreamTo( std::istream * in, int character, TIXML_STRING * tag ); ferencd@0: #endif ferencd@0: ferencd@0: /* Reads an XML name into the string provided. Returns ferencd@0: a pointer just past the last character of the name, ferencd@0: or 0 if the function has an error. ferencd@0: */ ferencd@0: static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding ); ferencd@0: ferencd@0: /* Reads text. Returns a pointer past the given end tag. ferencd@0: Wickedly complex options, but it keeps the (sensitive) code in one place. ferencd@0: */ ferencd@0: static const char* ReadText( const char* in, // where to start ferencd@0: TIXML_STRING* text, // the string read ferencd@0: bool ignoreWhiteSpace, // whether to keep the white space ferencd@0: const char* endTag, // what ends this text ferencd@0: bool ignoreCase, // whether to ignore case in the end tag ferencd@0: TiXmlEncoding encoding ); // the current encoding ferencd@0: ferencd@0: // If an entity has been found, transform it into a character. ferencd@0: static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding ); ferencd@0: ferencd@0: // Get a character, while interpreting entities. ferencd@0: // The length can be from 0 to 4 bytes. ferencd@0: inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding ) ferencd@0: { ferencd@0: assert( p ); ferencd@0: if ( encoding == TIXML_ENCODING_UTF8 ) ferencd@0: { ferencd@0: *length = utf8ByteTable[ *( reinterpret_cast(p)) ]; ferencd@0: assert( *length >= 0 && *length < 5 ); ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: *length = 1; ferencd@0: } ferencd@0: ferencd@0: if ( *length == 1 ) ferencd@0: { ferencd@0: if ( *p == '&' ) ferencd@0: return GetEntity( p, _value, length, encoding ); ferencd@0: *_value = *p; ferencd@0: return p+1; ferencd@0: } ferencd@0: else if ( *length ) ferencd@0: { ferencd@0: //strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe), ferencd@0: // and the null terminator isn't needed ferencd@0: for( int i=0; p[i] && i<*length; ++i ) { ferencd@0: _value[i] = p[i]; ferencd@0: } ferencd@0: return p + (*length); ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: // Not valid text. ferencd@0: return 0; ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: // Return true if the next characters in the stream are any of the endTag sequences. ferencd@0: // Ignore case only works for english, and should only be relied on when comparing ferencd@0: // to English words: StringEqual( p, "version", true ) is fine. ferencd@0: static bool StringEqual( const char* p, ferencd@0: const char* endTag, ferencd@0: bool ignoreCase, ferencd@0: TiXmlEncoding encoding ); ferencd@0: ferencd@0: static const char* errorString[ TIXML_ERROR_STRING_COUNT ]; ferencd@0: ferencd@0: TiXmlCursor location; ferencd@0: ferencd@0: /// Field containing a generic user pointer ferencd@0: void* userData; ferencd@0: ferencd@0: // None of these methods are reliable for any language except English. ferencd@0: // Good for approximation, not great for accuracy. ferencd@0: static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding ); ferencd@0: static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding ); ferencd@0: inline static int ToLower( int v, TiXmlEncoding encoding ) ferencd@0: { ferencd@0: if ( encoding == TIXML_ENCODING_UTF8 ) ferencd@0: { ferencd@0: if ( v < 128 ) return tolower( v ); ferencd@0: return v; ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: return tolower( v ); ferencd@0: } ferencd@0: } ferencd@0: static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); ferencd@0: ferencd@0: private: ferencd@0: TiXmlBase( const TiXmlBase& ); // not implemented. ferencd@0: void operator=( const TiXmlBase& base ); // not allowed. ferencd@0: ferencd@0: struct Entity ferencd@0: { ferencd@0: const char* str; ferencd@0: unsigned int strLength; ferencd@0: char chr; ferencd@0: }; ferencd@0: enum ferencd@0: { ferencd@0: NUM_ENTITY = 5, ferencd@0: MAX_ENTITY_LENGTH = 6 ferencd@0: ferencd@0: }; ferencd@0: static Entity entity[ NUM_ENTITY ]; ferencd@0: static bool condenseWhiteSpace; ferencd@0: }; ferencd@0: ferencd@0: ferencd@0: /** The parent class for everything in the Document Object Model. ferencd@0: (Except for attributes). ferencd@0: Nodes have siblings, a parent, and children. A node can be ferencd@0: in a document, or stand on its own. The type of a TiXmlNode ferencd@0: can be queried, and it can be cast to its more defined type. ferencd@0: */ ferencd@0: class TiXmlNode : public TiXmlBase ferencd@0: { ferencd@0: friend class TiXmlDocument; ferencd@0: friend class TiXmlElement; ferencd@0: ferencd@0: public: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: ferencd@0: /** An input stream operator, for every class. Tolerant of newlines and ferencd@0: formatting, but doesn't expect them. ferencd@0: */ ferencd@0: friend std::istream& operator >> (std::istream& in, TiXmlNode& base); ferencd@0: ferencd@0: /** An output stream operator, for every class. Note that this outputs ferencd@0: without any newlines or formatting, as opposed to Print(), which ferencd@0: includes tabs and new lines. ferencd@0: ferencd@0: The operator<< and operator>> are not completely symmetric. Writing ferencd@0: a node to a stream is very well defined. You'll get a nice stream ferencd@0: of output, without any extra whitespace or newlines. ferencd@0: ferencd@0: But reading is not as well defined. (As it always is.) If you create ferencd@0: a TiXmlElement (for example) and read that from an input stream, ferencd@0: the text needs to define an element or junk will result. This is ferencd@0: true of all input streams, but it's worth keeping in mind. ferencd@0: ferencd@0: A TiXmlDocument will read nodes until it reads a root element, and ferencd@0: all the children of that root element. ferencd@0: */ ferencd@0: friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base); ferencd@0: ferencd@0: /// Appends the XML node or attribute to a std::string. ferencd@0: friend std::string& operator<< (std::string& out, const TiXmlNode& base ); ferencd@0: ferencd@0: #endif ferencd@0: ferencd@0: /** The types of XML nodes supported by TinyXml. (All the ferencd@0: unsupported types are picked up by UNKNOWN.) ferencd@0: */ ferencd@0: enum NodeType ferencd@0: { ferencd@0: TINYXML_DOCUMENT, ferencd@0: TINYXML_ELEMENT, ferencd@0: TINYXML_COMMENT, ferencd@0: TINYXML_UNKNOWN, ferencd@0: TINYXML_TEXT, ferencd@0: TINYXML_DECLARATION, ferencd@0: TINYXML_TYPECOUNT ferencd@0: }; ferencd@0: ferencd@0: virtual ~TiXmlNode(); ferencd@0: ferencd@0: /** The meaning of 'value' changes for the specific type of ferencd@0: TiXmlNode. ferencd@0: @verbatim ferencd@0: Document: filename of the xml file ferencd@0: Element: name of the element ferencd@0: Comment: the comment text ferencd@0: Unknown: the tag contents ferencd@0: Text: the text string ferencd@0: @endverbatim ferencd@0: ferencd@0: The subclasses will wrap this function. ferencd@0: */ ferencd@0: const char *Value() const { return value.c_str (); } ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: /** Return Value() as a std::string. If you only use STL, ferencd@0: this is more efficient than calling Value(). ferencd@0: Only available in STL mode. ferencd@0: */ ferencd@0: const std::string& ValueStr() const { return value; } ferencd@0: #endif ferencd@0: ferencd@0: const TIXML_STRING& ValueTStr() const { return value; } ferencd@0: ferencd@0: /** Changes the value of the node. Defined as: ferencd@0: @verbatim ferencd@0: Document: filename of the xml file ferencd@0: Element: name of the element ferencd@0: Comment: the comment text ferencd@0: Unknown: the tag contents ferencd@0: Text: the text string ferencd@0: @endverbatim ferencd@0: */ ferencd@0: void SetValue(const char * _value) { value = _value;} ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: /// STL std::string form. ferencd@0: void SetValue( const std::string& _value ) { value = _value; } ferencd@0: #endif ferencd@0: ferencd@0: /// Delete all the children of this node. Does not affect 'this'. ferencd@0: void Clear(); ferencd@0: ferencd@0: /// One step up the DOM. ferencd@0: TiXmlNode* Parent() { return parent; } ferencd@0: const TiXmlNode* Parent() const { return parent; } ferencd@0: ferencd@0: const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children. ferencd@0: TiXmlNode* FirstChild() { return firstChild; } ferencd@0: const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found. ferencd@0: /// The first child of this node with the matching 'value'. Will be null if none found. ferencd@0: TiXmlNode* FirstChild( const char * _value ) { ferencd@0: // Call through to the const version - safe since nothing is changed. Exiting syntax: cast this to a const (always safe) ferencd@0: // call the method, cast the return back to non-const. ferencd@0: return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->FirstChild( _value )); ferencd@0: } ferencd@0: const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children. ferencd@0: TiXmlNode* LastChild() { return lastChild; } ferencd@0: ferencd@0: const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children. ferencd@0: TiXmlNode* LastChild( const char * _value ) { ferencd@0: return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->LastChild( _value )); ferencd@0: } ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form. ferencd@0: TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form. ferencd@0: const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form. ferencd@0: TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form. ferencd@0: #endif ferencd@0: ferencd@0: /** An alternate way to walk the children of a node. ferencd@0: One way to iterate over nodes is: ferencd@0: @verbatim ferencd@0: for( child = parent->FirstChild(); child; child = child->NextSibling() ) ferencd@0: @endverbatim ferencd@0: ferencd@0: IterateChildren does the same thing with the syntax: ferencd@0: @verbatim ferencd@0: child = 0; ferencd@0: while( child = parent->IterateChildren( child ) ) ferencd@0: @endverbatim ferencd@0: ferencd@0: IterateChildren takes the previous child as input and finds ferencd@0: the next one. If the previous child is null, it returns the ferencd@0: first. IterateChildren will return null when done. ferencd@0: */ ferencd@0: const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const; ferencd@0: TiXmlNode* IterateChildren( const TiXmlNode* previous ) { ferencd@0: return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( previous ) ); ferencd@0: } ferencd@0: ferencd@0: /// This flavor of IterateChildren searches for children with a particular 'value' ferencd@0: const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const; ferencd@0: TiXmlNode* IterateChildren( const char * _value, const TiXmlNode* previous ) { ferencd@0: return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( _value, previous ) ); ferencd@0: } ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. ferencd@0: TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. ferencd@0: #endif ferencd@0: ferencd@0: /** Add a new node related to this. Adds a child past the LastChild. ferencd@0: Returns a pointer to the new object or NULL if an error occured. ferencd@0: */ ferencd@0: TiXmlNode* InsertEndChild( const TiXmlNode& addThis ); ferencd@0: ferencd@0: ferencd@0: /** Add a new node related to this. Adds a child past the LastChild. ferencd@0: ferencd@0: NOTE: the node to be added is passed by pointer, and will be ferencd@0: henceforth owned (and deleted) by tinyXml. This method is efficient ferencd@0: and avoids an extra copy, but should be used with care as it ferencd@0: uses a different memory model than the other insert functions. ferencd@0: ferencd@0: @sa InsertEndChild ferencd@0: */ ferencd@0: TiXmlNode* LinkEndChild( TiXmlNode* addThis ); ferencd@0: ferencd@0: /** Add a new node related to this. Adds a child before the specified child. ferencd@0: Returns a pointer to the new object or NULL if an error occured. ferencd@0: */ ferencd@0: TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ); ferencd@0: ferencd@0: /** Add a new node related to this. Adds a child after the specified child. ferencd@0: Returns a pointer to the new object or NULL if an error occured. ferencd@0: */ ferencd@0: TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ); ferencd@0: ferencd@0: /** Replace a child of this node. ferencd@0: Returns a pointer to the new object or NULL if an error occured. ferencd@0: */ ferencd@0: TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ); ferencd@0: ferencd@0: /// Delete a child of this node. ferencd@0: bool RemoveChild( TiXmlNode* removeThis ); ferencd@0: ferencd@0: /// Navigate to a sibling node. ferencd@0: const TiXmlNode* PreviousSibling() const { return prev; } ferencd@0: TiXmlNode* PreviousSibling() { return prev; } ferencd@0: ferencd@0: /// Navigate to a sibling node. ferencd@0: const TiXmlNode* PreviousSibling( const char * ) const; ferencd@0: TiXmlNode* PreviousSibling( const char *_prev ) { ferencd@0: return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->PreviousSibling( _prev ) ); ferencd@0: } ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. ferencd@0: TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. ferencd@0: const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form. ferencd@0: TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form. ferencd@0: #endif ferencd@0: ferencd@0: /// Navigate to a sibling node. ferencd@0: const TiXmlNode* NextSibling() const { return next; } ferencd@0: TiXmlNode* NextSibling() { return next; } ferencd@0: ferencd@0: /// Navigate to a sibling node with the given 'value'. ferencd@0: const TiXmlNode* NextSibling( const char * ) const; ferencd@0: TiXmlNode* NextSibling( const char* _next ) { ferencd@0: return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->NextSibling( _next ) ); ferencd@0: } ferencd@0: ferencd@0: /** Convenience function to get through elements. ferencd@0: Calls NextSibling and ToElement. Will skip all non-Element ferencd@0: nodes. Returns 0 if there is not another element. ferencd@0: */ ferencd@0: const TiXmlElement* NextSiblingElement() const; ferencd@0: TiXmlElement* NextSiblingElement() { ferencd@0: return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement() ); ferencd@0: } ferencd@0: ferencd@0: /** Convenience function to get through elements. ferencd@0: Calls NextSibling and ToElement. Will skip all non-Element ferencd@0: nodes. Returns 0 if there is not another element. ferencd@0: */ ferencd@0: const TiXmlElement* NextSiblingElement( const char * ) const; ferencd@0: TiXmlElement* NextSiblingElement( const char *_next ) { ferencd@0: return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement( _next ) ); ferencd@0: } ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. ferencd@0: TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. ferencd@0: #endif ferencd@0: ferencd@0: /// Convenience function to get through elements. ferencd@0: const TiXmlElement* FirstChildElement() const; ferencd@0: TiXmlElement* FirstChildElement() { ferencd@0: return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement() ); ferencd@0: } ferencd@0: ferencd@0: /// Convenience function to get through elements. ferencd@0: const TiXmlElement* FirstChildElement( const char * _value ) const; ferencd@0: TiXmlElement* FirstChildElement( const char * _value ) { ferencd@0: return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement( _value ) ); ferencd@0: } ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. ferencd@0: TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. ferencd@0: #endif ferencd@0: ferencd@0: /** Query the type (as an enumerated value, above) of this node. ferencd@0: The possible types are: TINYXML_DOCUMENT, TINYXML_ELEMENT, TINYXML_COMMENT, ferencd@0: TINYXML_UNKNOWN, TINYXML_TEXT, and TINYXML_DECLARATION. ferencd@0: */ ferencd@0: int Type() const { return type; } ferencd@0: ferencd@0: /** Return a pointer to the Document this node lives in. ferencd@0: Returns null if not in a document. ferencd@0: */ ferencd@0: const TiXmlDocument* GetDocument() const; ferencd@0: TiXmlDocument* GetDocument() { ferencd@0: return const_cast< TiXmlDocument* >( (const_cast< const TiXmlNode* >(this))->GetDocument() ); ferencd@0: } ferencd@0: ferencd@0: /// Returns true if this node has no children. ferencd@0: bool NoChildren() const { return !firstChild; } ferencd@0: ferencd@0: virtual const TiXmlDocument* ToDocument() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. ferencd@0: virtual const TiXmlElement* ToElement() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. ferencd@0: virtual const TiXmlComment* ToComment() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. ferencd@0: virtual const TiXmlUnknown* ToUnknown() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. ferencd@0: virtual const TiXmlText* ToText() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. ferencd@0: virtual const TiXmlDeclaration* ToDeclaration() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. ferencd@0: ferencd@0: virtual TiXmlDocument* ToDocument() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. ferencd@0: virtual TiXmlElement* ToElement() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. ferencd@0: virtual TiXmlComment* ToComment() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. ferencd@0: virtual TiXmlUnknown* ToUnknown() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. ferencd@0: virtual TiXmlText* ToText() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. ferencd@0: virtual TiXmlDeclaration* ToDeclaration() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. ferencd@0: ferencd@0: /** Create an exact duplicate of this node and return it. The memory must be deleted ferencd@0: by the caller. ferencd@0: */ ferencd@0: virtual TiXmlNode* Clone() const = 0; ferencd@0: ferencd@0: /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the ferencd@0: XML tree will be conditionally visited and the host will be called back ferencd@0: via the TiXmlVisitor interface. ferencd@0: ferencd@0: This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse ferencd@0: the XML for the callbacks, so the performance of TinyXML is unchanged by using this ferencd@0: interface versus any other.) ferencd@0: ferencd@0: The interface has been based on ideas from: ferencd@0: ferencd@0: - http://www.saxproject.org/ ferencd@0: - http://c2.com/cgi/wiki?HierarchicalVisitorPattern ferencd@0: ferencd@0: Which are both good references for "visiting". ferencd@0: ferencd@0: An example of using Accept(): ferencd@0: @verbatim ferencd@0: TiXmlPrinter printer; ferencd@0: tinyxmlDoc.Accept( &printer ); ferencd@0: const char* xmlcstr = printer.CStr(); ferencd@0: @endverbatim ferencd@0: */ ferencd@0: virtual bool Accept( TiXmlVisitor* visitor ) const = 0; ferencd@0: ferencd@0: protected: ferencd@0: TiXmlNode( NodeType _type ); ferencd@0: ferencd@0: // Copy to the allocated object. Shared functionality between Clone, Copy constructor, ferencd@0: // and the assignment operator. ferencd@0: void CopyTo( TiXmlNode* target ) const; ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: // The real work of the input operator. ferencd@0: virtual void StreamIn( std::istream* in, TIXML_STRING* tag ) = 0; ferencd@0: #endif ferencd@0: ferencd@0: // Figure out what is at *p, and parse it. Returns null if it is not an xml node. ferencd@0: TiXmlNode* Identify( const char* start, TiXmlEncoding encoding ); ferencd@0: ferencd@0: TiXmlNode* parent; ferencd@0: NodeType type; ferencd@0: ferencd@0: TiXmlNode* firstChild; ferencd@0: TiXmlNode* lastChild; ferencd@0: ferencd@0: TIXML_STRING value; ferencd@0: ferencd@0: TiXmlNode* prev; ferencd@0: TiXmlNode* next; ferencd@0: ferencd@0: private: ferencd@0: TiXmlNode( const TiXmlNode& ); // not implemented. ferencd@0: void operator=( const TiXmlNode& base ); // not allowed. ferencd@0: }; ferencd@0: ferencd@0: ferencd@0: /** An attribute is a name-value pair. Elements have an arbitrary ferencd@0: number of attributes, each with a unique name. ferencd@0: ferencd@0: @note The attributes are not TiXmlNodes, since they are not ferencd@0: part of the tinyXML document object model. There are other ferencd@0: suggested ways to look at this problem. ferencd@0: */ ferencd@0: class TiXmlAttribute : public TiXmlBase ferencd@0: { ferencd@0: friend class TiXmlAttributeSet; ferencd@0: ferencd@0: public: ferencd@0: /// Construct an empty attribute. ferencd@0: TiXmlAttribute() : TiXmlBase() ferencd@0: { ferencd@0: document = 0; ferencd@0: prev = next = 0; ferencd@0: } ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: /// std::string constructor. ferencd@0: TiXmlAttribute( const std::string& _name, const std::string& _value ) ferencd@0: { ferencd@0: name = _name; ferencd@0: value = _value; ferencd@0: document = 0; ferencd@0: prev = next = 0; ferencd@0: } ferencd@0: #endif ferencd@0: ferencd@0: /// Construct an attribute with a name and value. ferencd@0: TiXmlAttribute( const char * _name, const char * _value ) ferencd@0: { ferencd@0: name = _name; ferencd@0: value = _value; ferencd@0: document = 0; ferencd@0: prev = next = 0; ferencd@0: } ferencd@0: ferencd@0: const char* Name() const { return name.c_str(); } ///< Return the name of this attribute. ferencd@0: const char* Value() const { return value.c_str(); } ///< Return the value of this attribute. ferencd@0: #ifdef TIXML_USE_STL ferencd@0: const std::string& ValueStr() const { return value; } ///< Return the value of this attribute. ferencd@0: #endif ferencd@0: int IntValue() const; ///< Return the value of this attribute, converted to an integer. ferencd@0: double DoubleValue() const; ///< Return the value of this attribute, converted to a double. ferencd@0: ferencd@0: // Get the tinyxml string representation ferencd@0: const TIXML_STRING& NameTStr() const { return name; } ferencd@0: ferencd@0: /** QueryIntValue examines the value string. It is an alternative to the ferencd@0: IntValue() method with richer error checking. ferencd@0: If the value is an integer, it is stored in 'value' and ferencd@0: the call returns TIXML_SUCCESS. If it is not ferencd@0: an integer, it returns TIXML_WRONG_TYPE. ferencd@0: ferencd@0: A specialized but useful call. Note that for success it returns 0, ferencd@0: which is the opposite of almost all other TinyXml calls. ferencd@0: */ ferencd@0: int QueryIntValue( int* _value ) const; ferencd@0: /// QueryDoubleValue examines the value string. See QueryIntValue(). ferencd@0: int QueryDoubleValue( double* _value ) const; ferencd@0: ferencd@0: void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute. ferencd@0: void SetValue( const char* _value ) { value = _value; } ///< Set the value. ferencd@0: ferencd@0: void SetIntValue( int _value ); ///< Set the value from an integer. ferencd@0: void SetDoubleValue( double _value ); ///< Set the value from a double. ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: /// STL std::string form. ferencd@0: void SetName( const std::string& _name ) { name = _name; } ferencd@0: /// STL std::string form. ferencd@0: void SetValue( const std::string& _value ) { value = _value; } ferencd@0: #endif ferencd@0: ferencd@0: /// Get the next sibling attribute in the DOM. Returns null at end. ferencd@0: const TiXmlAttribute* Next() const; ferencd@0: TiXmlAttribute* Next() { ferencd@0: return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Next() ); ferencd@0: } ferencd@0: ferencd@0: /// Get the previous sibling attribute in the DOM. Returns null at beginning. ferencd@0: const TiXmlAttribute* Previous() const; ferencd@0: TiXmlAttribute* Previous() { ferencd@0: return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Previous() ); ferencd@0: } ferencd@0: ferencd@0: bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; } ferencd@0: bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; } ferencd@0: bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; } ferencd@0: ferencd@0: /* Attribute parsing starts: first letter of the name ferencd@0: returns: the next char after the value end quote ferencd@0: */ ferencd@0: virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); ferencd@0: ferencd@0: // Prints this Attribute to a FILE stream. ferencd@0: virtual void Print( FILE* cfile, int depth ) const { ferencd@0: Print( cfile, depth, 0 ); ferencd@0: } ferencd@0: void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; ferencd@0: ferencd@0: virtual void Print( std::string&, int depth ) const; ferencd@0: ferencd@0: // [internal use] ferencd@0: // Set the document pointer so the attribute can report errors. ferencd@0: void SetDocument( TiXmlDocument* doc ) { document = doc; } ferencd@0: ferencd@0: private: ferencd@0: TiXmlAttribute( const TiXmlAttribute& ); // not implemented. ferencd@0: void operator=( const TiXmlAttribute& base ); // not allowed. ferencd@0: ferencd@0: TiXmlDocument* document; // A pointer back to a document, for error reporting. ferencd@0: TIXML_STRING name; ferencd@0: TIXML_STRING value; ferencd@0: TiXmlAttribute* prev; ferencd@0: TiXmlAttribute* next; ferencd@0: }; ferencd@0: ferencd@0: ferencd@0: /* A class used to manage a group of attributes. ferencd@0: It is only used internally, both by the ELEMENT and the DECLARATION. ferencd@0: ferencd@0: The set can be changed transparent to the Element and Declaration ferencd@0: classes that use it, but NOT transparent to the Attribute ferencd@0: which has to implement a next() and previous() method. Which makes ferencd@0: it a bit problematic and prevents the use of STL. ferencd@0: ferencd@0: This version is implemented with circular lists because: ferencd@0: - I like circular lists ferencd@0: - it demonstrates some independence from the (typical) doubly linked list. ferencd@0: */ ferencd@0: class TiXmlAttributeSet ferencd@0: { ferencd@0: public: ferencd@0: TiXmlAttributeSet(); ferencd@0: ~TiXmlAttributeSet(); ferencd@0: ferencd@0: void Add( TiXmlAttribute* attribute ); ferencd@0: void Remove( TiXmlAttribute* attribute ); ferencd@0: ferencd@0: const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } ferencd@0: TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } ferencd@0: const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } ferencd@0: TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } ferencd@0: ferencd@0: TiXmlAttribute* Find( const char* _name ) const; ferencd@0: TiXmlAttribute* FindOrCreate( const char* _name ); ferencd@0: ferencd@0: # ifdef TIXML_USE_STL ferencd@0: TiXmlAttribute* Find( const std::string& _name ) const; ferencd@0: TiXmlAttribute* FindOrCreate( const std::string& _name ); ferencd@0: # endif ferencd@0: ferencd@0: ferencd@0: private: ferencd@0: //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element), ferencd@0: //*ME: this class must be also use a hidden/disabled copy-constructor !!! ferencd@0: TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed ferencd@0: void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute) ferencd@0: ferencd@0: TiXmlAttribute sentinel; ferencd@0: }; ferencd@0: ferencd@0: ferencd@0: /** The element is a container class. It has a value, the element name, ferencd@0: and can contain other elements, text, comments, and unknowns. ferencd@0: Elements also contain an arbitrary number of attributes. ferencd@0: */ ferencd@0: class TiXmlElement : public TiXmlNode ferencd@0: { ferencd@0: public: ferencd@0: /// Construct an element. ferencd@0: TiXmlElement (const char * in_value); ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: /// std::string constructor. ferencd@0: TiXmlElement( const std::string& _value ); ferencd@0: #endif ferencd@0: ferencd@0: TiXmlElement( const TiXmlElement& ); ferencd@0: ferencd@0: TiXmlElement& operator=( const TiXmlElement& base ); ferencd@0: ferencd@0: virtual ~TiXmlElement(); ferencd@0: ferencd@0: /** Given an attribute name, Attribute() returns the value ferencd@0: for the attribute of that name, or null if none exists. ferencd@0: */ ferencd@0: const char* Attribute( const char* name ) const; ferencd@0: ferencd@0: /** Given an attribute name, Attribute() returns the value ferencd@0: for the attribute of that name, or null if none exists. ferencd@0: If the attribute exists and can be converted to an integer, ferencd@0: the integer value will be put in the return 'i', if 'i' ferencd@0: is non-null. ferencd@0: */ ferencd@0: const char* Attribute( const char* name, int* i ) const; ferencd@0: ferencd@0: /** Given an attribute name, Attribute() returns the value ferencd@0: for the attribute of that name, or null if none exists. ferencd@0: If the attribute exists and can be converted to an double, ferencd@0: the double value will be put in the return 'd', if 'd' ferencd@0: is non-null. ferencd@0: */ ferencd@0: const char* Attribute( const char* name, double* d ) const; ferencd@0: ferencd@0: /** QueryIntAttribute examines the attribute - it is an alternative to the ferencd@0: Attribute() method with richer error checking. ferencd@0: If the attribute is an integer, it is stored in 'value' and ferencd@0: the call returns TIXML_SUCCESS. If it is not ferencd@0: an integer, it returns TIXML_WRONG_TYPE. If the attribute ferencd@0: does not exist, then TIXML_NO_ATTRIBUTE is returned. ferencd@0: */ ferencd@0: int QueryIntAttribute( const char* name, int* _value ) const; ferencd@0: /// QueryUnsignedAttribute examines the attribute - see QueryIntAttribute(). ferencd@0: int QueryUnsignedAttribute( const char* name, unsigned* _value ) const; ferencd@0: /** QueryBoolAttribute examines the attribute - see QueryIntAttribute(). ferencd@0: Note that '1', 'true', or 'yes' are considered true, while '0', 'false' ferencd@0: and 'no' are considered false. ferencd@0: */ ferencd@0: int QueryBoolAttribute( const char* name, bool* _value ) const; ferencd@0: /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute(). ferencd@0: int QueryDoubleAttribute( const char* name, double* _value ) const; ferencd@0: /// QueryFloatAttribute examines the attribute - see QueryIntAttribute(). ferencd@0: int QueryFloatAttribute( const char* name, float* _value ) const { ferencd@0: double d; ferencd@0: int result = QueryDoubleAttribute( name, &d ); ferencd@0: if ( result == TIXML_SUCCESS ) { ferencd@0: *_value = static_cast(d); ferencd@0: } ferencd@0: return result; ferencd@0: } ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: /// QueryStringAttribute examines the attribute - see QueryIntAttribute(). ferencd@0: int QueryStringAttribute( const char* name, std::string* _value ) const { ferencd@0: const char* cstr = Attribute( name ); ferencd@0: if ( cstr ) { ferencd@0: *_value = std::string( cstr ); ferencd@0: return TIXML_SUCCESS; ferencd@0: } ferencd@0: return TIXML_NO_ATTRIBUTE; ferencd@0: } ferencd@0: ferencd@0: /** Template form of the attribute query which will try to read the ferencd@0: attribute into the specified type. Very easy, very powerful, but ferencd@0: be careful to make sure to call this with the correct type. ferencd@0: ferencd@0: NOTE: This method doesn't work correctly for 'string' types that contain spaces. ferencd@0: ferencd@0: @return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE ferencd@0: */ ferencd@0: template< typename T > int QueryValueAttribute( const std::string& name, T* outValue ) const ferencd@0: { ferencd@0: const TiXmlAttribute* node = attributeSet.Find( name ); ferencd@0: if ( !node ) ferencd@0: return TIXML_NO_ATTRIBUTE; ferencd@0: ferencd@0: std::stringstream sstream( node->ValueStr() ); ferencd@0: sstream >> *outValue; ferencd@0: if ( !sstream.fail() ) ferencd@0: return TIXML_SUCCESS; ferencd@0: return TIXML_WRONG_TYPE; ferencd@0: } ferencd@0: ferencd@0: int QueryValueAttribute( const std::string& name, std::string* outValue ) const ferencd@0: { ferencd@0: const TiXmlAttribute* node = attributeSet.Find( name ); ferencd@0: if ( !node ) ferencd@0: return TIXML_NO_ATTRIBUTE; ferencd@0: *outValue = node->ValueStr(); ferencd@0: return TIXML_SUCCESS; ferencd@0: } ferencd@0: #endif ferencd@0: ferencd@0: /** Sets an attribute of name to a given value. The attribute ferencd@0: will be created if it does not exist, or changed if it does. ferencd@0: */ ferencd@0: void SetAttribute( const char* name, const char * _value ); ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: const std::string* Attribute( const std::string& name ) const; ferencd@0: const std::string* Attribute( const std::string& name, int* i ) const; ferencd@0: const std::string* Attribute( const std::string& name, double* d ) const; ferencd@0: int QueryIntAttribute( const std::string& name, int* _value ) const; ferencd@0: int QueryDoubleAttribute( const std::string& name, double* _value ) const; ferencd@0: ferencd@0: /// STL std::string form. ferencd@0: void SetAttribute( const std::string& name, const std::string& _value ); ferencd@0: ///< STL std::string form. ferencd@0: void SetAttribute( const std::string& name, int _value ); ferencd@0: ///< STL std::string form. ferencd@0: void SetDoubleAttribute( const std::string& name, double value ); ferencd@0: #endif ferencd@0: ferencd@0: /** Sets an attribute of name to a given value. The attribute ferencd@0: will be created if it does not exist, or changed if it does. ferencd@0: */ ferencd@0: void SetAttribute( const char * name, int value ); ferencd@0: ferencd@0: /** Sets an attribute of name to a given value. The attribute ferencd@0: will be created if it does not exist, or changed if it does. ferencd@0: */ ferencd@0: void SetDoubleAttribute( const char * name, double value ); ferencd@0: ferencd@0: /** Deletes an attribute with the given name. ferencd@0: */ ferencd@0: void RemoveAttribute( const char * name ); ferencd@0: #ifdef TIXML_USE_STL ferencd@0: void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form. ferencd@0: #endif ferencd@0: ferencd@0: const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element. ferencd@0: TiXmlAttribute* FirstAttribute() { return attributeSet.First(); } ferencd@0: const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element. ferencd@0: TiXmlAttribute* LastAttribute() { return attributeSet.Last(); } ferencd@0: ferencd@0: /** Convenience function for easy access to the text inside an element. Although easy ferencd@0: and concise, GetText() is limited compared to getting the TiXmlText child ferencd@0: and accessing it directly. ferencd@0: ferencd@0: If the first child of 'this' is a TiXmlText, the GetText() ferencd@0: returns the character string of the Text node, else null is returned. ferencd@0: ferencd@0: This is a convenient method for getting the text of simple contained text: ferencd@0: @verbatim ferencd@0: This is text ferencd@0: const char* str = fooElement->GetText(); ferencd@0: @endverbatim ferencd@0: ferencd@0: 'str' will be a pointer to "This is text". ferencd@0: ferencd@0: Note that this function can be misleading. If the element foo was created from ferencd@0: this XML: ferencd@0: @verbatim ferencd@0: This is text ferencd@0: @endverbatim ferencd@0: ferencd@0: then the value of str would be null. The first child node isn't a text node, it is ferencd@0: another element. From this XML: ferencd@0: @verbatim ferencd@0: This is text ferencd@0: @endverbatim ferencd@0: GetText() will return "This is ". ferencd@0: ferencd@0: WARNING: GetText() accesses a child node - don't become confused with the ferencd@0: similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are ferencd@0: safe type casts on the referenced node. ferencd@0: */ ferencd@0: const char* GetText() const; ferencd@0: ferencd@0: /// Creates a new Element and returns it - the returned element is a copy. ferencd@0: virtual TiXmlNode* Clone() const; ferencd@0: // Print the Element to a FILE stream. ferencd@0: virtual void Print( FILE* cfile, int depth ) const; ferencd@0: virtual void Print(std::string&target, int depth ) const; ferencd@0: ferencd@0: /* Attribtue parsing starts: next char past '<' ferencd@0: returns: next char past '>' ferencd@0: */ ferencd@0: virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); ferencd@0: ferencd@0: virtual const TiXmlElement* ToElement() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. ferencd@0: virtual TiXmlElement* ToElement() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. ferencd@0: ferencd@0: /** Walk the XML tree visiting this node and all of its children. ferencd@0: */ ferencd@0: virtual bool Accept( TiXmlVisitor* visitor ) const; ferencd@0: ferencd@0: protected: ferencd@0: ferencd@0: void CopyTo( TiXmlElement* target ) const; ferencd@0: void ClearThis(); // like clear, but initializes 'this' object as well ferencd@0: ferencd@0: // Used to be public [internal use] ferencd@0: #ifdef TIXML_USE_STL ferencd@0: virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); ferencd@0: #endif ferencd@0: /* [internal use] ferencd@0: Reads the "value" of the element -- another element, or text. ferencd@0: This should terminate with the current end tag. ferencd@0: */ ferencd@0: const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding ); ferencd@0: ferencd@0: private: ferencd@0: TiXmlAttributeSet attributeSet; ferencd@0: }; ferencd@0: ferencd@0: ferencd@0: /** An XML comment. ferencd@0: */ ferencd@0: class TiXmlComment : public TiXmlNode ferencd@0: { ferencd@0: public: ferencd@0: /// Constructs an empty comment. ferencd@0: TiXmlComment() : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) {} ferencd@0: /// Construct a comment from text. ferencd@0: TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) { ferencd@0: SetValue( _value ); ferencd@0: } ferencd@0: TiXmlComment( const TiXmlComment& ); ferencd@0: TiXmlComment& operator=( const TiXmlComment& base ); ferencd@0: ferencd@0: virtual ~TiXmlComment() {} ferencd@0: ferencd@0: /// Returns a copy of this Comment. ferencd@0: virtual TiXmlNode* Clone() const; ferencd@0: // Write this Comment to a FILE stream. ferencd@0: virtual void Print( FILE* cfile, int depth ) const; ferencd@0: virtual void Print( std::string& target, int depth ) const; ferencd@0: ferencd@0: /* Attribtue parsing starts: at the ! of the !-- ferencd@0: returns: next char past '>' ferencd@0: */ ferencd@0: virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); ferencd@0: ferencd@0: virtual const TiXmlComment* ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. ferencd@0: virtual TiXmlComment* ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. ferencd@0: ferencd@0: /** Walk the XML tree visiting this node and all of its children. ferencd@0: */ ferencd@0: virtual bool Accept( TiXmlVisitor* visitor ) const; ferencd@0: ferencd@0: protected: ferencd@0: void CopyTo( TiXmlComment* target ) const; ferencd@0: ferencd@0: // used to be public ferencd@0: #ifdef TIXML_USE_STL ferencd@0: virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); ferencd@0: #endif ferencd@0: // virtual void StreamOut( TIXML_OSTREAM * out ) const; ferencd@0: ferencd@0: private: ferencd@0: ferencd@0: }; ferencd@0: ferencd@0: ferencd@0: /** XML text. A text node can have 2 ways to output the next. "normal" output ferencd@0: and CDATA. It will default to the mode it was parsed from the XML file and ferencd@0: you generally want to leave it alone, but you can change the output mode with ferencd@0: SetCDATA() and query it with CDATA(). ferencd@0: */ ferencd@0: class TiXmlText : public TiXmlNode ferencd@0: { ferencd@0: friend class TiXmlElement; ferencd@0: public: ferencd@0: /** Constructor for text element. By default, it is treated as ferencd@0: normal, encoded text. If you want it be output as a CDATA text ferencd@0: element, set the parameter _cdata to 'true' ferencd@0: */ ferencd@0: TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) ferencd@0: { ferencd@0: SetValue( initValue ); ferencd@0: cdata = false; ferencd@0: } ferencd@0: virtual ~TiXmlText() {} ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: /// Constructor. ferencd@0: TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) ferencd@0: { ferencd@0: SetValue( initValue ); ferencd@0: cdata = false; ferencd@0: } ferencd@0: #endif ferencd@0: ferencd@0: TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TINYXML_TEXT ) { copy.CopyTo( this ); } ferencd@0: TiXmlText& operator=( const TiXmlText& base ) { base.CopyTo( this ); return *this; } ferencd@0: ferencd@0: // Write this text object to a FILE stream. ferencd@0: virtual void Print( FILE* cfile, int depth ) const; ferencd@0: void Print(std::string& target, int depth ) const; ferencd@0: ferencd@0: /// Queries whether this represents text using a CDATA section. ferencd@0: bool CDATA() const { return cdata; } ferencd@0: /// Turns on or off a CDATA representation of text. ferencd@0: void SetCDATA( bool _cdata ) { cdata = _cdata; } ferencd@0: ferencd@0: virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); ferencd@0: ferencd@0: virtual const TiXmlText* ToText() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. ferencd@0: virtual TiXmlText* ToText() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. ferencd@0: ferencd@0: /** Walk the XML tree visiting this node and all of its children. ferencd@0: */ ferencd@0: virtual bool Accept( TiXmlVisitor* content ) const; ferencd@0: ferencd@0: protected : ferencd@0: /// [internal use] Creates a new Element and returns it. ferencd@0: virtual TiXmlNode* Clone() const; ferencd@0: void CopyTo( TiXmlText* target ) const; ferencd@0: ferencd@0: bool Blank() const; // returns true if all white space and new lines ferencd@0: // [internal use] ferencd@0: #ifdef TIXML_USE_STL ferencd@0: virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); ferencd@0: #endif ferencd@0: ferencd@0: private: ferencd@0: bool cdata; // true if this should be input and output as a CDATA style text element ferencd@0: }; ferencd@0: ferencd@0: ferencd@0: /** In correct XML the declaration is the first entry in the file. ferencd@0: @verbatim ferencd@0: ferencd@0: @endverbatim ferencd@0: ferencd@0: TinyXml will happily read or write files without a declaration, ferencd@0: however. There are 3 possible attributes to the declaration: ferencd@0: version, encoding, and standalone. ferencd@0: ferencd@0: Note: In this version of the code, the attributes are ferencd@0: handled as special cases, not generic attributes, simply ferencd@0: because there can only be at most 3 and they are always the same. ferencd@0: */ ferencd@0: class TiXmlDeclaration : public TiXmlNode ferencd@0: { ferencd@0: public: ferencd@0: /// Construct an empty declaration. ferencd@0: TiXmlDeclaration() : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) {} ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: /// Constructor. ferencd@0: TiXmlDeclaration( const std::string& _version, ferencd@0: const std::string& _encoding, ferencd@0: const std::string& _standalone ); ferencd@0: #endif ferencd@0: ferencd@0: /// Construct. ferencd@0: TiXmlDeclaration( const char* _version, ferencd@0: const char* _encoding, ferencd@0: const char* _standalone ); ferencd@0: ferencd@0: TiXmlDeclaration( const TiXmlDeclaration& copy ); ferencd@0: TiXmlDeclaration& operator=( const TiXmlDeclaration& copy ); ferencd@0: ferencd@0: virtual ~TiXmlDeclaration() {} ferencd@0: ferencd@0: /// Version. Will return an empty string if none was found. ferencd@0: const char *Version() const { return version.c_str (); } ferencd@0: /// Encoding. Will return an empty string if none was found. ferencd@0: const char *Encoding() const { return encoding.c_str (); } ferencd@0: /// Is this a standalone document? ferencd@0: const char *Standalone() const { return standalone.c_str (); } ferencd@0: ferencd@0: /// Creates a copy of this Declaration and returns it. ferencd@0: virtual TiXmlNode* Clone() const; ferencd@0: // Print this declaration to a FILE stream. ferencd@0: virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; ferencd@0: virtual void Print( FILE* cfile, int depth ) const { ferencd@0: Print( cfile, depth, 0 ); ferencd@0: } ferencd@0: void Print( std::string& target, int /*depth*/) const; ferencd@0: ferencd@0: virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); ferencd@0: ferencd@0: virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. ferencd@0: virtual TiXmlDeclaration* ToDeclaration() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. ferencd@0: ferencd@0: /** Walk the XML tree visiting this node and all of its children. ferencd@0: */ ferencd@0: virtual bool Accept( TiXmlVisitor* visitor ) const; ferencd@0: ferencd@0: protected: ferencd@0: void CopyTo( TiXmlDeclaration* target ) const; ferencd@0: // used to be public ferencd@0: #ifdef TIXML_USE_STL ferencd@0: virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); ferencd@0: #endif ferencd@0: ferencd@0: private: ferencd@0: ferencd@0: TIXML_STRING version; ferencd@0: TIXML_STRING encoding; ferencd@0: TIXML_STRING standalone; ferencd@0: }; ferencd@0: ferencd@0: ferencd@0: /** Any tag that tinyXml doesn't recognize is saved as an ferencd@0: unknown. It is a tag of text, but should not be modified. ferencd@0: It will be written back to the XML, unchanged, when the file ferencd@0: is saved. ferencd@0: ferencd@0: DTD tags get thrown into TiXmlUnknowns. ferencd@0: */ ferencd@0: class TiXmlUnknown : public TiXmlNode ferencd@0: { ferencd@0: public: ferencd@0: TiXmlUnknown() : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) {} ferencd@0: virtual ~TiXmlUnknown() {} ferencd@0: ferencd@0: TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) { copy.CopyTo( this ); } ferencd@0: TiXmlUnknown& operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); return *this; } ferencd@0: ferencd@0: /// Creates a copy of this Unknown and returns it. ferencd@0: virtual TiXmlNode* Clone() const; ferencd@0: // Print this Unknown to a FILE stream. ferencd@0: virtual void Print( FILE* cfile, int depth ) const; ferencd@0: virtual void Print( std::string& target, int depth ) const; ferencd@0: ferencd@0: ferencd@0: virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); ferencd@0: ferencd@0: virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. ferencd@0: virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. ferencd@0: ferencd@0: /** Walk the XML tree visiting this node and all of its children. ferencd@0: */ ferencd@0: virtual bool Accept( TiXmlVisitor* content ) const; ferencd@0: ferencd@0: protected: ferencd@0: void CopyTo( TiXmlUnknown* target ) const; ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); ferencd@0: #endif ferencd@0: ferencd@0: private: ferencd@0: ferencd@0: }; ferencd@0: ferencd@0: ferencd@0: /** Always the top level node. A document binds together all the ferencd@0: XML pieces. It can be saved, loaded, and printed to the screen. ferencd@0: The 'value' of a document node is the xml file name. ferencd@0: */ ferencd@0: class TiXmlDocument : public TiXmlNode ferencd@0: { ferencd@0: public: ferencd@0: /// Create an empty document, that has no name. ferencd@0: TiXmlDocument(); ferencd@0: /// Create a document with a name. The name of the document is also the filename of the xml. ferencd@0: TiXmlDocument( const char * documentName ); ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: /// Constructor. ferencd@0: TiXmlDocument( const std::string& documentName ); ferencd@0: #endif ferencd@0: ferencd@0: TiXmlDocument( const TiXmlDocument& copy ); ferencd@0: TiXmlDocument& operator=( const TiXmlDocument& copy ); ferencd@0: ferencd@0: virtual ~TiXmlDocument() {} ferencd@0: ferencd@0: /** Load a file using the current document value. ferencd@0: Returns true if successful. Will delete any existing ferencd@0: document data before loading. ferencd@0: */ ferencd@0: bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); ferencd@0: /// Save a file using the current document value. Returns true if successful. ferencd@0: bool SaveFile() const; ferencd@0: /// Load a file using the given filename. Returns true if successful. ferencd@0: bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); ferencd@0: /// Save a file using the given filename. Returns true if successful. ferencd@0: bool SaveFile( const char * filename ) const; ferencd@0: /** Load a file using the given FILE*. Returns true if successful. Note that this method ferencd@0: doesn't stream - the entire object pointed at by the FILE* ferencd@0: will be interpreted as an XML file. TinyXML doesn't stream in XML from the current ferencd@0: file location. Streaming may be added in the future. ferencd@0: */ ferencd@0: bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); ferencd@0: /// Save a file using the given FILE*. Returns true if successful. ferencd@0: bool SaveFile( FILE* ) const; ferencd@0: // loads and parses the buffer from an in-memory buffer ferencd@0: bool FromMemory(const char* source, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version. ferencd@0: { ferencd@0: return LoadFile( filename.c_str(), encoding ); ferencd@0: } ferencd@0: bool SaveFile( const std::string& filename ) const ///< STL std::string version. ferencd@0: { ferencd@0: return SaveFile( filename.c_str() ); ferencd@0: } ferencd@0: #endif ferencd@0: ferencd@0: /** Parse the given null terminated block of xml data. Passing in an encoding to this ferencd@0: method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml ferencd@0: to use that encoding, regardless of what TinyXml might otherwise try to detect. ferencd@0: */ ferencd@0: virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); ferencd@0: ferencd@0: /** Get the root element -- the only top level element -- of the document. ferencd@0: In well formed XML, there should only be one. TinyXml is tolerant of ferencd@0: multiple elements at the document level. ferencd@0: */ ferencd@0: const TiXmlElement* RootElement() const { return FirstChildElement(); } ferencd@0: TiXmlElement* RootElement() { return FirstChildElement(); } ferencd@0: ferencd@0: /** If an error occurs, Error will be set to true. Also, ferencd@0: - The ErrorId() will contain the integer identifier of the error (not generally useful) ferencd@0: - The ErrorDesc() method will return the name of the error. (very useful) ferencd@0: - The ErrorRow() and ErrorCol() will return the location of the error (if known) ferencd@0: */ ferencd@0: bool Error() const { return error; } ferencd@0: ferencd@0: /// Contains a textual (english) description of the error if one occurs. ferencd@0: const char * ErrorDesc() const { return errorDesc.c_str (); } ferencd@0: ferencd@0: /** Generally, you probably want the error string ( ErrorDesc() ). But if you ferencd@0: prefer the ErrorId, this function will fetch it. ferencd@0: */ ferencd@0: int ErrorId() const { return errorId; } ferencd@0: ferencd@0: /** Returns the location (if known) of the error. The first column is column 1, ferencd@0: and the first row is row 1. A value of 0 means the row and column wasn't applicable ferencd@0: (memory errors, for example, have no row/column) or the parser lost the error. (An ferencd@0: error in the error reporting, in that case.) ferencd@0: ferencd@0: @sa SetTabSize, Row, Column ferencd@0: */ ferencd@0: int ErrorRow() const { return errorLocation.row+1; } ferencd@0: int ErrorCol() const { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow() ferencd@0: ferencd@0: /** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol()) ferencd@0: to report the correct values for row and column. It does not change the output ferencd@0: or input in any way. ferencd@0: ferencd@0: By calling this method, with a tab size ferencd@0: greater than 0, the row and column of each node and attribute is stored ferencd@0: when the file is loaded. Very useful for tracking the DOM back in to ferencd@0: the source file. ferencd@0: ferencd@0: The tab size is required for calculating the location of nodes. If not ferencd@0: set, the default of 4 is used. The tabsize is set per document. Setting ferencd@0: the tabsize to 0 disables row/column tracking. ferencd@0: ferencd@0: Note that row and column tracking is not supported when using operator>>. ferencd@0: ferencd@0: The tab size needs to be enabled before the parse or load. Correct usage: ferencd@0: @verbatim ferencd@0: TiXmlDocument doc; ferencd@0: doc.SetTabSize( 8 ); ferencd@0: doc.Load( "myfile.xml" ); ferencd@0: @endverbatim ferencd@0: ferencd@0: @sa Row, Column ferencd@0: */ ferencd@0: void SetTabSize( int _tabsize ) { tabsize = _tabsize; } ferencd@0: ferencd@0: int TabSize() const { return tabsize; } ferencd@0: ferencd@0: /** If you have handled the error, it can be reset with this call. The error ferencd@0: state is automatically cleared if you Parse a new XML block. ferencd@0: */ ferencd@0: void ClearError() { error = false; ferencd@0: errorId = 0; ferencd@0: errorDesc = ""; ferencd@0: errorLocation.row = errorLocation.col = 0; ferencd@0: //errorLocation.last = 0; ferencd@0: } ferencd@0: ferencd@0: /** Write the document to standard out using formatted printing ("pretty print"). */ ferencd@0: void Print() const { Print( stdout, 0 ); } ferencd@0: ferencd@0: /* Write the document to a string using formatted printing ("pretty print"). This ferencd@0: will allocate a character array (new char[]) and return it as a pointer. The ferencd@0: calling code pust call delete[] on the return char* to avoid a memory leak. ferencd@0: */ ferencd@0: //char* PrintToMemory() const; ferencd@0: ferencd@0: /// Print this Document to a FILE stream. ferencd@0: virtual void Print( FILE* cfile, int depth = 0 ) const; ferencd@0: virtual void Print( std::string &, int depth = 0 ) const; ferencd@0: // [internal use] ferencd@0: void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding ); ferencd@0: ferencd@0: virtual const TiXmlDocument* ToDocument() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. ferencd@0: virtual TiXmlDocument* ToDocument() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. ferencd@0: ferencd@0: /** Walk the XML tree visiting this node and all of its children. ferencd@0: */ ferencd@0: virtual bool Accept( TiXmlVisitor* content ) const; ferencd@0: ferencd@0: protected : ferencd@0: // [internal use] ferencd@0: virtual TiXmlNode* Clone() const; ferencd@0: #ifdef TIXML_USE_STL ferencd@0: virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); ferencd@0: #endif ferencd@0: ferencd@0: private: ferencd@0: void CopyTo( TiXmlDocument* target ) const; ferencd@0: char *FixLineFeeds(char* buf, size_t length); ferencd@0: ferencd@0: bool error; ferencd@0: int errorId; ferencd@0: TIXML_STRING errorDesc; ferencd@0: int tabsize; ferencd@0: TiXmlCursor errorLocation; ferencd@0: bool useMicrosoftBOM; // the UTF-8 BOM were found when read. Note this, and try to write. ferencd@0: }; ferencd@0: ferencd@0: ferencd@0: /** ferencd@0: A TiXmlHandle is a class that wraps a node pointer with null checks; this is ferencd@0: an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml ferencd@0: DOM structure. It is a separate utility class. ferencd@0: ferencd@0: Take an example: ferencd@0: @verbatim ferencd@0: ferencd@0: ferencd@0: ferencd@0: ferencd@0: ferencd@0: ferencd@0: @endverbatim ferencd@0: ferencd@0: Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very ferencd@0: easy to write a *lot* of code that looks like: ferencd@0: ferencd@0: @verbatim ferencd@0: TiXmlElement* root = document.FirstChildElement( "Document" ); ferencd@0: if ( root ) ferencd@0: { ferencd@0: TiXmlElement* element = root->FirstChildElement( "Element" ); ferencd@0: if ( element ) ferencd@0: { ferencd@0: TiXmlElement* child = element->FirstChildElement( "Child" ); ferencd@0: if ( child ) ferencd@0: { ferencd@0: TiXmlElement* child2 = child->NextSiblingElement( "Child" ); ferencd@0: if ( child2 ) ferencd@0: { ferencd@0: // Finally do something useful. ferencd@0: @endverbatim ferencd@0: ferencd@0: And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity ferencd@0: of such code. A TiXmlHandle checks for null pointers so it is perfectly safe ferencd@0: and correct to use: ferencd@0: ferencd@0: @verbatim ferencd@0: TiXmlHandle docHandle( &document ); ferencd@0: TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement(); ferencd@0: if ( child2 ) ferencd@0: { ferencd@0: // do something useful ferencd@0: @endverbatim ferencd@0: ferencd@0: Which is MUCH more concise and useful. ferencd@0: ferencd@0: It is also safe to copy handles - internally they are nothing more than node pointers. ferencd@0: @verbatim ferencd@0: TiXmlHandle handleCopy = handle; ferencd@0: @endverbatim ferencd@0: ferencd@0: What they should not be used for is iteration: ferencd@0: ferencd@0: @verbatim ferencd@0: int i=0; ferencd@0: while ( true ) ferencd@0: { ferencd@0: TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).ToElement(); ferencd@0: if ( !child ) ferencd@0: break; ferencd@0: // do something ferencd@0: ++i; ferencd@0: } ferencd@0: @endverbatim ferencd@0: ferencd@0: It seems reasonable, but it is in fact two embedded while loops. The Child method is ferencd@0: a linear walk to find the element, so this code would iterate much more than it needs ferencd@0: to. Instead, prefer: ferencd@0: ferencd@0: @verbatim ferencd@0: TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).ToElement(); ferencd@0: ferencd@0: for( child; child; child=child->NextSiblingElement() ) ferencd@0: { ferencd@0: // do something ferencd@0: } ferencd@0: @endverbatim ferencd@0: */ ferencd@0: class TiXmlHandle ferencd@0: { ferencd@0: public: ferencd@0: /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. ferencd@0: TiXmlHandle( TiXmlNode* _node ) { this->node = _node; } ferencd@0: /// Copy constructor ferencd@0: TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; } ferencd@0: TiXmlHandle operator=( const TiXmlHandle& ref ) { if ( &ref != this ) this->node = ref.node; return *this; } ferencd@0: ferencd@0: /// Return a handle to the first child node. ferencd@0: TiXmlHandle FirstChild() const; ferencd@0: /// Return a handle to the first child node with the given name. ferencd@0: TiXmlHandle FirstChild( const char * value ) const; ferencd@0: /// Return a handle to the first child element. ferencd@0: TiXmlHandle FirstChildElement() const; ferencd@0: /// Return a handle to the first child element with the given name. ferencd@0: TiXmlHandle FirstChildElement( const char * value ) const; ferencd@0: ferencd@0: /** Return a handle to the "index" child with the given name. ferencd@0: The first child is 0, the second 1, etc. ferencd@0: */ ferencd@0: TiXmlHandle Child( const char* value, int index ) const; ferencd@0: /** Return a handle to the "index" child. ferencd@0: The first child is 0, the second 1, etc. ferencd@0: */ ferencd@0: TiXmlHandle Child( int index ) const; ferencd@0: /** Return a handle to the "index" child element with the given name. ferencd@0: The first child element is 0, the second 1, etc. Note that only TiXmlElements ferencd@0: are indexed: other types are not counted. ferencd@0: */ ferencd@0: TiXmlHandle ChildElement( const char* value, int index ) const; ferencd@0: /** Return a handle to the "index" child element. ferencd@0: The first child element is 0, the second 1, etc. Note that only TiXmlElements ferencd@0: are indexed: other types are not counted. ferencd@0: */ ferencd@0: TiXmlHandle ChildElement( int index ) const; ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); } ferencd@0: TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); } ferencd@0: ferencd@0: TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); } ferencd@0: TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); } ferencd@0: #endif ferencd@0: ferencd@0: /** Return the handle as a TiXmlNode. This may return null. ferencd@0: */ ferencd@0: TiXmlNode* ToNode() const { return node; } ferencd@0: /** Return the handle as a TiXmlElement. This may return null. ferencd@0: */ ferencd@0: TiXmlElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); } ferencd@0: /** Return the handle as a TiXmlText. This may return null. ferencd@0: */ ferencd@0: TiXmlText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); } ferencd@0: /** Return the handle as a TiXmlUnknown. This may return null. ferencd@0: */ ferencd@0: TiXmlUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); } ferencd@0: ferencd@0: /** @deprecated use ToNode. ferencd@0: Return the handle as a TiXmlNode. This may return null. ferencd@0: */ ferencd@0: TiXmlNode* Node() const { return ToNode(); } ferencd@0: /** @deprecated use ToElement. ferencd@0: Return the handle as a TiXmlElement. This may return null. ferencd@0: */ ferencd@0: TiXmlElement* Element() const { return ToElement(); } ferencd@0: /** @deprecated use ToText() ferencd@0: Return the handle as a TiXmlText. This may return null. ferencd@0: */ ferencd@0: TiXmlText* Text() const { return ToText(); } ferencd@0: /** @deprecated use ToUnknown() ferencd@0: Return the handle as a TiXmlUnknown. This may return null. ferencd@0: */ ferencd@0: TiXmlUnknown* Unknown() const { return ToUnknown(); } ferencd@0: ferencd@0: private: ferencd@0: TiXmlNode* node; ferencd@0: }; ferencd@0: ferencd@0: ferencd@0: /** Print to memory functionality. The TiXmlPrinter is useful when you need to: ferencd@0: ferencd@0: -# Print to memory (especially in non-STL mode) ferencd@0: -# Control formatting (line endings, etc.) ferencd@0: ferencd@0: When constructed, the TiXmlPrinter is in its default "pretty printing" mode. ferencd@0: Before calling Accept() you can call methods to control the printing ferencd@0: of the XML document. After TiXmlNode::Accept() is called, the printed document can ferencd@0: be accessed via the CStr(), Str(), and Size() methods. ferencd@0: ferencd@0: TiXmlPrinter uses the Visitor API. ferencd@0: @verbatim ferencd@0: TiXmlPrinter printer; ferencd@0: printer.SetIndent( "\t" ); ferencd@0: ferencd@0: doc.Accept( &printer ); ferencd@0: fprintf( stdout, "%s", printer.CStr() ); ferencd@0: @endverbatim ferencd@0: */ ferencd@0: class TiXmlPrinter : public TiXmlVisitor ferencd@0: { ferencd@0: public: ferencd@0: TiXmlPrinter() : depth( 0 ), simpleTextPrint( false ), ferencd@0: buffer(), indent( " " ), lineBreak( "\n" ) {} ferencd@0: ferencd@0: virtual bool VisitEnter( const TiXmlDocument& doc ); ferencd@0: virtual bool VisitExit( const TiXmlDocument& doc ); ferencd@0: ferencd@0: virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ); ferencd@0: virtual bool VisitExit( const TiXmlElement& element ); ferencd@0: ferencd@0: virtual bool Visit( const TiXmlDeclaration& declaration ); ferencd@0: virtual bool Visit( const TiXmlText& text ); ferencd@0: virtual bool Visit( const TiXmlComment& comment ); ferencd@0: virtual bool Visit( const TiXmlUnknown& unknown ); ferencd@0: ferencd@0: /** Set the indent characters for printing. By default 4 spaces ferencd@0: but tab (\t) is also useful, or null/empty string for no indentation. ferencd@0: */ ferencd@0: void SetIndent( const char* _indent ) { indent = _indent ? _indent : "" ; } ferencd@0: /// Query the indention string. ferencd@0: const char* Indent() { return indent.c_str(); } ferencd@0: /** Set the line breaking string. By default set to newline (\n). ferencd@0: Some operating systems prefer other characters, or can be ferencd@0: set to the null/empty string for no indenation. ferencd@0: */ ferencd@0: void SetLineBreak( const char* _lineBreak ) { lineBreak = _lineBreak ? _lineBreak : ""; } ferencd@0: /// Query the current line breaking string. ferencd@0: const char* LineBreak() { return lineBreak.c_str(); } ferencd@0: ferencd@0: /** Switch over to "stream printing" which is the most dense formatting without ferencd@0: linebreaks. Common when the XML is needed for network transmission. ferencd@0: */ ferencd@0: void SetStreamPrinting() { indent = ""; ferencd@0: lineBreak = ""; ferencd@0: } ferencd@0: /// Return the result. ferencd@0: const char* CStr() { return buffer.c_str(); } ferencd@0: /// Return the length of the result string. ferencd@0: size_t Size() { return buffer.size(); } ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: /// Return the result. ferencd@0: const std::string& Str() { return buffer; } ferencd@0: #endif ferencd@0: ferencd@0: private: ferencd@0: void DoIndent() { ferencd@0: for( int i=0; i