mirror of https://github.com/AxioDL/tinyxml2.git
added a bunch of comments in
This commit is contained in:
parent
784607f31d
commit
2a1cd27732
58
tinyxml2.cpp
58
tinyxml2.cpp
|
@ -448,7 +448,7 @@ XMLNode::XMLNode( XMLDocument* doc ) :
|
||||||
|
|
||||||
XMLNode::~XMLNode()
|
XMLNode::~XMLNode()
|
||||||
{
|
{
|
||||||
ClearChildren();
|
DeleteChildren();
|
||||||
if ( parent ) {
|
if ( parent ) {
|
||||||
parent->Unlink( this );
|
parent->Unlink( this );
|
||||||
}
|
}
|
||||||
|
@ -464,7 +464,7 @@ void XMLNode::SetValue( const char* str, bool staticMem )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void XMLNode::ClearChildren()
|
void XMLNode::DeleteChildren()
|
||||||
{
|
{
|
||||||
while( firstChild ) {
|
while( firstChild ) {
|
||||||
XMLNode* node = firstChild;
|
XMLNode* node = firstChild;
|
||||||
|
@ -1106,7 +1106,7 @@ XMLDocument::XMLDocument() :
|
||||||
|
|
||||||
XMLDocument::~XMLDocument()
|
XMLDocument::~XMLDocument()
|
||||||
{
|
{
|
||||||
ClearChildren();
|
DeleteChildren();
|
||||||
delete [] charBuffer;
|
delete [] charBuffer;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -1164,7 +1164,7 @@ XMLText* XMLDocument::NewText( const char* str )
|
||||||
|
|
||||||
int XMLDocument::LoadFile( const char* filename )
|
int XMLDocument::LoadFile( const char* filename )
|
||||||
{
|
{
|
||||||
ClearChildren();
|
DeleteChildren();
|
||||||
InitDocument();
|
InitDocument();
|
||||||
|
|
||||||
FILE* fp = fopen( filename, "rb" );
|
FILE* fp = fopen( filename, "rb" );
|
||||||
|
@ -1180,7 +1180,7 @@ int XMLDocument::LoadFile( const char* filename )
|
||||||
|
|
||||||
int XMLDocument::LoadFile( FILE* fp )
|
int XMLDocument::LoadFile( FILE* fp )
|
||||||
{
|
{
|
||||||
ClearChildren();
|
DeleteChildren();
|
||||||
InitDocument();
|
InitDocument();
|
||||||
|
|
||||||
fseek( fp, 0, SEEK_END );
|
fseek( fp, 0, SEEK_END );
|
||||||
|
@ -1211,7 +1211,7 @@ int XMLDocument::LoadFile( FILE* fp )
|
||||||
void XMLDocument::SaveFile( const char* filename )
|
void XMLDocument::SaveFile( const char* filename )
|
||||||
{
|
{
|
||||||
FILE* fp = fopen( filename, "w" );
|
FILE* fp = fopen( filename, "w" );
|
||||||
XMLStreamer stream( fp );
|
XMLPrinter stream( fp );
|
||||||
Print( &stream );
|
Print( &stream );
|
||||||
fclose( fp );
|
fclose( fp );
|
||||||
}
|
}
|
||||||
|
@ -1219,7 +1219,7 @@ void XMLDocument::SaveFile( const char* filename )
|
||||||
|
|
||||||
int XMLDocument::Parse( const char* p )
|
int XMLDocument::Parse( const char* p )
|
||||||
{
|
{
|
||||||
ClearChildren();
|
DeleteChildren();
|
||||||
InitDocument();
|
InitDocument();
|
||||||
|
|
||||||
if ( !p || !*p ) {
|
if ( !p || !*p ) {
|
||||||
|
@ -1243,9 +1243,9 @@ int XMLDocument::Parse( const char* p )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void XMLDocument::Print( XMLStreamer* streamer )
|
void XMLDocument::Print( XMLPrinter* streamer )
|
||||||
{
|
{
|
||||||
XMLStreamer stdStreamer( stdout );
|
XMLPrinter stdStreamer( stdout );
|
||||||
if ( !streamer )
|
if ( !streamer )
|
||||||
streamer = &stdStreamer;
|
streamer = &stdStreamer;
|
||||||
Accept( streamer );
|
Accept( streamer );
|
||||||
|
@ -1281,7 +1281,7 @@ void XMLDocument::PrintError() const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
XMLStreamer::XMLStreamer( FILE* file ) :
|
XMLPrinter::XMLPrinter( FILE* file ) :
|
||||||
elementJustOpened( false ),
|
elementJustOpened( false ),
|
||||||
firstElement( true ),
|
firstElement( true ),
|
||||||
fp( file ),
|
fp( file ),
|
||||||
|
@ -1305,7 +1305,7 @@ XMLStreamer::XMLStreamer( FILE* file ) :
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void XMLStreamer::Print( const char* format, ... )
|
void XMLPrinter::Print( const char* format, ... )
|
||||||
{
|
{
|
||||||
va_list va;
|
va_list va;
|
||||||
va_start( va, format );
|
va_start( va, format );
|
||||||
|
@ -1338,7 +1338,7 @@ void XMLStreamer::Print( const char* format, ... )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void XMLStreamer::PrintSpace( int depth )
|
void XMLPrinter::PrintSpace( int depth )
|
||||||
{
|
{
|
||||||
for( int i=0; i<depth; ++i ) {
|
for( int i=0; i<depth; ++i ) {
|
||||||
Print( " " );
|
Print( " " );
|
||||||
|
@ -1346,7 +1346,7 @@ void XMLStreamer::PrintSpace( int depth )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void XMLStreamer::PrintString( const char* p, bool restricted )
|
void XMLPrinter::PrintString( const char* p, bool restricted )
|
||||||
{
|
{
|
||||||
// Look for runs of bytes between entities to print.
|
// Look for runs of bytes between entities to print.
|
||||||
const char* q = p;
|
const char* q = p;
|
||||||
|
@ -1382,7 +1382,7 @@ void XMLStreamer::PrintString( const char* p, bool restricted )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void XMLStreamer::PushHeader( bool writeBOM, bool writeDec )
|
void XMLPrinter::PushHeader( bool writeBOM, bool writeDec )
|
||||||
{
|
{
|
||||||
static const unsigned char bom[] = { TIXML_UTF_LEAD_0, TIXML_UTF_LEAD_1, TIXML_UTF_LEAD_2, 0 };
|
static const unsigned char bom[] = { TIXML_UTF_LEAD_0, TIXML_UTF_LEAD_1, TIXML_UTF_LEAD_2, 0 };
|
||||||
if ( writeBOM ) {
|
if ( writeBOM ) {
|
||||||
|
@ -1394,7 +1394,7 @@ void XMLStreamer::PushHeader( bool writeBOM, bool writeDec )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void XMLStreamer::OpenElement( const char* name )
|
void XMLPrinter::OpenElement( const char* name )
|
||||||
{
|
{
|
||||||
if ( elementJustOpened ) {
|
if ( elementJustOpened ) {
|
||||||
SealElement();
|
SealElement();
|
||||||
|
@ -1413,7 +1413,7 @@ void XMLStreamer::OpenElement( const char* name )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void XMLStreamer::PushAttribute( const char* name, const char* value )
|
void XMLPrinter::PushAttribute( const char* name, const char* value )
|
||||||
{
|
{
|
||||||
TIXMLASSERT( elementJustOpened );
|
TIXMLASSERT( elementJustOpened );
|
||||||
Print( " %s=\"", name );
|
Print( " %s=\"", name );
|
||||||
|
@ -1422,7 +1422,7 @@ void XMLStreamer::PushAttribute( const char* name, const char* value )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void XMLStreamer::CloseElement()
|
void XMLPrinter::CloseElement()
|
||||||
{
|
{
|
||||||
--depth;
|
--depth;
|
||||||
const char* name = stack.Pop();
|
const char* name = stack.Pop();
|
||||||
|
@ -1446,14 +1446,14 @@ void XMLStreamer::CloseElement()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void XMLStreamer::SealElement()
|
void XMLPrinter::SealElement()
|
||||||
{
|
{
|
||||||
elementJustOpened = false;
|
elementJustOpened = false;
|
||||||
Print( ">" );
|
Print( ">" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void XMLStreamer::PushText( const char* text, bool cdata )
|
void XMLPrinter::PushText( const char* text, bool cdata )
|
||||||
{
|
{
|
||||||
textDepth = depth-1;
|
textDepth = depth-1;
|
||||||
|
|
||||||
|
@ -1471,7 +1471,7 @@ void XMLStreamer::PushText( const char* text, bool cdata )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void XMLStreamer::PushComment( const char* comment )
|
void XMLPrinter::PushComment( const char* comment )
|
||||||
{
|
{
|
||||||
if ( elementJustOpened ) {
|
if ( elementJustOpened ) {
|
||||||
SealElement();
|
SealElement();
|
||||||
|
@ -1485,7 +1485,7 @@ void XMLStreamer::PushComment( const char* comment )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void XMLStreamer::PushDeclaration( const char* value )
|
void XMLPrinter::PushDeclaration( const char* value )
|
||||||
{
|
{
|
||||||
if ( elementJustOpened ) {
|
if ( elementJustOpened ) {
|
||||||
SealElement();
|
SealElement();
|
||||||
|
@ -1499,7 +1499,7 @@ void XMLStreamer::PushDeclaration( const char* value )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void XMLStreamer::PushUnknown( const char* value )
|
void XMLPrinter::PushUnknown( const char* value )
|
||||||
{
|
{
|
||||||
if ( elementJustOpened ) {
|
if ( elementJustOpened ) {
|
||||||
SealElement();
|
SealElement();
|
||||||
|
@ -1513,7 +1513,7 @@ void XMLStreamer::PushUnknown( const char* value )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool XMLStreamer::VisitEnter( const XMLDocument& doc )
|
bool XMLPrinter::VisitEnter( const XMLDocument& doc )
|
||||||
{
|
{
|
||||||
if ( doc.HasBOM() ) {
|
if ( doc.HasBOM() ) {
|
||||||
PushHeader( true, false );
|
PushHeader( true, false );
|
||||||
|
@ -1522,7 +1522,7 @@ bool XMLStreamer::VisitEnter( const XMLDocument& doc )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool XMLStreamer::VisitEnter( const XMLElement& element, const XMLAttribute* attribute )
|
bool XMLPrinter::VisitEnter( const XMLElement& element, const XMLAttribute* attribute )
|
||||||
{
|
{
|
||||||
OpenElement( element.Name() );
|
OpenElement( element.Name() );
|
||||||
while ( attribute ) {
|
while ( attribute ) {
|
||||||
|
@ -1533,34 +1533,34 @@ bool XMLStreamer::VisitEnter( const XMLElement& element, const XMLAttribute* att
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool XMLStreamer::VisitExit( const XMLElement& element )
|
bool XMLPrinter::VisitExit( const XMLElement& element )
|
||||||
{
|
{
|
||||||
CloseElement();
|
CloseElement();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool XMLStreamer::Visit( const XMLText& text )
|
bool XMLPrinter::Visit( const XMLText& text )
|
||||||
{
|
{
|
||||||
PushText( text.Value(), text.CData() );
|
PushText( text.Value(), text.CData() );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool XMLStreamer::Visit( const XMLComment& comment )
|
bool XMLPrinter::Visit( const XMLComment& comment )
|
||||||
{
|
{
|
||||||
PushComment( comment.Value() );
|
PushComment( comment.Value() );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool XMLStreamer::Visit( const XMLDeclaration& declaration )
|
bool XMLPrinter::Visit( const XMLDeclaration& declaration )
|
||||||
{
|
{
|
||||||
PushDeclaration( declaration.Value() );
|
PushDeclaration( declaration.Value() );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool XMLStreamer::Visit( const XMLUnknown& unknown )
|
bool XMLPrinter::Visit( const XMLUnknown& unknown )
|
||||||
{
|
{
|
||||||
PushUnknown( unknown.Value() );
|
PushUnknown( unknown.Value() );
|
||||||
return true;
|
return true;
|
||||||
|
|
409
tinyxml2.h
409
tinyxml2.h
|
@ -1,36 +1,16 @@
|
||||||
#ifndef TINYXML_INCLUDED
|
#ifndef TINYXML_INCLUDED
|
||||||
#define TINYXML2_INCLUDED
|
#define TINYXML2_INCLUDED
|
||||||
|
|
||||||
/*
|
|
||||||
TODO
|
|
||||||
X const and non-const versions of API
|
|
||||||
X memory pool the class construction
|
|
||||||
X attribute accessors
|
|
||||||
X node navigation
|
|
||||||
- handles
|
|
||||||
X visit pattern - change streamer?
|
|
||||||
X make constructors protected
|
|
||||||
X hide copy constructor
|
|
||||||
X hide = operator
|
|
||||||
X UTF8 support: isAlpha, etc.
|
|
||||||
X string buffer for sets. (Grr.)
|
|
||||||
- MS BOM
|
|
||||||
X print to memory buffer
|
|
||||||
- tests from xml1
|
|
||||||
- xml1 tests especially UTF-8
|
|
||||||
- perf test: xml1
|
|
||||||
- perf test: xenowar
|
|
||||||
- test: load(char*)
|
|
||||||
- test: load(FILE*)
|
|
||||||
- rename declaration
|
|
||||||
- rename streamer
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
|
|
||||||
|
/* TODO: create main page description.
|
||||||
|
TODO: add 'lastAttribute' for faster parsing.
|
||||||
|
*/
|
||||||
|
|
||||||
#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
|
#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
|
||||||
#ifndef DEBUG
|
#ifndef DEBUG
|
||||||
#define DEBUG
|
#define DEBUG
|
||||||
|
@ -89,12 +69,12 @@ class XMLText;
|
||||||
class XMLDeclaration;
|
class XMLDeclaration;
|
||||||
class XMLUnknown;
|
class XMLUnknown;
|
||||||
|
|
||||||
class XMLStreamer;
|
class XMLPrinter;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A class that wraps strings. Normally stores the start and end
|
A class that wraps strings. Normally stores the start and end
|
||||||
pointers into the XML file itself, and will apply normalization
|
pointers into the XML file itself, and will apply normalization
|
||||||
and entity transalion if actually read. Can also store (and memory
|
and entity translation if actually read. Can also store (and memory
|
||||||
manage) a traditional char[]
|
manage) a traditional char[]
|
||||||
*/
|
*/
|
||||||
class StrPair
|
class StrPair
|
||||||
|
@ -380,20 +360,48 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** XMLNode is a base class for every object that is in the
|
||||||
|
XML Document Object Model (DOM), except XMLAttributes.
|
||||||
|
Nodes have siblings, a parent, and children which can
|
||||||
|
be navigated. A node is always in a XMLDocument.
|
||||||
|
The type of a TiXmlNode can be queried, and it can
|
||||||
|
be cast to its more defined type.
|
||||||
|
|
||||||
|
An XMLDocument allocates memory for all its Nodes.
|
||||||
|
When the XMLDocument gets deleted, all its Nodes
|
||||||
|
will also be deleted.
|
||||||
|
|
||||||
|
@verbatim
|
||||||
|
A Document can contain: Element (container or leaf)
|
||||||
|
Comment (leaf)
|
||||||
|
Unknown (leaf)
|
||||||
|
Declaration( leaf )
|
||||||
|
|
||||||
|
An Element can contain: Element (container or leaf)
|
||||||
|
Text (leaf)
|
||||||
|
Attributes (not on tree)
|
||||||
|
Comment (leaf)
|
||||||
|
Unknown (leaf)
|
||||||
|
|
||||||
|
@endverbatim
|
||||||
|
*/
|
||||||
class XMLNode
|
class XMLNode
|
||||||
{
|
{
|
||||||
friend class XMLDocument;
|
friend class XMLDocument;
|
||||||
friend class XMLElement;
|
friend class XMLElement;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/// Get the XMLDocument that owns this XMLNode.
|
||||||
const XMLDocument* GetDocument() const { return document; }
|
const XMLDocument* GetDocument() const { return document; }
|
||||||
|
/// Get the XMLDocument that owns this XMLNode.
|
||||||
XMLDocument* GetDocument() { return document; }
|
XMLDocument* GetDocument() { return document; }
|
||||||
|
|
||||||
virtual XMLElement* ToElement() { return 0; }
|
virtual XMLElement* ToElement() { return 0; } ///< Safely cast to an Element, or null.
|
||||||
virtual XMLText* ToText() { return 0; }
|
virtual XMLText* ToText() { return 0; } ///< Safely cast to Text, or null.
|
||||||
virtual XMLComment* ToComment() { return 0; }
|
virtual XMLComment* ToComment() { return 0; } ///< Safely cast to a Comment, or null.
|
||||||
virtual XMLDocument* ToDocument() { return 0; }
|
virtual XMLDocument* ToDocument() { return 0; } ///< Safely cast to a Document, or null.
|
||||||
virtual XMLDeclaration* ToDeclaration() { return 0; }
|
virtual XMLDeclaration* ToDeclaration() { return 0; } ///< Safely cast to a Declaration, or null.
|
||||||
virtual XMLUnknown* ToUnknown() { return 0; }
|
virtual XMLUnknown* ToUnknown() { return 0; } ///< Safely cast to an Unknown, or null.
|
||||||
|
|
||||||
virtual const XMLElement* ToElement() const { return 0; }
|
virtual const XMLElement* ToElement() const { return 0; }
|
||||||
virtual const XMLText* ToText() const { return 0; }
|
virtual const XMLText* ToText() const { return 0; }
|
||||||
|
@ -402,66 +410,111 @@ public:
|
||||||
virtual const XMLDeclaration* ToDeclaration() const { return 0; }
|
virtual const XMLDeclaration* ToDeclaration() const { return 0; }
|
||||||
virtual const XMLUnknown* ToUnknown() const { return 0; }
|
virtual const XMLUnknown* ToUnknown() const { return 0; }
|
||||||
|
|
||||||
|
/** The meaning of 'value' changes for the specific type.
|
||||||
|
@verbatim
|
||||||
|
Document: empy
|
||||||
|
Element: name of the element
|
||||||
|
Comment: the comment text
|
||||||
|
Unknown: the tag contents
|
||||||
|
Text: the text string
|
||||||
|
@endverbatim
|
||||||
|
*/
|
||||||
const char* Value() const { return value.GetStr(); }
|
const char* Value() const { return value.GetStr(); }
|
||||||
|
/** Set the Value of an XML node.
|
||||||
|
@sa Value()
|
||||||
|
*/
|
||||||
void SetValue( const char* val, bool staticMem=false );
|
void SetValue( const char* val, bool staticMem=false );
|
||||||
|
|
||||||
|
/// Get the parent of this node on the DOM.
|
||||||
const XMLNode* Parent() const { return parent; }
|
const XMLNode* Parent() const { return parent; }
|
||||||
XMLNode* Parent() { return parent; }
|
XMLNode* Parent() { return parent; }
|
||||||
|
|
||||||
/// Returns true if this node has no children.
|
/// Returns true if this node has no children.
|
||||||
bool NoChildren() const { return !firstChild; }
|
bool NoChildren() const { return !firstChild; }
|
||||||
|
|
||||||
|
/// Get the first child node, or null if none exists.
|
||||||
const XMLNode* FirstChild() const { return firstChild; }
|
const XMLNode* FirstChild() const { return firstChild; }
|
||||||
XMLNode* FirstChild() { return firstChild; }
|
XMLNode* FirstChild() { return firstChild; }
|
||||||
|
/** Get the first child element, or optionally the first child
|
||||||
|
element with the specified name.
|
||||||
|
*/
|
||||||
const XMLElement* FirstChildElement( const char* value=0 ) const;
|
const XMLElement* FirstChildElement( const char* value=0 ) const;
|
||||||
XMLElement* FirstChildElement( const char* value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value )); }
|
XMLElement* FirstChildElement( const char* value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value )); }
|
||||||
|
|
||||||
|
/// Get the last child node, or null if none exists.
|
||||||
const XMLNode* LastChild() const { return lastChild; }
|
const XMLNode* LastChild() const { return lastChild; }
|
||||||
XMLNode* LastChild() { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() ); }
|
XMLNode* LastChild() { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() ); }
|
||||||
|
|
||||||
|
/** Get the last child element or optionally the last child
|
||||||
|
element with the specified name.
|
||||||
|
*/
|
||||||
const XMLElement* LastChildElement( const char* value=0 ) const;
|
const XMLElement* LastChildElement( const char* value=0 ) const;
|
||||||
XMLElement* LastChildElement( const char* value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) ); }
|
XMLElement* LastChildElement( const char* value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) ); }
|
||||||
|
|
||||||
|
/// Get the previous (left) sibling node of this node.
|
||||||
const XMLNode* PreviousSibling() const { return prev; }
|
const XMLNode* PreviousSibling() const { return prev; }
|
||||||
XMLNode* PreviousSibling() { return prev; }
|
XMLNode* PreviousSibling() { return prev; }
|
||||||
|
|
||||||
|
/// Get the previous (left) sibling element of this node, with an opitionally supplied name.
|
||||||
const XMLNode* PreviousSiblingElement( const char* value=0 ) const ;
|
const XMLNode* PreviousSiblingElement( const char* value=0 ) const ;
|
||||||
XMLNode* PreviousSiblingElement( const char* value=0 ) { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) ); }
|
XMLNode* PreviousSiblingElement( const char* value=0 ) { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) ); }
|
||||||
|
|
||||||
|
/// Get the next (right) sibling node of this node.
|
||||||
const XMLNode* NextSibling() const { return next; }
|
const XMLNode* NextSibling() const { return next; }
|
||||||
XMLNode* NextSibling() { return next; }
|
XMLNode* NextSibling() { return next; }
|
||||||
|
|
||||||
|
/// Get the next (right) sibling element of this node, with an opitionally supplied name.
|
||||||
const XMLNode* NextSiblingElement( const char* value=0 ) const;
|
const XMLNode* NextSiblingElement( const char* value=0 ) const;
|
||||||
XMLNode* NextSiblingElement( const char* value=0 ) { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) ); }
|
XMLNode* NextSiblingElement( const char* value=0 ) { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) ); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Add a child node as the last (right) child.
|
||||||
Tests: Programmatic DOM
|
|
||||||
*/
|
*/
|
||||||
XMLNode* InsertEndChild( XMLNode* addThis );
|
XMLNode* InsertEndChild( XMLNode* addThis );
|
||||||
/**
|
/**
|
||||||
|
Add a child node as the first (left) child.
|
||||||
Tests: Programmatic DOM
|
|
||||||
*/
|
*/
|
||||||
XMLNode* InsertFirstChild( XMLNode* addThis );
|
XMLNode* InsertFirstChild( XMLNode* addThis );
|
||||||
/**
|
/**
|
||||||
|
Add a node after the specified child node.
|
||||||
Tests: Programmatic DOM
|
|
||||||
*/
|
*/
|
||||||
XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
|
XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Tests: All (used by destructor)
|
Delete all the children of this node.
|
||||||
*/
|
*/
|
||||||
void ClearChildren();
|
void DeleteChildren();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Tests: Progammatic DOM
|
Delete a child of this node.
|
||||||
*/
|
*/
|
||||||
void DeleteChild( XMLNode* node );
|
void DeleteChild( XMLNode* node );
|
||||||
|
|
||||||
|
/** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the
|
||||||
|
XML tree will be conditionally visited and the host will be called back
|
||||||
|
via the TiXmlVisitor interface.
|
||||||
|
|
||||||
|
This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse
|
||||||
|
the XML for the callbacks, so the performance of TinyXML is unchanged by using this
|
||||||
|
interface versus any other.)
|
||||||
|
|
||||||
|
The interface has been based on ideas from:
|
||||||
|
|
||||||
|
- http://www.saxproject.org/
|
||||||
|
- http://c2.com/cgi/wiki?HierarchicalVisitorPattern
|
||||||
|
|
||||||
|
Which are both good references for "visiting".
|
||||||
|
|
||||||
|
An example of using Accept():
|
||||||
|
@verbatim
|
||||||
|
TiXmlPrinter printer;
|
||||||
|
tinyxmlDoc.Accept( &printer );
|
||||||
|
const char* xmlcstr = printer.CStr();
|
||||||
|
@endverbatim
|
||||||
|
*/
|
||||||
virtual bool Accept( XMLVisitor* visitor ) const = 0;
|
virtual bool Accept( XMLVisitor* visitor ) const = 0;
|
||||||
|
|
||||||
|
// internal
|
||||||
virtual char* ParseDeep( char*, StrPair* );
|
virtual char* ParseDeep( char*, StrPair* );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -486,6 +539,18 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** XML text.
|
||||||
|
|
||||||
|
Note that a text node can have child element nodes, for example:
|
||||||
|
@verbatim
|
||||||
|
<root>This is <b>bold</b></root>
|
||||||
|
@endverbatim
|
||||||
|
|
||||||
|
A text node can have 2 ways to output the next. "normal" output
|
||||||
|
and CDATA. It will default to the mode it was parsed from the XML file and
|
||||||
|
you generally want to leave it alone, but you can change the output mode with
|
||||||
|
SetCDATA() and query it with CDATA().
|
||||||
|
*/
|
||||||
class XMLText : public XMLNode
|
class XMLText : public XMLNode
|
||||||
{
|
{
|
||||||
friend class XMLBase;
|
friend class XMLBase;
|
||||||
|
@ -496,7 +561,9 @@ public:
|
||||||
virtual XMLText* ToText() { return this; }
|
virtual XMLText* ToText() { return this; }
|
||||||
virtual const XMLText* ToText() const { return this; }
|
virtual const XMLText* ToText() const { return this; }
|
||||||
|
|
||||||
void SetCData( bool value ) { isCData = true; }
|
/// Declare whether this should be CDATA or standard text.
|
||||||
|
void SetCData( bool isCData ) { this->isCData = isCData; }
|
||||||
|
/// Returns true if this is a CDATA text element.
|
||||||
bool CData() const { return isCData; }
|
bool CData() const { return isCData; }
|
||||||
|
|
||||||
char* ParseDeep( char*, StrPair* endTag );
|
char* ParseDeep( char*, StrPair* endTag );
|
||||||
|
@ -512,6 +579,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** An XML Comment. */
|
||||||
class XMLComment : public XMLNode
|
class XMLComment : public XMLNode
|
||||||
{
|
{
|
||||||
friend class XMLDocument;
|
friend class XMLDocument;
|
||||||
|
@ -533,6 +601,17 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** In correct XML the declaration is the first entry in the file.
|
||||||
|
@verbatim
|
||||||
|
<?xml version="1.0" standalone="yes"?>
|
||||||
|
@endverbatim
|
||||||
|
|
||||||
|
TinyXML2 will happily read or write files without a declaration,
|
||||||
|
however.
|
||||||
|
|
||||||
|
The text of the declaration isn't interpreted. It is parsed
|
||||||
|
and written as a string.
|
||||||
|
*/
|
||||||
class XMLDeclaration : public XMLNode
|
class XMLDeclaration : public XMLNode
|
||||||
{
|
{
|
||||||
friend class XMLDocument;
|
friend class XMLDocument;
|
||||||
|
@ -552,6 +631,13 @@ protected:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** Any tag that tinyXml doesn't recognize is saved as an
|
||||||
|
unknown. It is a tag of text, but should not be modified.
|
||||||
|
It will be written back to the XML, unchanged, when the file
|
||||||
|
is saved.
|
||||||
|
|
||||||
|
DTD tags get thrown into TiXmlUnknowns.
|
||||||
|
*/
|
||||||
class XMLUnknown : public XMLNode
|
class XMLUnknown : public XMLNode
|
||||||
{
|
{
|
||||||
friend class XMLDocument;
|
friend class XMLDocument;
|
||||||
|
@ -593,31 +679,59 @@ enum {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** An attribute is a name-value pair. Elements have an arbitrary
|
||||||
|
number of attributes, each with a unique name.
|
||||||
|
|
||||||
|
@note The attributes are not XMLNodes. You may only query the
|
||||||
|
Next() attribute in a list.
|
||||||
|
*/
|
||||||
class XMLAttribute
|
class XMLAttribute
|
||||||
{
|
{
|
||||||
friend class XMLElement;
|
friend class XMLElement;
|
||||||
public:
|
public:
|
||||||
const char* Name() const { return name.GetStr(); }
|
const char* Name() const { return name.GetStr(); } ///< The name of the attribute.
|
||||||
const char* Value() const { return value.GetStr(); }
|
const char* Value() const { return value.GetStr(); } ///< The value of the attribute.
|
||||||
const XMLAttribute* Next() const { return next; }
|
const XMLAttribute* Next() const { return next; } ///< The next attribute in the list.
|
||||||
|
|
||||||
|
/** IntAttribute interprets the attribute as an integer, and returns the value.
|
||||||
|
If the value isn't an integer, 0 will be returned. There is no error checking;
|
||||||
|
use QueryIntAttribute() if you need error checking.
|
||||||
|
*/
|
||||||
int IntAttribute( const char* name ) const { int i=0; QueryIntAttribute( &i ); return i; }
|
int IntAttribute( const char* name ) const { int i=0; QueryIntAttribute( &i ); return i; }
|
||||||
|
/// Query as an unsigned integer. See IntAttribute()
|
||||||
unsigned UnsignedAttribute( const char* name ) const{ unsigned i=0; QueryUnsignedAttribute( &i ); return i; }
|
unsigned UnsignedAttribute( const char* name ) const{ unsigned i=0; QueryUnsignedAttribute( &i ); return i; }
|
||||||
|
/// Query as a boolean. See IntAttribute()
|
||||||
bool BoolAttribute( const char* name ) const { bool b=false; QueryBoolAttribute( &b ); return b; }
|
bool BoolAttribute( const char* name ) const { bool b=false; QueryBoolAttribute( &b ); return b; }
|
||||||
|
/// Query as a double. See IntAttribute()
|
||||||
double DoubleAttribute( const char* name ) const { double d=0; QueryDoubleAttribute( &d ); return d; }
|
double DoubleAttribute( const char* name ) const { double d=0; QueryDoubleAttribute( &d ); return d; }
|
||||||
|
/// Query as a float. See IntAttribute()
|
||||||
float FloatAttribute( const char* name ) const { float f=0; QueryFloatAttribute( &f ); return f; }
|
float FloatAttribute( const char* name ) const { float f=0; QueryFloatAttribute( &f ); return f; }
|
||||||
|
|
||||||
|
/** QueryIntAttribute interprets the attribute as an integer, and returns the value
|
||||||
|
in the provided paremeter. The function will return XML_NO_ERROR on success,
|
||||||
|
and WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
|
||||||
|
*/
|
||||||
int QueryIntAttribute( int* value ) const;
|
int QueryIntAttribute( int* value ) const;
|
||||||
|
/// See QueryIntAttribute
|
||||||
int QueryUnsignedAttribute( unsigned int* value ) const;
|
int QueryUnsignedAttribute( unsigned int* value ) const;
|
||||||
|
/// See QueryIntAttribute
|
||||||
int QueryBoolAttribute( bool* value ) const;
|
int QueryBoolAttribute( bool* value ) const;
|
||||||
|
/// See QueryIntAttribute
|
||||||
int QueryDoubleAttribute( double* value ) const;
|
int QueryDoubleAttribute( double* value ) const;
|
||||||
|
/// See QueryIntAttribute
|
||||||
int QueryFloatAttribute( float* value ) const;
|
int QueryFloatAttribute( float* value ) const;
|
||||||
|
|
||||||
|
/// Set the attribute to a string value.
|
||||||
void SetAttribute( const char* value );
|
void SetAttribute( const char* value );
|
||||||
|
/// Set the attribute to value.
|
||||||
void SetAttribute( int value );
|
void SetAttribute( int value );
|
||||||
|
/// Set the attribute to value.
|
||||||
void SetAttribute( unsigned value );
|
void SetAttribute( unsigned value );
|
||||||
|
/// Set the attribute to value.
|
||||||
void SetAttribute( bool value );
|
void SetAttribute( bool value );
|
||||||
|
/// Set the attribute to value.
|
||||||
void SetAttribute( double value );
|
void SetAttribute( double value );
|
||||||
|
/// Set the attribute to value.
|
||||||
void SetAttribute( float value );
|
void SetAttribute( float value );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -638,46 +752,116 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** The element is a container class. It has a value, the element name,
|
||||||
|
and can contain other elements, text, comments, and unknowns.
|
||||||
|
Elements also contain an arbitrary number of attributes.
|
||||||
|
*/
|
||||||
class XMLElement : public XMLNode
|
class XMLElement : public XMLNode
|
||||||
{
|
{
|
||||||
friend class XMLBase;
|
friend class XMLBase;
|
||||||
friend class XMLDocument;
|
friend class XMLDocument;
|
||||||
public:
|
public:
|
||||||
|
/// Get the name of an element (which is the Value() of the node.)
|
||||||
const char* Name() const { return Value(); }
|
const char* Name() const { return Value(); }
|
||||||
|
/// Set the name of the element.
|
||||||
void SetName( const char* str, bool staticMem=false ) { SetValue( str, staticMem ); }
|
void SetName( const char* str, bool staticMem=false ) { SetValue( str, staticMem ); }
|
||||||
|
|
||||||
virtual XMLElement* ToElement() { return this; }
|
virtual XMLElement* ToElement() { return this; }
|
||||||
virtual const XMLElement* ToElement() const { return this; }
|
virtual const XMLElement* ToElement() const { return this; }
|
||||||
virtual bool Accept( XMLVisitor* visitor ) const;
|
virtual bool Accept( XMLVisitor* visitor ) const;
|
||||||
|
|
||||||
|
/** Given an attribute name, Attribute() returns the value
|
||||||
|
for the attribute of that name, or null if none exists.
|
||||||
|
*/
|
||||||
const char* Attribute( const char* name ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return 0; return a->Value(); }
|
const char* Attribute( const char* name ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return 0; return a->Value(); }
|
||||||
|
|
||||||
|
/** Given an attribute name, IntAttribute() returns the value
|
||||||
|
of the attribute interpreted as an integer. 0 will be
|
||||||
|
returned if there is an error. For a method with error
|
||||||
|
checking, see QueryIntAttribute()
|
||||||
|
*/
|
||||||
int IntAttribute( const char* name ) const { int i=0; QueryIntAttribute( name, &i ); return i; }
|
int IntAttribute( const char* name ) const { int i=0; QueryIntAttribute( name, &i ); return i; }
|
||||||
|
/// See IntAttribute()
|
||||||
unsigned UnsignedAttribute( const char* name ) const{ unsigned i=0; QueryUnsignedAttribute( name, &i ); return i; }
|
unsigned UnsignedAttribute( const char* name ) const{ unsigned i=0; QueryUnsignedAttribute( name, &i ); return i; }
|
||||||
|
/// See IntAttribute()
|
||||||
bool BoolAttribute( const char* name ) const { bool b=false; QueryBoolAttribute( name, &b ); return b; }
|
bool BoolAttribute( const char* name ) const { bool b=false; QueryBoolAttribute( name, &b ); return b; }
|
||||||
|
/// See IntAttribute()
|
||||||
double DoubleAttribute( const char* name ) const { double d=0; QueryDoubleAttribute( name, &d ); return d; }
|
double DoubleAttribute( const char* name ) const { double d=0; QueryDoubleAttribute( name, &d ); return d; }
|
||||||
|
/// See IntAttribute()
|
||||||
float FloatAttribute( const char* name ) const { float f=0; QueryFloatAttribute( name, &f ); return f; }
|
float FloatAttribute( const char* name ) const { float f=0; QueryFloatAttribute( name, &f ); return f; }
|
||||||
|
|
||||||
|
/** Given an attribute name, QueryIntAttribute() returns
|
||||||
|
XML_NO_ERROR, WRONG_ATTRIBUTE_TYPE if the conversion
|
||||||
|
can't be performed, or NO_ATTRIBUTE if the attribute
|
||||||
|
doesn't exist. If successful, the result of the conversion
|
||||||
|
will be written to 'value'. If not successful, nothing will
|
||||||
|
be written to 'value'. This allows you to provide default
|
||||||
|
value:
|
||||||
|
|
||||||
|
@verbatim
|
||||||
|
int value = 10;
|
||||||
|
QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
|
||||||
|
@endverbatim
|
||||||
|
*/
|
||||||
int QueryIntAttribute( const char* name, int* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryIntAttribute( value ); }
|
int QueryIntAttribute( const char* name, int* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryIntAttribute( value ); }
|
||||||
|
/// See QueryIntAttribute()
|
||||||
int QueryUnsignedAttribute( const char* name, unsigned int* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryUnsignedAttribute( value ); }
|
int QueryUnsignedAttribute( const char* name, unsigned int* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryUnsignedAttribute( value ); }
|
||||||
|
/// See QueryIntAttribute()
|
||||||
int QueryBoolAttribute( const char* name, bool* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryBoolAttribute( value ); }
|
int QueryBoolAttribute( const char* name, bool* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryBoolAttribute( value ); }
|
||||||
|
/// See QueryIntAttribute()
|
||||||
int QueryDoubleAttribute( const char* name, double* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryDoubleAttribute( value ); }
|
int QueryDoubleAttribute( const char* name, double* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryDoubleAttribute( value ); }
|
||||||
|
/// See QueryIntAttribute()
|
||||||
int QueryFloatAttribute( const char* name, float* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryFloatAttribute( value ); }
|
int QueryFloatAttribute( const char* name, float* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryFloatAttribute( value ); }
|
||||||
|
|
||||||
|
/// Sets the named attribute to value.
|
||||||
void SetAttribute( const char* name, const char* value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
|
void SetAttribute( const char* name, const char* value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
|
||||||
|
/// Sets the named attribute to value.
|
||||||
void SetAttribute( const char* name, int value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
|
void SetAttribute( const char* name, int value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
|
||||||
|
/// Sets the named attribute to value.
|
||||||
void SetAttribute( const char* name, unsigned value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
|
void SetAttribute( const char* name, unsigned value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
|
||||||
|
/// Sets the named attribute to value.
|
||||||
void SetAttribute( const char* name, bool value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
|
void SetAttribute( const char* name, bool value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
|
||||||
|
/// Sets the named attribute to value.
|
||||||
void SetAttribute( const char* name, double value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
|
void SetAttribute( const char* name, double value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Tests: Programmatic DOM
|
Delete an attribute.
|
||||||
*/
|
*/
|
||||||
void DeleteAttribute( const char* name );
|
void DeleteAttribute( const char* name );
|
||||||
|
|
||||||
|
/// Return the first attribute in the list.
|
||||||
const XMLAttribute* FirstAttribute() const { return rootAttribute; }
|
const XMLAttribute* FirstAttribute() const { return rootAttribute; }
|
||||||
|
/// Query a specific attribute in the list.
|
||||||
const XMLAttribute* FindAttribute( const char* name ) const;
|
const XMLAttribute* FindAttribute( const char* name ) const;
|
||||||
|
|
||||||
|
/** Convenience function for easy access to the text inside an element. Although easy
|
||||||
|
and concise, GetText() is limited compared to getting the TiXmlText child
|
||||||
|
and accessing it directly.
|
||||||
|
|
||||||
|
If the first child of 'this' is a TiXmlText, the GetText()
|
||||||
|
returns the character string of the Text node, else null is returned.
|
||||||
|
|
||||||
|
This is a convenient method for getting the text of simple contained text:
|
||||||
|
@verbatim
|
||||||
|
<foo>This is text</foo>
|
||||||
|
const char* str = fooElement->GetText();
|
||||||
|
@endverbatim
|
||||||
|
|
||||||
|
'str' will be a pointer to "This is text".
|
||||||
|
|
||||||
|
Note that this function can be misleading. If the element foo was created from
|
||||||
|
this XML:
|
||||||
|
@verbatim
|
||||||
|
<foo><b>This is text</b></foo>
|
||||||
|
@endverbatim
|
||||||
|
|
||||||
|
then the value of str would be null. The first child node isn't a text node, it is
|
||||||
|
another element. From this XML:
|
||||||
|
@verbatim
|
||||||
|
<foo>This is <b>text</b></foo>
|
||||||
|
@endverbatim
|
||||||
|
GetText() will return "This is ".
|
||||||
|
*/
|
||||||
const char* GetText() const;
|
const char* GetText() const;
|
||||||
|
|
||||||
// internal:
|
// internal:
|
||||||
|
@ -705,54 +889,111 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** A document binds together all the functionality.
|
||||||
|
It can be saved, loaded, and printed to the screen.
|
||||||
|
All Nodes are connected and allocated to a Document.
|
||||||
|
If the Document is deleted, all its Nodes are also deleted.
|
||||||
|
*/
|
||||||
class XMLDocument : public XMLNode
|
class XMLDocument : public XMLNode
|
||||||
{
|
{
|
||||||
friend class XMLElement;
|
friend class XMLElement;
|
||||||
public:
|
public:
|
||||||
|
/// constructor
|
||||||
XMLDocument();
|
XMLDocument();
|
||||||
~XMLDocument();
|
~XMLDocument();
|
||||||
|
|
||||||
virtual XMLDocument* ToDocument() { return this; }
|
virtual XMLDocument* ToDocument() { return this; }
|
||||||
virtual const XMLDocument* ToDocument() const { return this; }
|
virtual const XMLDocument* ToDocument() const { return this; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
Parse an XML file from a character string.
|
||||||
|
Returns XML_NO_ERROR (0) on success, or
|
||||||
|
an errorID.
|
||||||
|
*/
|
||||||
int Parse( const char* xml );
|
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 );
|
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* );
|
int LoadFile( FILE* );
|
||||||
|
/**
|
||||||
|
Save the XML file to disk.
|
||||||
|
*/
|
||||||
void SaveFile( const char* filename );
|
void SaveFile( const char* filename );
|
||||||
|
|
||||||
bool HasBOM() const { return writeBOM; }
|
bool HasBOM() const { return writeBOM; }
|
||||||
|
|
||||||
|
/** Return the root element of DOM. Equivalent to FirstChildElement().
|
||||||
|
To get the first node, use FirstChild().
|
||||||
|
*/
|
||||||
XMLElement* RootElement() { return FirstChildElement(); }
|
XMLElement* RootElement() { return FirstChildElement(); }
|
||||||
const XMLElement* RootElement() const { return FirstChildElement(); }
|
const XMLElement* RootElement() const { return FirstChildElement(); }
|
||||||
|
|
||||||
void Print( XMLStreamer* streamer=0 );
|
/** Print the Document. If the Printer is not provided, it will
|
||||||
|
print to stdout. If you provide Printer, this can print to a file:
|
||||||
|
@verbatim
|
||||||
|
XMLPrinter printer( fp );
|
||||||
|
doc.Print( &printer );
|
||||||
|
@endverbatim
|
||||||
|
|
||||||
|
Or you can use a printer to print to memory:
|
||||||
|
@verbatim
|
||||||
|
XMLPrinter printer;
|
||||||
|
doc->Print( &printer );
|
||||||
|
SomeFunctior( printer.CStr() );
|
||||||
|
@endverbatim
|
||||||
|
*/
|
||||||
|
void Print( XMLPrinter* streamer=0 );
|
||||||
virtual bool Accept( XMLVisitor* visitor ) const;
|
virtual bool Accept( XMLVisitor* visitor ) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Tests: Programmatic DOM
|
Create a new Element associated with
|
||||||
|
this Document. The memory for the Element
|
||||||
|
is managed by the Document.
|
||||||
*/
|
*/
|
||||||
XMLElement* NewElement( const char* name );
|
XMLElement* NewElement( const char* name );
|
||||||
/**
|
/**
|
||||||
Tests: Programmatic DOM
|
Create a new Comment associated with
|
||||||
|
this Document. The memory for the Comment
|
||||||
|
is managed by the Document.
|
||||||
*/
|
*/
|
||||||
XMLComment* NewComment( const char* comment );
|
XMLComment* NewComment( const char* comment );
|
||||||
/**
|
/**
|
||||||
Tests: Programmatic DOM
|
Create a new Text associated with
|
||||||
|
this Document. The memory for the Text
|
||||||
|
is managed by the Document.
|
||||||
*/
|
*/
|
||||||
XMLText* NewText( const char* text );
|
XMLText* NewText( const char* text );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Tests: Programmatic DOM
|
Delete a node associated with this documented.
|
||||||
|
It will be unlinked from the DOM.
|
||||||
*/
|
*/
|
||||||
void DeleteNode( XMLNode* node ) { node->parent->DeleteChild( node ); }
|
void DeleteNode( XMLNode* node ) { node->parent->DeleteChild( node ); }
|
||||||
|
|
||||||
void SetError( int error, const char* str1, const char* str2 );
|
void SetError( int error, const char* str1, const char* str2 );
|
||||||
|
|
||||||
|
/// Return true if there was an error parsing the document.
|
||||||
bool Error() const { return errorID != XML_NO_ERROR; }
|
bool Error() const { return errorID != XML_NO_ERROR; }
|
||||||
|
/// Return the errorID.
|
||||||
int ErrorID() const { return errorID; }
|
int ErrorID() const { return errorID; }
|
||||||
|
/// Return a possibly helpful diagnostic location or string.
|
||||||
const char* GetErrorStr1() const { return errorStr1; }
|
const char* GetErrorStr1() const { return errorStr1; }
|
||||||
|
/// Return possibly helpful secondary diagnostic location or string.
|
||||||
const char* GetErrorStr2() const { return errorStr2; }
|
const char* GetErrorStr2() const { return errorStr2; }
|
||||||
|
/// If there is an error, print it to stdout
|
||||||
void PrintError() const;
|
void PrintError() const;
|
||||||
|
|
||||||
|
// internal
|
||||||
char* Identify( char* p, XMLNode** node );
|
char* Identify( char* p, XMLNode** node );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -773,19 +1014,75 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class XMLStreamer : public XMLVisitor
|
|
||||||
|
/**
|
||||||
|
Printing functionality. The XMLPrinter gives you more
|
||||||
|
options than the XMLDocument::Print() method.
|
||||||
|
|
||||||
|
It can:
|
||||||
|
-# Print to memory.
|
||||||
|
-# Print to a file you provide
|
||||||
|
-# Print XML without a XMLDocument.
|
||||||
|
|
||||||
|
Print to Memory
|
||||||
|
|
||||||
|
@verbatim
|
||||||
|
XMLPrinter printer;
|
||||||
|
doc->Print( &printer );
|
||||||
|
SomeFunctior( printer.CStr() );
|
||||||
|
@endverbatim
|
||||||
|
|
||||||
|
Print to a File
|
||||||
|
|
||||||
|
You provide the file pointer.
|
||||||
|
@verbatim
|
||||||
|
XMLPrinter printer( fp );
|
||||||
|
doc.Print( &printer );
|
||||||
|
@endverbatim
|
||||||
|
|
||||||
|
Print without a XMLDocument
|
||||||
|
|
||||||
|
When loading, an XML parser is very useful. However, sometimes
|
||||||
|
when saving, it just gets in the way. The code is often set up
|
||||||
|
for streaming, and constructing the DOM is just overhead.
|
||||||
|
|
||||||
|
The Printer supports the streaming case. The following code
|
||||||
|
prints out a trivially simple XML file without ever creating
|
||||||
|
an XML document.
|
||||||
|
|
||||||
|
@verbatim
|
||||||
|
XMLPrinter printer( fp );
|
||||||
|
printer.OpenElement( "foo" );
|
||||||
|
printer.PushAttribute( "foo", "bar" );
|
||||||
|
printer.CloseElement();
|
||||||
|
@endverbatim
|
||||||
|
*/
|
||||||
|
class XMLPrinter : public XMLVisitor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
XMLStreamer( FILE* file=0 );
|
/** Construct the printer. If the FILE* is specified,
|
||||||
~XMLStreamer() {}
|
this will print to the FILE. Else it will print
|
||||||
|
to memory, and the result is available in CStr()
|
||||||
|
*/
|
||||||
|
XMLPrinter( FILE* file=0 );
|
||||||
|
~XMLPrinter() {}
|
||||||
|
|
||||||
|
/** If streaming, write the BOM and declaration. */
|
||||||
void PushHeader( bool writeBOM, bool writeDeclaration );
|
void PushHeader( bool writeBOM, bool writeDeclaration );
|
||||||
|
/** If streaming, start writing an element.
|
||||||
|
The element must be closed with CloseElement()
|
||||||
|
*/
|
||||||
void OpenElement( const char* name );
|
void OpenElement( const char* name );
|
||||||
|
/// If streaming, add an attribute to an open element.
|
||||||
void PushAttribute( const char* name, const char* value );
|
void PushAttribute( const char* name, const char* value );
|
||||||
|
/// If streaming, close the Element.
|
||||||
void CloseElement();
|
void CloseElement();
|
||||||
|
|
||||||
|
/// Add a text node.
|
||||||
void PushText( const char* text, bool cdata=false );
|
void PushText( const char* text, bool cdata=false );
|
||||||
|
/// Add a comment
|
||||||
void PushComment( const char* comment );
|
void PushComment( const char* comment );
|
||||||
|
|
||||||
void PushDeclaration( const char* value );
|
void PushDeclaration( const char* value );
|
||||||
void PushUnknown( const char* value );
|
void PushUnknown( const char* value );
|
||||||
|
|
||||||
|
@ -800,6 +1097,10 @@ public:
|
||||||
virtual bool Visit( const XMLDeclaration& declaration );
|
virtual bool Visit( const XMLDeclaration& declaration );
|
||||||
virtual bool Visit( const XMLUnknown& unknown );
|
virtual bool Visit( const XMLUnknown& unknown );
|
||||||
|
|
||||||
|
/**
|
||||||
|
If in print to memory mode, return a pointer to
|
||||||
|
the XML file in memory.
|
||||||
|
*/
|
||||||
const char* CStr() const { return buffer.Mem(); }
|
const char* CStr() const { return buffer.Mem(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
40
xmltest.cpp
40
xmltest.cpp
|
@ -4,7 +4,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#if defined( WIN32 )
|
#if defined( _MSC_VER )
|
||||||
#include <crtdbg.h>
|
#include <crtdbg.h>
|
||||||
_CrtMemState startMemState;
|
_CrtMemState startMemState;
|
||||||
_CrtMemState endMemState;
|
_CrtMemState endMemState;
|
||||||
|
@ -14,35 +14,6 @@ using namespace tinyxml2;
|
||||||
int gPass = 0;
|
int gPass = 0;
|
||||||
int gFail = 0;
|
int gFail = 0;
|
||||||
|
|
||||||
//#define DREAM_ONLY
|
|
||||||
|
|
||||||
/*
|
|
||||||
int gNew = 0;
|
|
||||||
int gNewTotal = 0;
|
|
||||||
|
|
||||||
void* operator new( size_t size )
|
|
||||||
{
|
|
||||||
++gNew;
|
|
||||||
return malloc( size );
|
|
||||||
}
|
|
||||||
|
|
||||||
void* operator new[]( size_t size )
|
|
||||||
{
|
|
||||||
++gNew;
|
|
||||||
return malloc( size );
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator delete[]( void* mem )
|
|
||||||
{
|
|
||||||
free( mem );
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator delete( void* mem )
|
|
||||||
{
|
|
||||||
free( mem );
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
bool XMLTest (const char* testString, const char* expected, const char* found, bool echo=true )
|
bool XMLTest (const char* testString, const char* expected, const char* found, bool echo=true )
|
||||||
{
|
{
|
||||||
|
@ -100,7 +71,7 @@ void NullLineEndings( char* p )
|
||||||
|
|
||||||
int main( int argc, const char* argv )
|
int main( int argc, const char* argv )
|
||||||
{
|
{
|
||||||
#if defined( WIN32 )
|
#if defined( _MSC_VER )
|
||||||
_CrtMemCheckpoint( &startMemState );
|
_CrtMemCheckpoint( &startMemState );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -201,7 +172,7 @@ int main( int argc, const char* argv )
|
||||||
|
|
||||||
doc->Print();
|
doc->Print();
|
||||||
|
|
||||||
XMLStreamer streamer;
|
XMLPrinter streamer;
|
||||||
doc->Print( &streamer );
|
doc->Print( &streamer );
|
||||||
printf( "%s", streamer.CStr() );
|
printf( "%s", streamer.CStr() );
|
||||||
|
|
||||||
|
@ -447,7 +418,7 @@ int main( int argc, const char* argv )
|
||||||
FILE* textfile = fopen( "textfile.txt", "w" );
|
FILE* textfile = fopen( "textfile.txt", "w" );
|
||||||
if ( textfile )
|
if ( textfile )
|
||||||
{
|
{
|
||||||
XMLStreamer streamer( textfile );
|
XMLPrinter streamer( textfile );
|
||||||
psg->Accept( &streamer );
|
psg->Accept( &streamer );
|
||||||
fclose( textfile );
|
fclose( textfile );
|
||||||
}
|
}
|
||||||
|
@ -637,7 +608,8 @@ int main( int argc, const char* argv )
|
||||||
XMLTest( "Infinite loop test.", true, true );
|
XMLTest( "Infinite loop test.", true, true );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined( WIN32 )
|
|
||||||
|
#if defined( _MSC_VER )
|
||||||
_CrtMemCheckpoint( &endMemState );
|
_CrtMemCheckpoint( &endMemState );
|
||||||
//_CrtMemDumpStatistics( &endMemState );
|
//_CrtMemDumpStatistics( &endMemState );
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue