diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..3d9c670 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,48 @@ +cmake_minimum_required(VERSION 2.6 FATAL_ERROR) +cmake_policy(VERSION 2.6) + +project(tinyxml2) +#enable_testing() + +#CMAKE_BUILD_TOOL + +################################ +# Add common source + +include_directories("${CMAKE_CURRENT_SOURCE_DIR}/.") + +################################ +# Add custom target to copy all data + +set(TARGET_DATA_COPY DATA_COPY) +if(${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_BINARY_DIR}) + add_custom_target( + ${TARGET_DATA_COPY} + COMMAND ${CMAKE_COMMAND} -E echo "In source build") +else(${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_BINARY_DIR}) + add_custom_target( + ${TARGET_DATA_COPY} + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/dream.xml ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/utf8test.xml ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/utf8testverify.xml ${CMAKE_CURRENT_BINARY_DIR}) +endif(${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_BINARY_DIR}) + +set(OGL_DATA_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/data) + +################################ +# Add definitions + +if(MSVC) + add_definitions(-D_CRT_SECURE_NO_WARNINGS) +endif(MSVC) + +################################ +# Add targets + +add_library(tinyxml2 STATIC tinyxml2.cpp tinyxml2.h) + +add_executable(test xmltest.cpp) +add_dependencies(test tinyxml2) +add_dependencies(test ${TARGET_DATA_COPY}) +target_link_libraries(test tinyxml2) +#add_test(test ${SAMPLE_NAME} COMMAND $) diff --git a/dox b/dox index 3a18853..1d40136 100755 --- a/dox +++ b/dox @@ -32,7 +32,7 @@ PROJECT_NAME = "TinyXML-2" # This could be handy for archiving the generated documentation or # if some version control system is used. -PROJECT_NUMBER = 0.9.3 +PROJECT_NUMBER = 0.9.4 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer @@ -661,7 +661,7 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = tinyxml2.h readme.txt +INPUT = tinyxml2.h xmltest.h readme.txt # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is diff --git a/readme.txt b/readme.txt index ec2d015..29226f7 100755 --- a/readme.txt +++ b/readme.txt @@ -11,8 +11,7 @@ github.com/leethomason/tinyxml2 The online HTML version of these docs: http://grinninglizard.com/tinyxml2docs/index.html -Where examples are in the "related pages" tab: -http://grinninglizard.com/tinyxml2docs/pages.html +Examples are in the "related pages" tab of the HTML docs.

What it does.

@@ -243,8 +242,9 @@ And additionally a test file:
  • xmltest.cpp
  • -Simply compile and run. There is a visual studio 2010 project included. - +Simply compile and run. There is a visual studio 2010 project included, a simple Makefile, +an XCode project, and a cmake CMakeLists.txt included to help you. The top of tinyxml.h +even has a simple g++ command line if you are are *nix and don't want to use a build system.

    Documentation

    diff --git a/tinyxml2.cpp b/tinyxml2.cpp index 9e92ae2..4ce9b32 100644 --- a/tinyxml2.cpp +++ b/tinyxml2.cpp @@ -24,7 +24,6 @@ distribution. #include "tinyxml2.h" #if 1 - #include #include #include #include @@ -998,7 +997,7 @@ void XMLAttribute::SetAttribute( const char* v ) void XMLAttribute::SetAttribute( int v ) { char buf[BUF_SIZE]; - TIXML_SNPRINTF( buf, BUF_SIZE-1, "%d", v ); + TIXML_SNPRINTF( buf, BUF_SIZE, "%d", v ); value.SetStr( buf ); } @@ -1006,7 +1005,7 @@ void XMLAttribute::SetAttribute( int v ) void XMLAttribute::SetAttribute( unsigned v ) { char buf[BUF_SIZE]; - TIXML_SNPRINTF( buf, BUF_SIZE-1, "%u", v ); + TIXML_SNPRINTF( buf, BUF_SIZE, "%u", v ); value.SetStr( buf ); } @@ -1014,21 +1013,21 @@ void XMLAttribute::SetAttribute( unsigned v ) void XMLAttribute::SetAttribute( bool v ) { char buf[BUF_SIZE]; - TIXML_SNPRINTF( buf, BUF_SIZE-1, "%d", v ? 1 : 0 ); + TIXML_SNPRINTF( buf, BUF_SIZE, "%d", v ? 1 : 0 ); value.SetStr( buf ); } void XMLAttribute::SetAttribute( double v ) { char buf[BUF_SIZE]; - TIXML_SNPRINTF( buf, BUF_SIZE-1, "%f", v ); + TIXML_SNPRINTF( buf, BUF_SIZE, "%f", v ); value.SetStr( buf ); } void XMLAttribute::SetAttribute( float v ) { char buf[BUF_SIZE]; - TIXML_SNPRINTF( buf, BUF_SIZE-1, "%f", v ); + TIXML_SNPRINTF( buf, BUF_SIZE, "%f", v ); value.SetStr( buf ); } @@ -1408,7 +1407,7 @@ int XMLDocument::LoadFile( FILE* fp ) } -void XMLDocument::SaveFile( const char* filename ) +int XMLDocument::SaveFile( const char* filename ) { #if defined(_MSC_VER) #pragma warning ( push ) @@ -1418,14 +1417,21 @@ void XMLDocument::SaveFile( const char* filename ) #if defined(_MSC_VER) #pragma warning ( pop ) #endif - if ( fp ) { - XMLPrinter stream( fp ); - Print( &stream ); - fclose( fp ); - } - else { + if ( !fp ) { SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, filename, 0 ); + return errorID; } + SaveFile(fp); + fclose( fp ); + return errorID; +} + + +int XMLDocument::SaveFile( FILE* fp ) +{ + XMLPrinter stream( fp ); + Print( &stream ); + return errorID; } @@ -1481,11 +1487,9 @@ void XMLDocument::PrintError() const if ( errorStr1 ) { TIXML_SNPRINTF( buf1, LEN, "%s", errorStr1 ); - buf1[LEN-1] = 0; } if ( errorStr2 ) { TIXML_SNPRINTF( buf2, LEN, "%s", errorStr2 ); - buf2[LEN-1] = 0; } printf( "XMLDocument error id=%d str1=%s str2=%s\n", @@ -1534,10 +1538,10 @@ void XMLPrinter::Print( const char* format, ... ) int len = -1; int expand = 1000; while ( len < 0 ) { - len = vsnprintf_s( accumulator.Mem(), accumulator.Capacity(), accumulator.Capacity()-1, format, va ); + len = vsnprintf_s( accumulator.Mem(), accumulator.Capacity(), _TRUNCATE, format, va ); if ( len < 0 ) { - accumulator.PushArr( expand ); expand *= 3/2; + accumulator.PushArr( expand ); } } char* p = buffer.PushArr( len ) - 1; @@ -1644,7 +1648,7 @@ void XMLPrinter::PushAttribute( const char* name, const char* value ) void XMLPrinter::PushAttribute( const char* name, int v ) { char buf[BUF_SIZE]; - TIXML_SNPRINTF( buf, BUF_SIZE-1, "%d", v ); + TIXML_SNPRINTF( buf, BUF_SIZE, "%d", v ); PushAttribute( name, buf ); } @@ -1652,7 +1656,7 @@ void XMLPrinter::PushAttribute( const char* name, int v ) void XMLPrinter::PushAttribute( const char* name, unsigned v ) { char buf[BUF_SIZE]; - TIXML_SNPRINTF( buf, BUF_SIZE-1, "%u", v ); + TIXML_SNPRINTF( buf, BUF_SIZE, "%u", v ); PushAttribute( name, buf ); } @@ -1660,7 +1664,7 @@ void XMLPrinter::PushAttribute( const char* name, unsigned v ) void XMLPrinter::PushAttribute( const char* name, bool v ) { char buf[BUF_SIZE]; - TIXML_SNPRINTF( buf, BUF_SIZE-1, "%d", v ? 1 : 0 ); + TIXML_SNPRINTF( buf, BUF_SIZE, "%d", v ? 1 : 0 ); PushAttribute( name, buf ); } @@ -1668,7 +1672,7 @@ void XMLPrinter::PushAttribute( const char* name, bool v ) void XMLPrinter::PushAttribute( const char* name, double v ) { char buf[BUF_SIZE]; - TIXML_SNPRINTF( buf, BUF_SIZE-1, "%f", v ); + TIXML_SNPRINTF( buf, BUF_SIZE, "%f", v ); PushAttribute( name, buf ); } diff --git a/tinyxml2.h b/tinyxml2.h index 7fc1ea9..76e47ac 100644 --- a/tinyxml2.h +++ b/tinyxml2.h @@ -29,6 +29,7 @@ distribution. #include #include #include + #include #else // Not completely sure all the interesting systems // can handle the new headers; can switch this if @@ -70,33 +71,33 @@ distribution. #endif -// Deprecated library function hell. Compilers want to use the -// new safe versions. This probably doesn't fully address the problem, -// but it gets closer. There are too many compilers for me to fully -// test. If you get compilation troubles, undefine TIXML_SAFE - #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) // Microsoft visual studio, version 2005 and higher. - #define TIXML_SNPRINTF _snprintf_s + /*int _snprintf_s( + char *buffer, + size_t sizeOfBuffer, + size_t count, + const char *format [, + argument] ... + );*/ + inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... ) { + va_list va; + va_start( va, format ); + int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va ); + va_end( va ); + return result; + } #define TIXML_SSCANF sscanf_s -#elif defined(_MSC_VER) && (_MSC_VER >= 1200 ) - // Microsoft visual studio, version 6 and higher. - //#pragma message( "Using _sn* functions." ) - #define TIXML_SNPRINTF _snprintf - #define TIXML_SSCANF sscanf -#elif defined(__GNUC__) && (__GNUC__ >= 3 ) +#else // GCC version 3 and higher //#warning( "Using sn* functions." ) #define TIXML_SNPRINTF snprintf #define TIXML_SSCANF sscanf -#else - #define TIXML_SNPRINTF snprintf - #define TIXML_SSCANF sscanf #endif static const int TIXML2_MAJOR_VERSION = 0; static const int TIXML2_MINOR_VERSION = 9; -static const int TIXML2_PATCH_VERSION = 3; +static const int TIXML2_PATCH_VERSION = 4; namespace tinyxml2 { @@ -1007,24 +1008,38 @@ public: an errorID. */ int Parse( const char* xml ); + /** Load an XML file from disk. Returns XML_NO_ERROR (0) on success, or an errorID. - */ + */ int LoadFile( const char* filename ); + /** Load an XML file from disk. You are responsible for providing and closing the FILE*. Returns XML_NO_ERROR (0) on success, or an errorID. - */ + */ int LoadFile( FILE* ); + /** Save the XML file to disk. + Returns XML_NO_ERROR (0) on success, or + an errorID. */ - void SaveFile( const char* filename ); + int SaveFile( const char* filename ); + + /** + Save the XML file to disk. You are responsible + for providing and closing the FILE*. + + Returns XML_NO_ERROR (0) on success, or + an errorID. + */ + int SaveFile( FILE* ); bool ProcessEntities() const { return processEntities; } @@ -1131,6 +1146,139 @@ private: }; +/** + A XMLHandle is a class that wraps a node pointer with null checks; this is + an incredibly useful thing. Note that XMLHandle is not part of the TinyXML + DOM structure. It is a separate utility class. + + Take an example: + @verbatim + + + + + + + @endverbatim + + Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very + easy to write a *lot* of code that looks like: + + @verbatim + XMLElement* root = document.FirstChildElement( "Document" ); + if ( root ) + { + XMLElement* element = root->FirstChildElement( "Element" ); + if ( element ) + { + XMLElement* child = element->FirstChildElement( "Child" ); + if ( child ) + { + XMLElement* child2 = child->NextSiblingElement( "Child" ); + if ( child2 ) + { + // Finally do something useful. + @endverbatim + + And that doesn't even cover "else" cases. XMLHandle addresses the verbosity + of such code. A XMLHandle checks for null pointers so it is perfectly safe + and correct to use: + + @verbatim + XMLHandle docHandle( &document ); + XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement(); + if ( child2 ) + { + // do something useful + @endverbatim + + Which is MUCH more concise and useful. + + It is also safe to copy handles - internally they are nothing more than node pointers. + @verbatim + XMLHandle handleCopy = handle; + @endverbatim + + See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects. +*/ +class XMLHandle +{ +public: + /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. + XMLHandle( XMLNode* _node ) { node = _node; } + /// Create a handle from a node. + XMLHandle( XMLNode& _node ) { node = &_node; } + /// Copy constructor + XMLHandle( const XMLHandle& ref ) { node = ref.node; } + /// Assignment + XMLHandle operator=( const XMLHandle& ref ) { node = ref.node; return *this; } + + /// Get the first child of this handle. + XMLHandle FirstChild() { return XMLHandle( node ? node->FirstChild() : 0 ); } + /// Get the first child element of this handle. + XMLHandle FirstChildElement( const char* value=0 ) { return XMLHandle( node ? node->FirstChildElement( value ) : 0 ); } + /// Get the last child of this handle. + XMLHandle LastChild() { return XMLHandle( node ? node->LastChild() : 0 ); } + /// Get the last child element of this handle. + XMLHandle LastChildElement( const char* _value=0 ) { return XMLHandle( node ? node->LastChildElement( _value ) : 0 ); } + /// Get the previous sibling of this handle. + XMLHandle PreviousSibling() { return XMLHandle( node ? node->PreviousSibling() : 0 ); } + /// Get the previous sibling element of this handle. + XMLHandle PreviousSiblingElement( const char* _value=0 ) { return XMLHandle( node ? node->PreviousSiblingElement( _value ) : 0 ); } + /// Get the next sibling of this handle. + XMLHandle NextSibling() { return XMLHandle( node ? node->NextSibling() : 0 ); } + /// Get the next sibling element of this handle. + XMLHandle NextSiblingElement( const char* _value=0 ) { return XMLHandle( node ? node->NextSiblingElement( _value ) : 0 ); } + + /// Safe cast to XMLNode. This can return null. + XMLNode* ToNode() { return node; } + /// Safe cast to XMLElement. This can return null. + XMLElement* ToElement() { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); } + /// Safe cast to XMLText. This can return null. + XMLText* ToText() { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); } + /// Safe cast to XMLUnknown. This can return null. + XMLUnknown* ToUnknown() { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); } + /// Safe cast to XMLDeclaration. This can return null. + XMLDeclaration* ToDeclaration() { return ( ( node && node->ToDeclaration() ) ? node->ToDeclaration() : 0 ); } + +private: + XMLNode* node; +}; + + +/** + A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the + same in all regards, except for the 'const' qualifiers. See XMLHandle for API. +*/ +class XMLConstHandle +{ +public: + XMLConstHandle( const XMLNode* _node ) { node = _node; } + XMLConstHandle( const XMLNode& _node ) { node = &_node; } + XMLConstHandle( const XMLConstHandle& ref ) { node = ref.node; } + + XMLConstHandle operator=( const XMLConstHandle& ref ) { node = ref.node; return *this; } + + const XMLConstHandle FirstChild() const { return XMLConstHandle( node ? node->FirstChild() : 0 ); } + const XMLConstHandle FirstChildElement( const char* value=0 ) const { return XMLConstHandle( node ? node->FirstChildElement( value ) : 0 ); } + const XMLConstHandle LastChild() const { return XMLConstHandle( node ? node->LastChild() : 0 ); } + const XMLConstHandle LastChildElement( const char* _value=0 ) const { return XMLConstHandle( node ? node->LastChildElement( _value ) : 0 ); } + const XMLConstHandle PreviousSibling() const { return XMLConstHandle( node ? node->PreviousSibling() : 0 ); } + const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const { return XMLConstHandle( node ? node->PreviousSiblingElement( _value ) : 0 ); } + const XMLConstHandle NextSibling() const { return XMLConstHandle( node ? node->NextSibling() : 0 ); } + const XMLConstHandle NextSiblingElement( const char* _value=0 ) const { return XMLConstHandle( node ? node->NextSiblingElement( _value ) : 0 ); } + + + const XMLNode* ToNode() const { return node; } + const XMLElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); } + const XMLText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); } + const XMLUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); } + const XMLDeclaration* ToDeclaration() const { return ( ( node && node->ToDeclaration() ) ? node->ToDeclaration() : 0 ); } + +private: + const XMLNode* node; +}; + /** Printing functionality. The XMLPrinter gives you more @@ -1252,96 +1400,4 @@ private: } // tinyxml2 -// What follows is the docs for the examples. -// I'd like the docs to be just before the -// actual examples in xmltest.cpp, but I -// can't seem to get doxygen to do that. It -// would be a wonderful patch if anyone figures -// it out. - -/** @page Example-1 Load an XML File - * @dontinclude ./xmltest.cpp - * Basic XML file loading. - * The basic syntax to load an XML file from - * disk and check for an error. (ErrorID() - * will return 0 for no error.) - * @skip example_1() - * @until } - */ - - -/** @page Example-2 Parse an XML from char buffer - * @dontinclude ./xmltest.cpp - * Basic XML string parsing. - * The basic syntax to parse an XML for - * a char* and check for an error. (ErrorID() - * will return 0 for no error.) - * @skip example_2() - * @until } - */ - -/** @page Example-3 Get information out of XML - @dontinclude ./xmltest.cpp - In this example, we navigate a simple XML - file, and read some interesting text. Note - that this is examlpe doesn't use error - checking; working code should check for null - pointers when walking an XML tree, or use - XMLHandle. - - (The XML is an excerpt from "dream.xml"). - - @skip example_3 - @until "; - - The structure of the XML file is: - -
      -
    • (declaration)
    • -
    • (dtd stuff)
    • -
    • Element "PLAY"
    • -
        -
      • Element "TITLE"
      • -
          -
        • Text "A Midsummer Night's Dream"
        • -
        -
      -
    - - For this example, we want to print out the - title of the play. The text of the title (what - we want) is child of the "TITLE" element which - is a child of the "PLAY" element. - - We want to skip the declaration and dtd, so the - method FirstChildElement() is a good choice. The - FirstChildElement() of the Document is the "PLAY" - Element, the FirstChildElement() of the "PLAY" Element - is the "TITLE" Element. - - @until ( "TITLE" ); - - We can then use the convenience function GetText() - to get the title of the play. - - @until title ); - - Text is just another Node in the XML DOM. And in - fact you should be a little cautious with it, as - text nodes can contain elements. - - @verbatim - Consider: A Midsummer Night's Dream - @endverbatim - - It is more correct to actually query the Text Node - if in doubt: - - @until title ); - - Noting that here we use FirstChild() since we are - looking for XMLText, not an element, and ToText() - is a cast from a Node to a XMLText. -*/ - #endif // TINYXML2_INCLUDED diff --git a/tinyxml2/tinyxml2.xcodeproj/project.pbxproj b/tinyxml2/tinyxml2.xcodeproj/project.pbxproj index 7b1b7a2..a6b7b61 100644 --- a/tinyxml2/tinyxml2.xcodeproj/project.pbxproj +++ b/tinyxml2/tinyxml2.xcodeproj/project.pbxproj @@ -7,11 +7,11 @@ objects = { /* Begin PBXBuildFile section */ - 037AE8A4151E692700E0F29F /* tinyxml2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 037AE8A1151E692700E0F29F /* tinyxml2.cpp */; }; 037AE8A5151E692700E0F29F /* xmltest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 037AE8A3151E692700E0F29F /* xmltest.cpp */; }; 037AE9BE151E694400E0F29F /* dream.xml in CopyFiles */ = {isa = PBXBuildFile; fileRef = 037AE062151CCC6D00E0F29F /* dream.xml */; }; 037AE9BF151E694400E0F29F /* utf8test.xml in CopyFiles */ = {isa = PBXBuildFile; fileRef = 037AE065151CCC6D00E0F29F /* utf8test.xml */; }; 037AE9C0151E694400E0F29F /* utf8testverify.xml in CopyFiles */ = {isa = PBXBuildFile; fileRef = 037AE066151CCC6D00E0F29F /* utf8testverify.xml */; }; + 03F28B53152E9B1B00D4CD90 /* tinyxml2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 03F28B4A152E9B1B00D4CD90 /* tinyxml2.cpp */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -34,9 +34,9 @@ 037AE065151CCC6D00E0F29F /* utf8test.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = utf8test.xml; sourceTree = ""; }; 037AE066151CCC6D00E0F29F /* utf8testverify.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = utf8testverify.xml; sourceTree = ""; }; 037AE86D151E685F00E0F29F /* tinyxml2 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tinyxml2; sourceTree = BUILT_PRODUCTS_DIR; }; - 037AE8A1151E692700E0F29F /* tinyxml2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tinyxml2.cpp; path = ../tinyxml2.cpp; sourceTree = ""; }; - 037AE8A2151E692700E0F29F /* tinyxml2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tinyxml2.h; path = ../tinyxml2.h; sourceTree = ""; }; 037AE8A3151E692700E0F29F /* xmltest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = xmltest.cpp; path = ../xmltest.cpp; sourceTree = SOURCE_ROOT; }; + 03F28B4A152E9B1B00D4CD90 /* tinyxml2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tinyxml2.cpp; sourceTree = ""; }; + 03F28B4B152E9B1B00D4CD90 /* tinyxml2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tinyxml2.h; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -53,30 +53,29 @@ 037AE056151CCC5200E0F29F = { isa = PBXGroup; children = ( - 037AE06A151CCC7C00E0F29F /* resources */, - 037AE069151CCC7000E0F29F /* src */, + 037AE069151CCC7000E0F29F /* Classes */, + 037AE06A151CCC7C00E0F29F /* Resources */, + 03F28B60152E9B4C00D4CD90 /* Libraries */, 037AE06F151CCCB900E0F29F /* Products */, ); sourceTree = ""; }; - 037AE069151CCC7000E0F29F /* src */ = { + 037AE069151CCC7000E0F29F /* Classes */ = { isa = PBXGroup; children = ( - 037AE8A1151E692700E0F29F /* tinyxml2.cpp */, - 037AE8A2151E692700E0F29F /* tinyxml2.h */, 037AE8A3151E692700E0F29F /* xmltest.cpp */, ); - name = src; + name = Classes; sourceTree = ""; }; - 037AE06A151CCC7C00E0F29F /* resources */ = { + 037AE06A151CCC7C00E0F29F /* Resources */ = { isa = PBXGroup; children = ( 037AE062151CCC6D00E0F29F /* dream.xml */, 037AE065151CCC6D00E0F29F /* utf8test.xml */, 037AE066151CCC6D00E0F29F /* utf8testverify.xml */, ); - name = resources; + name = Resources; path = ..; sourceTree = ""; }; @@ -88,6 +87,24 @@ name = Products; sourceTree = ""; }; + 03F28AD7152E9B1B00D4CD90 /* tinyxml2 */ = { + isa = PBXGroup; + children = ( + 03F28B4A152E9B1B00D4CD90 /* tinyxml2.cpp */, + 03F28B4B152E9B1B00D4CD90 /* tinyxml2.h */, + ); + name = tinyxml2; + path = ..; + sourceTree = SOURCE_ROOT; + }; + 03F28B60152E9B4C00D4CD90 /* Libraries */ = { + isa = PBXGroup; + children = ( + 03F28AD7152E9B1B00D4CD90 /* tinyxml2 */, + ); + name = Libraries; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -138,8 +155,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 037AE8A4151E692700E0F29F /* tinyxml2.cpp in Sources */, 037AE8A5151E692700E0F29F /* xmltest.cpp in Sources */, + 03F28B53152E9B1B00D4CD90 /* tinyxml2.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/xmltest.cpp b/xmltest.cpp index bb5bdfb..0991e2d 100644 --- a/xmltest.cpp +++ b/xmltest.cpp @@ -94,12 +94,12 @@ int example_2() int example_3() { - static const char* xml = - "" - "" - "" - "A Midsummer Night's Dream" - ""; + static const char* xml = + "" + "" + "" + "A Midsummer Night's Dream" + ""; XMLDocument doc; doc.Parse( xml ); @@ -751,6 +751,44 @@ int main( int /*argc*/, const char ** /*argv*/ ) XMLTest( "Clone and Equal", 4, count ); } + { + // This shouldn't crash. + XMLDocument doc; + if(XML_NO_ERROR != doc.LoadFile( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" )) + { + doc.PrintError(); + } + XMLTest( "Error in snprinf handling.", true, doc.Error() ); + } + + // -------- Handles ------------ + { + static const char* xml = "Text"; + XMLDocument doc; + doc.Parse( xml ); + + XMLElement* ele = XMLHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement(); + XMLTest( "Handle, success, mutable", ele->Value(), "sub" ); + + XMLHandle docH( doc ); + ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement(); + XMLTest( "Handle, dne, mutable", false, ele != 0 ); + } + + { + static const char* xml = "Text"; + XMLDocument doc; + doc.Parse( xml ); + XMLConstHandle docH( doc ); + + const XMLElement* ele = docH.FirstChildElement( "element" ).FirstChild().ToElement(); + XMLTest( "Handle, success, const", ele->Value(), "sub" ); + + ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement(); + XMLTest( "Handle, dne, const", false, ele != 0 ); + } + + // ----------- Performance tracking -------------- { #if defined( _MSC_VER ) diff --git a/xmltest.h b/xmltest.h new file mode 100755 index 0000000..73a48c0 --- /dev/null +++ b/xmltest.h @@ -0,0 +1,94 @@ +// Purely doxygen documentation + + +// What follows is the docs for the examples. +// I'd like the docs to be just before the +// actual examples in xmltest.cpp, but I +// can't seem to get doxygen to do that. It +// would be a wonderful patch if anyone figures +// it out. + +/** @page Example-1 Load an XML File + * @dontinclude ./xmltest.cpp + * Basic XML file loading. + * The basic syntax to load an XML file from + * disk and check for an error. (ErrorID() + * will return 0 for no error.) + * @skip example_1() + * @until } + */ + + +/** @page Example-2 Parse an XML from char buffer + * @dontinclude ./xmltest.cpp + * Basic XML string parsing. + * The basic syntax to parse an XML for + * a char* and check for an error. (ErrorID() + * will return 0 for no error.) + * @skip example_2() + * @until } + */ + +/** @page Example-3 Get information out of XML + @dontinclude ./xmltest.cpp + In this example, we navigate a simple XML + file, and read some interesting text. Note + that this is examlpe doesn't use error + checking; working code should check for null + pointers when walking an XML tree, or use + XMLHandle. + + (The XML is an excerpt from "dream.xml"). + + @skip example_3 + @until "; + + The structure of the XML file is: + +
      +
    • (declaration)
    • +
    • (dtd stuff)
    • +
    • Element "PLAY"
    • +
        +
      • Element "TITLE"
      • +
          +
        • Text "A Midsummer Night's Dream"
        • +
        +
      +
    + + For this example, we want to print out the + title of the play. The text of the title (what + we want) is child of the "TITLE" element which + is a child of the "PLAY" element. + + We want to skip the declaration and dtd, so the + method FirstChildElement() is a good choice. The + FirstChildElement() of the Document is the "PLAY" + Element, the FirstChildElement() of the "PLAY" Element + is the "TITLE" Element. + + @until ( "TITLE" ); + + We can then use the convenience function GetText() + to get the title of the play. + + @until title ); + + Text is just another Node in the XML DOM. And in + fact you should be a little cautious with it, as + text nodes can contain elements. + + @verbatim + Consider: A Midsummer Night's Dream + @endverbatim + + It is more correct to actually query the Text Node + if in doubt: + + @until title ); + + Noting that here we use FirstChild() since we are + looking for XMLText, not an element, and ToText() + is a cast from a Node to a XMLText. +*/