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()
|
||||
{
|
||||
ClearChildren();
|
||||
DeleteChildren();
|
||||
if ( parent ) {
|
||||
parent->Unlink( this );
|
||||
}
|
||||
|
@ -464,7 +464,7 @@ void XMLNode::SetValue( const char* str, bool staticMem )
|
|||
}
|
||||
|
||||
|
||||
void XMLNode::ClearChildren()
|
||||
void XMLNode::DeleteChildren()
|
||||
{
|
||||
while( firstChild ) {
|
||||
XMLNode* node = firstChild;
|
||||
|
@ -1106,7 +1106,7 @@ XMLDocument::XMLDocument() :
|
|||
|
||||
XMLDocument::~XMLDocument()
|
||||
{
|
||||
ClearChildren();
|
||||
DeleteChildren();
|
||||
delete [] charBuffer;
|
||||
|
||||
#if 0
|
||||
|
@ -1164,7 +1164,7 @@ XMLText* XMLDocument::NewText( const char* str )
|
|||
|
||||
int XMLDocument::LoadFile( const char* filename )
|
||||
{
|
||||
ClearChildren();
|
||||
DeleteChildren();
|
||||
InitDocument();
|
||||
|
||||
FILE* fp = fopen( filename, "rb" );
|
||||
|
@ -1180,7 +1180,7 @@ int XMLDocument::LoadFile( const char* filename )
|
|||
|
||||
int XMLDocument::LoadFile( FILE* fp )
|
||||
{
|
||||
ClearChildren();
|
||||
DeleteChildren();
|
||||
InitDocument();
|
||||
|
||||
fseek( fp, 0, SEEK_END );
|
||||
|
@ -1211,7 +1211,7 @@ int XMLDocument::LoadFile( FILE* fp )
|
|||
void XMLDocument::SaveFile( const char* filename )
|
||||
{
|
||||
FILE* fp = fopen( filename, "w" );
|
||||
XMLStreamer stream( fp );
|
||||
XMLPrinter stream( fp );
|
||||
Print( &stream );
|
||||
fclose( fp );
|
||||
}
|
||||
|
@ -1219,7 +1219,7 @@ void XMLDocument::SaveFile( const char* filename )
|
|||
|
||||
int XMLDocument::Parse( const char* p )
|
||||
{
|
||||
ClearChildren();
|
||||
DeleteChildren();
|
||||
InitDocument();
|
||||
|
||||
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 )
|
||||
streamer = &stdStreamer;
|
||||
Accept( streamer );
|
||||
|
@ -1281,7 +1281,7 @@ void XMLDocument::PrintError() const
|
|||
}
|
||||
|
||||
|
||||
XMLStreamer::XMLStreamer( FILE* file ) :
|
||||
XMLPrinter::XMLPrinter( FILE* file ) :
|
||||
elementJustOpened( false ),
|
||||
firstElement( true ),
|
||||
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_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 ) {
|
||||
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.
|
||||
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 };
|
||||
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 ) {
|
||||
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 );
|
||||
Print( " %s=\"", name );
|
||||
|
@ -1422,7 +1422,7 @@ void XMLStreamer::PushAttribute( const char* name, const char* value )
|
|||
}
|
||||
|
||||
|
||||
void XMLStreamer::CloseElement()
|
||||
void XMLPrinter::CloseElement()
|
||||
{
|
||||
--depth;
|
||||
const char* name = stack.Pop();
|
||||
|
@ -1446,14 +1446,14 @@ void XMLStreamer::CloseElement()
|
|||
}
|
||||
|
||||
|
||||
void XMLStreamer::SealElement()
|
||||
void XMLPrinter::SealElement()
|
||||
{
|
||||
elementJustOpened = false;
|
||||
Print( ">" );
|
||||
}
|
||||
|
||||
|
||||
void XMLStreamer::PushText( const char* text, bool cdata )
|
||||
void XMLPrinter::PushText( const char* text, bool cdata )
|
||||
{
|
||||
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 ) {
|
||||
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 ) {
|
||||
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 ) {
|
||||
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() ) {
|
||||
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() );
|
||||
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();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool XMLStreamer::Visit( const XMLText& text )
|
||||
bool XMLPrinter::Visit( const XMLText& text )
|
||||
{
|
||||
PushText( text.Value(), text.CData() );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool XMLStreamer::Visit( const XMLComment& comment )
|
||||
bool XMLPrinter::Visit( const XMLComment& comment )
|
||||
{
|
||||
PushComment( comment.Value() );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool XMLStreamer::Visit( const XMLDeclaration& declaration )
|
||||
bool XMLPrinter::Visit( const XMLDeclaration& declaration )
|
||||
{
|
||||
PushDeclaration( declaration.Value() );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool XMLStreamer::Visit( const XMLUnknown& unknown )
|
||||
bool XMLPrinter::Visit( const XMLUnknown& unknown )
|
||||
{
|
||||
PushUnknown( unknown.Value() );
|
||||
return true;
|
||||
|
|
409
tinyxml2.h
409
tinyxml2.h
|
@ -1,36 +1,16 @@
|
|||
#ifndef TINYXML_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 <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <memory.h>
|
||||
|
||||
/* TODO: create main page description.
|
||||
TODO: add 'lastAttribute' for faster parsing.
|
||||
*/
|
||||
|
||||
#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
|
||||
#ifndef DEBUG
|
||||
#define DEBUG
|
||||
|
@ -89,12 +69,12 @@ class XMLText;
|
|||
class XMLDeclaration;
|
||||
class XMLUnknown;
|
||||
|
||||
class XMLStreamer;
|
||||
class XMLPrinter;
|
||||
|
||||
/*
|
||||
A class that wraps strings. Normally stores the start and end
|
||||
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[]
|
||||
*/
|
||||
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
|
||||
{
|
||||
friend class XMLDocument;
|
||||
friend class XMLElement;
|
||||
public:
|
||||
|
||||
/// Get the XMLDocument that owns this XMLNode.
|
||||
const XMLDocument* GetDocument() const { return document; }
|
||||
/// Get the XMLDocument that owns this XMLNode.
|
||||
XMLDocument* GetDocument() { return document; }
|
||||
|
||||
virtual XMLElement* ToElement() { return 0; }
|
||||
virtual XMLText* ToText() { return 0; }
|
||||
virtual XMLComment* ToComment() { return 0; }
|
||||
virtual XMLDocument* ToDocument() { return 0; }
|
||||
virtual XMLDeclaration* ToDeclaration() { return 0; }
|
||||
virtual XMLUnknown* ToUnknown() { return 0; }
|
||||
virtual XMLElement* ToElement() { return 0; } ///< Safely cast to an Element, or null.
|
||||
virtual XMLText* ToText() { return 0; } ///< Safely cast to Text, or null.
|
||||
virtual XMLComment* ToComment() { return 0; } ///< Safely cast to a Comment, or null.
|
||||
virtual XMLDocument* ToDocument() { return 0; } ///< Safely cast to a Document, or null.
|
||||
virtual XMLDeclaration* ToDeclaration() { return 0; } ///< Safely cast to a Declaration, or null.
|
||||
virtual XMLUnknown* ToUnknown() { return 0; } ///< Safely cast to an Unknown, or null.
|
||||
|
||||
virtual const XMLElement* ToElement() const { return 0; }
|
||||
virtual const XMLText* ToText() const { return 0; }
|
||||
|
@ -402,66 +410,111 @@ public:
|
|||
virtual const XMLDeclaration* ToDeclaration() 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(); }
|
||||
/** Set the Value of an XML node.
|
||||
@sa Value()
|
||||
*/
|
||||
void SetValue( const char* val, bool staticMem=false );
|
||||
|
||||
/// Get the parent of this node on the DOM.
|
||||
const XMLNode* Parent() const { return parent; }
|
||||
XMLNode* Parent() { return parent; }
|
||||
|
||||
/// Returns true if this node has no children.
|
||||
bool NoChildren() const { return !firstChild; }
|
||||
|
||||
/// Get the first child node, or null if none exists.
|
||||
const XMLNode* FirstChild() const { 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;
|
||||
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; }
|
||||
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;
|
||||
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; }
|
||||
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 ;
|
||||
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; }
|
||||
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;
|
||||
XMLNode* NextSiblingElement( const char* value=0 ) { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) ); }
|
||||
|
||||
/**
|
||||
|
||||
Tests: Programmatic DOM
|
||||
Add a child node as the last (right) child.
|
||||
*/
|
||||
XMLNode* InsertEndChild( XMLNode* addThis );
|
||||
/**
|
||||
|
||||
Tests: Programmatic DOM
|
||||
Add a child node as the first (left) child.
|
||||
*/
|
||||
XMLNode* InsertFirstChild( XMLNode* addThis );
|
||||
/**
|
||||
|
||||
Tests: Programmatic DOM
|
||||
Add a node after the specified child node.
|
||||
*/
|
||||
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 );
|
||||
|
||||
/** 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;
|
||||
|
||||
// internal
|
||||
virtual char* ParseDeep( char*, StrPair* );
|
||||
|
||||
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
|
||||
{
|
||||
friend class XMLBase;
|
||||
|
@ -496,7 +561,9 @@ public:
|
|||
virtual XMLText* ToText() { 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; }
|
||||
|
||||
char* ParseDeep( char*, StrPair* endTag );
|
||||
|
@ -512,6 +579,7 @@ private:
|
|||
};
|
||||
|
||||
|
||||
/** An XML Comment. */
|
||||
class XMLComment : public XMLNode
|
||||
{
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
friend class XMLElement;
|
||||
public:
|
||||
const char* Name() const { return name.GetStr(); }
|
||||
const char* Value() const { return value.GetStr(); }
|
||||
const XMLAttribute* Next() const { return next; }
|
||||
const char* Name() const { return name.GetStr(); } ///< The name of the attribute.
|
||||
const char* Value() const { return value.GetStr(); } ///< The value of the attribute.
|
||||
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; }
|
||||
/// Query as an unsigned integer. See IntAttribute()
|
||||
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; }
|
||||
/// Query as a double. See IntAttribute()
|
||||
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; }
|
||||
|
||||
/** 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;
|
||||
/// See QueryIntAttribute
|
||||
int QueryUnsignedAttribute( unsigned int* value ) const;
|
||||
/// See QueryIntAttribute
|
||||
int QueryBoolAttribute( bool* value ) const;
|
||||
/// See QueryIntAttribute
|
||||
int QueryDoubleAttribute( double* value ) const;
|
||||
/// See QueryIntAttribute
|
||||
int QueryFloatAttribute( float* value ) const;
|
||||
|
||||
/// Set the attribute to a string value.
|
||||
void SetAttribute( const char* value );
|
||||
/// Set the attribute to value.
|
||||
void SetAttribute( int value );
|
||||
/// Set the attribute to value.
|
||||
void SetAttribute( unsigned value );
|
||||
/// Set the attribute to value.
|
||||
void SetAttribute( bool value );
|
||||
/// Set the attribute to value.
|
||||
void SetAttribute( double value );
|
||||
/// Set the attribute to value.
|
||||
void SetAttribute( float value );
|
||||
|
||||
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
|
||||
{
|
||||
friend class XMLBase;
|
||||
friend class XMLDocument;
|
||||
public:
|
||||
/// Get the name of an element (which is the Value() of the node.)
|
||||
const char* Name() const { return Value(); }
|
||||
/// Set the name of the element.
|
||||
void SetName( const char* str, bool staticMem=false ) { SetValue( str, staticMem ); }
|
||||
|
||||
virtual XMLElement* ToElement() { return this; }
|
||||
virtual const XMLElement* ToElement() const { return this; }
|
||||
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(); }
|
||||
|
||||
/** 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; }
|
||||
/// See IntAttribute()
|
||||
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; }
|
||||
/// See IntAttribute()
|
||||
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; }
|
||||
|
||||
/** 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 ); }
|
||||
/// 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 ); }
|
||||
/// See QueryIntAttribute()
|
||||
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 ); }
|
||||
/// See QueryIntAttribute()
|
||||
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 ); }
|
||||
/// Sets the named attribute to 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 ); }
|
||||
/// Sets the named attribute to 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 ); }
|
||||
|
||||
/**
|
||||
Tests: Programmatic DOM
|
||||
Delete an attribute.
|
||||
*/
|
||||
void DeleteAttribute( const char* name );
|
||||
|
||||
/// Return the first attribute in the list.
|
||||
const XMLAttribute* FirstAttribute() const { return rootAttribute; }
|
||||
/// Query a specific attribute in the list.
|
||||
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;
|
||||
|
||||
// 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
|
||||
{
|
||||
friend class XMLElement;
|
||||
public:
|
||||
/// constructor
|
||||
XMLDocument();
|
||||
~XMLDocument();
|
||||
|
||||
virtual XMLDocument* ToDocument() { 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 );
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
void SaveFile( const char* filename );
|
||||
|
||||
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(); }
|
||||
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;
|
||||
|
||||
/**
|
||||
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 );
|
||||
/**
|
||||
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 );
|
||||
/**
|
||||
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 );
|
||||
|
||||
/**
|
||||
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 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; }
|
||||
/// Return the errorID.
|
||||
int ErrorID() const { return errorID; }
|
||||
/// Return a possibly helpful diagnostic location or string.
|
||||
const char* GetErrorStr1() const { return errorStr1; }
|
||||
/// Return possibly helpful secondary diagnostic location or string.
|
||||
const char* GetErrorStr2() const { return errorStr2; }
|
||||
/// If there is an error, print it to stdout
|
||||
void PrintError() const;
|
||||
|
||||
// internal
|
||||
char* Identify( char* p, XMLNode** node );
|
||||
|
||||
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:
|
||||
XMLStreamer( FILE* file=0 );
|
||||
~XMLStreamer() {}
|
||||
/** Construct the printer. If the FILE* is specified,
|
||||
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 );
|
||||
/** If streaming, start writing an element.
|
||||
The element must be closed with CloseElement()
|
||||
*/
|
||||
void OpenElement( const char* name );
|
||||
/// If streaming, add an attribute to an open element.
|
||||
void PushAttribute( const char* name, const char* value );
|
||||
/// If streaming, close the Element.
|
||||
void CloseElement();
|
||||
|
||||
/// Add a text node.
|
||||
void PushText( const char* text, bool cdata=false );
|
||||
/// Add a comment
|
||||
void PushComment( const char* comment );
|
||||
|
||||
void PushDeclaration( const char* value );
|
||||
void PushUnknown( const char* value );
|
||||
|
||||
|
@ -800,6 +1097,10 @@ public:
|
|||
virtual bool Visit( const XMLDeclaration& declaration );
|
||||
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(); }
|
||||
|
||||
private:
|
||||
|
|
40
xmltest.cpp
40
xmltest.cpp
|
@ -4,7 +4,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined( WIN32 )
|
||||
#if defined( _MSC_VER )
|
||||
#include <crtdbg.h>
|
||||
_CrtMemState startMemState;
|
||||
_CrtMemState endMemState;
|
||||
|
@ -14,35 +14,6 @@ using namespace tinyxml2;
|
|||
int gPass = 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 )
|
||||
{
|
||||
|
@ -100,7 +71,7 @@ void NullLineEndings( char* p )
|
|||
|
||||
int main( int argc, const char* argv )
|
||||
{
|
||||
#if defined( WIN32 )
|
||||
#if defined( _MSC_VER )
|
||||
_CrtMemCheckpoint( &startMemState );
|
||||
#endif
|
||||
|
||||
|
@ -201,7 +172,7 @@ int main( int argc, const char* argv )
|
|||
|
||||
doc->Print();
|
||||
|
||||
XMLStreamer streamer;
|
||||
XMLPrinter streamer;
|
||||
doc->Print( &streamer );
|
||||
printf( "%s", streamer.CStr() );
|
||||
|
||||
|
@ -447,7 +418,7 @@ int main( int argc, const char* argv )
|
|||
FILE* textfile = fopen( "textfile.txt", "w" );
|
||||
if ( textfile )
|
||||
{
|
||||
XMLStreamer streamer( textfile );
|
||||
XMLPrinter streamer( textfile );
|
||||
psg->Accept( &streamer );
|
||||
fclose( textfile );
|
||||
}
|
||||
|
@ -637,7 +608,8 @@ int main( int argc, const char* argv )
|
|||
XMLTest( "Infinite loop test.", true, true );
|
||||
}
|
||||
#endif
|
||||
#if defined( WIN32 )
|
||||
|
||||
#if defined( _MSC_VER )
|
||||
_CrtMemCheckpoint( &endMemState );
|
||||
//_CrtMemDumpStatistics( &endMemState );
|
||||
|
||||
|
|
Loading…
Reference in New Issue