Merge branch 'master' of github.com:leethomason/tinyxml2

This commit is contained in:
Lee Thomason 2012-04-18 11:25:01 -07:00
commit 975426752c
8 changed files with 413 additions and 156 deletions

48
CMakeLists.txt Normal file
View File

@ -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 $<TARGET_FILE:${SAMPLE_NAME}>)

4
dox
View File

@ -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

View File

@ -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.
<h2> What it does. </h2>
@ -243,8 +242,9 @@ And additionally a test file:
<li>xmltest.cpp</li>
</ol>
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.
<h2> Documentation </h2>

View File

@ -24,7 +24,6 @@ distribution.
#include "tinyxml2.h"
#if 1
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#include <new>
@ -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 );
}

View File

@ -29,6 +29,7 @@ distribution.
#include <climits>
#include <cstdio>
#include <cstring>
#include <cstdarg>
#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
<Document>
<Element attributeA = "valueA">
<Child attributeB = "value1" />
<Child attributeB = "value2" />
</Element>
<Document>
@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 </PLAY>";
The structure of the XML file is:
<ul>
<li>(declaration)</li>
<li>(dtd stuff)</li>
<li>Element "PLAY"</li>
<ul>
<li>Element "TITLE"</li>
<ul>
<li>Text "A Midsummer Night's Dream"</li>
</ul>
</ul>
</ul>
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 <b>Dream</b>
@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

View File

@ -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 = "<group>"; };
037AE066151CCC6D00E0F29F /* utf8testverify.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = utf8testverify.xml; sourceTree = "<group>"; };
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 = "<group>"; };
037AE8A2151E692700E0F29F /* tinyxml2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tinyxml2.h; path = ../tinyxml2.h; sourceTree = "<group>"; };
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 = "<group>"; };
03F28B4B152E9B1B00D4CD90 /* tinyxml2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tinyxml2.h; sourceTree = "<group>"; };
/* 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 = "<group>";
};
037AE069151CCC7000E0F29F /* src */ = {
037AE069151CCC7000E0F29F /* Classes */ = {
isa = PBXGroup;
children = (
037AE8A1151E692700E0F29F /* tinyxml2.cpp */,
037AE8A2151E692700E0F29F /* tinyxml2.h */,
037AE8A3151E692700E0F29F /* xmltest.cpp */,
);
name = src;
name = Classes;
sourceTree = "<group>";
};
037AE06A151CCC7C00E0F29F /* resources */ = {
037AE06A151CCC7C00E0F29F /* Resources */ = {
isa = PBXGroup;
children = (
037AE062151CCC6D00E0F29F /* dream.xml */,
037AE065151CCC6D00E0F29F /* utf8test.xml */,
037AE066151CCC6D00E0F29F /* utf8testverify.xml */,
);
name = resources;
name = Resources;
path = ..;
sourceTree = "<group>";
};
@ -88,6 +87,24 @@
name = Products;
sourceTree = "<group>";
};
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 = "<group>";
};
/* 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;
};

View File

@ -94,12 +94,12 @@ int example_2()
int example_3()
{
static const char* xml =
"<?xml version=\"1.0\"?>"
"<!DOCTYPE PLAY SYSTEM \"play.dtd\">"
"<PLAY>"
"<TITLE>A Midsummer Night's Dream</TITLE>"
"</PLAY>";
static const char* xml =
"<?xml version=\"1.0\"?>"
"<!DOCTYPE PLAY SYSTEM \"play.dtd\">"
"<PLAY>"
"<TITLE>A Midsummer Night's Dream</TITLE>"
"</PLAY>";
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 = "<element attrib='bar'><sub>Text</sub></element>";
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 = "<element attrib='bar'><sub>Text</sub></element>";
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 )

94
xmltest.h Executable file
View File

@ -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 </PLAY>";
The structure of the XML file is:
<ul>
<li>(declaration)</li>
<li>(dtd stuff)</li>
<li>Element "PLAY"</li>
<ul>
<li>Element "TITLE"</li>
<ul>
<li>Text "A Midsummer Night's Dream"</li>
</ul>
</ul>
</ul>
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 <b>Dream</b>
@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.
*/