1716 lines
33 KiB
C++
1716 lines
33 KiB
C++
|
/*
|
||
|
www.sourceforge.net/projects/tinyxml
|
||
|
Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com)
|
||
|
|
||
|
This software is provided 'as-is', without any express or implied
|
||
|
warranty. In no event will the authors be held liable for any
|
||
|
damages arising from the use of this software.
|
||
|
|
||
|
Permission is granted to anyone to use this software for any
|
||
|
purpose, including commercial applications, and to alter it and
|
||
|
redistribute it freely, subject to the following restrictions:
|
||
|
|
||
|
1. The origin of this software must not be misrepresented; you must
|
||
|
not claim that you wrote the original software. If you use this
|
||
|
software in a product, an acknowledgment in the product documentation
|
||
|
would be appreciated but is not required.
|
||
|
|
||
|
2. Altered source versions must be plainly marked as such, and
|
||
|
must not be misrepresented as being the original software.
|
||
|
|
||
|
3. This notice may not be removed or altered from any source
|
||
|
distribution.
|
||
|
*/
|
||
|
#include "stdneb.h"
|
||
|
#include <ctype.h>
|
||
|
#include "tinyxml.h"
|
||
|
|
||
|
#ifdef TIXML_USE_STL
|
||
|
#include <sstream>
|
||
|
#include <iostream>
|
||
|
#endif
|
||
|
|
||
|
|
||
|
bool TiXmlBase::condenseWhiteSpace = true;
|
||
|
|
||
|
void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_OSTREAM* stream )
|
||
|
{
|
||
|
TIXML_STRING buffer;
|
||
|
PutString( str, &buffer );
|
||
|
(*stream) << buffer;
|
||
|
}
|
||
|
|
||
|
void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_STRING* outString )
|
||
|
{
|
||
|
int i=0;
|
||
|
|
||
|
while( i<(int)str.length() )
|
||
|
{
|
||
|
unsigned char c = (unsigned char) str[i];
|
||
|
|
||
|
if ( c == '&'
|
||
|
&& i < ( (int)str.length() - 2 )
|
||
|
&& str[i+1] == '#'
|
||
|
&& str[i+2] == 'x' )
|
||
|
{
|
||
|
// Hexadecimal character reference.
|
||
|
// Pass through unchanged.
|
||
|
// © -- copyright symbol, for example.
|
||
|
//
|
||
|
// The -1 is a bug fix from Rob Laveaux. It keeps
|
||
|
// an overflow from happening if there is no ';'.
|
||
|
// There are actually 2 ways to exit this loop -
|
||
|
// while fails (error case) and break (semicolon found).
|
||
|
// However, there is no mechanism (currently) for
|
||
|
// this function to return an error.
|
||
|
while ( i<(int)str.length()-1 )
|
||
|
{
|
||
|
outString->append( str.c_str() + i, 1 );
|
||
|
++i;
|
||
|
if ( str[i] == ';' )
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else if ( c == '&' )
|
||
|
{
|
||
|
outString->append( entity[0].str, entity[0].strLength );
|
||
|
++i;
|
||
|
}
|
||
|
else if ( c == '<' )
|
||
|
{
|
||
|
outString->append( entity[1].str, entity[1].strLength );
|
||
|
++i;
|
||
|
}
|
||
|
else if ( c == '>' )
|
||
|
{
|
||
|
outString->append( entity[2].str, entity[2].strLength );
|
||
|
++i;
|
||
|
}
|
||
|
else if ( c == '\"' )
|
||
|
{
|
||
|
outString->append( entity[3].str, entity[3].strLength );
|
||
|
++i;
|
||
|
}
|
||
|
else if ( c == '\'' )
|
||
|
{
|
||
|
outString->append( entity[4].str, entity[4].strLength );
|
||
|
++i;
|
||
|
}
|
||
|
else if ( c < 32 )
|
||
|
{
|
||
|
// Easy pass at non-alpha/numeric/symbol
|
||
|
// Below 32 is symbolic.
|
||
|
char buf[ 32 ];
|
||
|
|
||
|
#if defined(TIXML_SNPRINTF)
|
||
|
TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) );
|
||
|
#else
|
||
|
sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) );
|
||
|
#endif
|
||
|
|
||
|
//*ME: warning C4267: convert 'size_t' to 'int'
|
||
|
//*ME: Int-Cast to make compiler happy ...
|
||
|
outString->append( buf, (int)strlen( buf ) );
|
||
|
++i;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//char realc = (char) c;
|
||
|
//outString->append( &realc, 1 );
|
||
|
*outString += (char) c; // somewhat more efficient function call.
|
||
|
++i;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// <-- Strange class for a bug fix. Search for STL_STRING_BUG
|
||
|
TiXmlBase::StringToBuffer::StringToBuffer( const TIXML_STRING& str )
|
||
|
{
|
||
|
buffer = new char[ str.length()+1 ];
|
||
|
if ( buffer )
|
||
|
{
|
||
|
strcpy( buffer, str.c_str() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
TiXmlBase::StringToBuffer::~StringToBuffer()
|
||
|
{
|
||
|
delete [] buffer;
|
||
|
}
|
||
|
// End strange bug fix. -->
|
||
|
|
||
|
|
||
|
TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase()
|
||
|
{
|
||
|
parent = 0;
|
||
|
type = _type;
|
||
|
firstChild = 0;
|
||
|
lastChild = 0;
|
||
|
prev = 0;
|
||
|
next = 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
TiXmlNode::~TiXmlNode()
|
||
|
{
|
||
|
TiXmlNode* node = firstChild;
|
||
|
TiXmlNode* temp = 0;
|
||
|
|
||
|
while ( node )
|
||
|
{
|
||
|
temp = node;
|
||
|
node = node->next;
|
||
|
delete temp;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlNode::CopyTo( TiXmlNode* target ) const
|
||
|
{
|
||
|
target->SetValue (value.c_str() );
|
||
|
target->userData = userData;
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlNode::Clear()
|
||
|
{
|
||
|
TiXmlNode* node = firstChild;
|
||
|
TiXmlNode* temp = 0;
|
||
|
|
||
|
while ( node )
|
||
|
{
|
||
|
temp = node;
|
||
|
node = node->next;
|
||
|
delete temp;
|
||
|
}
|
||
|
|
||
|
firstChild = 0;
|
||
|
lastChild = 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
|
||
|
{
|
||
|
assert( node->parent == 0 || node->parent == this );
|
||
|
assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() );
|
||
|
|
||
|
node->parent = this;
|
||
|
|
||
|
node->prev = lastChild;
|
||
|
node->next = 0;
|
||
|
|
||
|
if ( lastChild )
|
||
|
lastChild->next = node;
|
||
|
else
|
||
|
firstChild = node; // it was an empty list.
|
||
|
|
||
|
lastChild = node;
|
||
|
return node;
|
||
|
}
|
||
|
|
||
|
|
||
|
TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis )
|
||
|
{
|
||
|
TiXmlNode* node = addThis.Clone();
|
||
|
if ( !node )
|
||
|
return 0;
|
||
|
|
||
|
return LinkEndChild( node );
|
||
|
}
|
||
|
|
||
|
|
||
|
TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis )
|
||
|
{
|
||
|
if ( !beforeThis || beforeThis->parent != this )
|
||
|
return 0;
|
||
|
|
||
|
TiXmlNode* node = addThis.Clone();
|
||
|
if ( !node )
|
||
|
return 0;
|
||
|
node->parent = this;
|
||
|
|
||
|
node->next = beforeThis;
|
||
|
node->prev = beforeThis->prev;
|
||
|
if ( beforeThis->prev )
|
||
|
{
|
||
|
beforeThis->prev->next = node;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
assert( firstChild == beforeThis );
|
||
|
firstChild = node;
|
||
|
}
|
||
|
beforeThis->prev = node;
|
||
|
return node;
|
||
|
}
|
||
|
|
||
|
|
||
|
TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis )
|
||
|
{
|
||
|
if ( !afterThis || afterThis->parent != this )
|
||
|
return 0;
|
||
|
|
||
|
TiXmlNode* node = addThis.Clone();
|
||
|
if ( !node )
|
||
|
return 0;
|
||
|
node->parent = this;
|
||
|
|
||
|
node->prev = afterThis;
|
||
|
node->next = afterThis->next;
|
||
|
if ( afterThis->next )
|
||
|
{
|
||
|
afterThis->next->prev = node;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
assert( lastChild == afterThis );
|
||
|
lastChild = node;
|
||
|
}
|
||
|
afterThis->next = node;
|
||
|
return node;
|
||
|
}
|
||
|
|
||
|
|
||
|
TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis )
|
||
|
{
|
||
|
if ( replaceThis->parent != this )
|
||
|
return 0;
|
||
|
|
||
|
TiXmlNode* node = withThis.Clone();
|
||
|
if ( !node )
|
||
|
return 0;
|
||
|
|
||
|
node->next = replaceThis->next;
|
||
|
node->prev = replaceThis->prev;
|
||
|
|
||
|
if ( replaceThis->next )
|
||
|
replaceThis->next->prev = node;
|
||
|
else
|
||
|
lastChild = node;
|
||
|
|
||
|
if ( replaceThis->prev )
|
||
|
replaceThis->prev->next = node;
|
||
|
else
|
||
|
firstChild = node;
|
||
|
|
||
|
delete replaceThis;
|
||
|
node->parent = this;
|
||
|
return node;
|
||
|
}
|
||
|
|
||
|
|
||
|
bool TiXmlNode::RemoveChild( TiXmlNode* removeThis )
|
||
|
{
|
||
|
if ( removeThis->parent != this )
|
||
|
{
|
||
|
assert( 0 );
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if ( removeThis->next )
|
||
|
removeThis->next->prev = removeThis->prev;
|
||
|
else
|
||
|
lastChild = removeThis->prev;
|
||
|
|
||
|
if ( removeThis->prev )
|
||
|
removeThis->prev->next = removeThis->next;
|
||
|
else
|
||
|
firstChild = removeThis->next;
|
||
|
|
||
|
delete removeThis;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const
|
||
|
{
|
||
|
const TiXmlNode* node;
|
||
|
for ( node = firstChild; node; node = node->next )
|
||
|
{
|
||
|
if ( strcmp( node->Value(), _value ) == 0 )
|
||
|
return node;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
TiXmlNode* TiXmlNode::FirstChild( const char * _value )
|
||
|
{
|
||
|
TiXmlNode* node;
|
||
|
for ( node = firstChild; node; node = node->next )
|
||
|
{
|
||
|
if ( strcmp( node->Value(), _value ) == 0 )
|
||
|
return node;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const
|
||
|
{
|
||
|
const TiXmlNode* node;
|
||
|
for ( node = lastChild; node; node = node->prev )
|
||
|
{
|
||
|
if ( strcmp( node->Value(), _value ) == 0 )
|
||
|
return node;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
TiXmlNode* TiXmlNode::LastChild( const char * _value )
|
||
|
{
|
||
|
TiXmlNode* node;
|
||
|
for ( node = lastChild; node; node = node->prev )
|
||
|
{
|
||
|
if ( strcmp( node->Value(), _value ) == 0 )
|
||
|
return node;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const
|
||
|
{
|
||
|
if ( !previous )
|
||
|
{
|
||
|
return FirstChild();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
assert( previous->parent == this );
|
||
|
return previous->NextSibling();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
TiXmlNode* TiXmlNode::IterateChildren( TiXmlNode* previous )
|
||
|
{
|
||
|
if ( !previous )
|
||
|
{
|
||
|
return FirstChild();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
assert( previous->parent == this );
|
||
|
return previous->NextSibling();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const
|
||
|
{
|
||
|
if ( !previous )
|
||
|
{
|
||
|
return FirstChild( val );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
assert( previous->parent == this );
|
||
|
return previous->NextSibling( val );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
TiXmlNode* TiXmlNode::IterateChildren( const char * val, TiXmlNode* previous )
|
||
|
{
|
||
|
if ( !previous )
|
||
|
{
|
||
|
return FirstChild( val );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
assert( previous->parent == this );
|
||
|
return previous->NextSibling( val );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const
|
||
|
{
|
||
|
const TiXmlNode* node;
|
||
|
for ( node = next; node; node = node->next )
|
||
|
{
|
||
|
if ( strcmp( node->Value(), _value ) == 0 )
|
||
|
return node;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
TiXmlNode* TiXmlNode::NextSibling( const char * _value )
|
||
|
{
|
||
|
TiXmlNode* node;
|
||
|
for ( node = next; node; node = node->next )
|
||
|
{
|
||
|
if ( strcmp( node->Value(), _value ) == 0 )
|
||
|
return node;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const
|
||
|
{
|
||
|
const TiXmlNode* node;
|
||
|
for ( node = prev; node; node = node->prev )
|
||
|
{
|
||
|
if ( strcmp( node->Value(), _value ) == 0 )
|
||
|
return node;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
TiXmlNode* TiXmlNode::PreviousSibling( const char * _value )
|
||
|
{
|
||
|
TiXmlNode* node;
|
||
|
for ( node = prev; node; node = node->prev )
|
||
|
{
|
||
|
if ( strcmp( node->Value(), _value ) == 0 )
|
||
|
return node;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void TiXmlElement::RemoveAttribute( const char * name )
|
||
|
{
|
||
|
TIXML_STRING str( name );
|
||
|
TiXmlAttribute* node = attributeSet.Find( str );
|
||
|
if ( node )
|
||
|
{
|
||
|
attributeSet.Remove( node );
|
||
|
delete node;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const TiXmlElement* TiXmlNode::FirstChildElement() const
|
||
|
{
|
||
|
const TiXmlNode* node;
|
||
|
|
||
|
for ( node = FirstChild();
|
||
|
node;
|
||
|
node = node->NextSibling() )
|
||
|
{
|
||
|
if ( node->ToElement() )
|
||
|
return node->ToElement();
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
TiXmlElement* TiXmlNode::FirstChildElement()
|
||
|
{
|
||
|
TiXmlNode* node;
|
||
|
|
||
|
for ( node = FirstChild();
|
||
|
node;
|
||
|
node = node->NextSibling() )
|
||
|
{
|
||
|
if ( node->ToElement() )
|
||
|
return node->ToElement();
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const
|
||
|
{
|
||
|
const TiXmlNode* node;
|
||
|
|
||
|
for ( node = FirstChild( _value );
|
||
|
node;
|
||
|
node = node->NextSibling( _value ) )
|
||
|
{
|
||
|
if ( node->ToElement() )
|
||
|
return node->ToElement();
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
TiXmlElement* TiXmlNode::FirstChildElement( const char * _value )
|
||
|
{
|
||
|
TiXmlNode* node;
|
||
|
|
||
|
for ( node = FirstChild( _value );
|
||
|
node;
|
||
|
node = node->NextSibling( _value ) )
|
||
|
{
|
||
|
if ( node->ToElement() )
|
||
|
return node->ToElement();
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
const TiXmlElement* TiXmlNode::NextSiblingElement() const
|
||
|
{
|
||
|
const TiXmlNode* node;
|
||
|
|
||
|
for ( node = NextSibling();
|
||
|
node;
|
||
|
node = node->NextSibling() )
|
||
|
{
|
||
|
if ( node->ToElement() )
|
||
|
return node->ToElement();
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
TiXmlElement* TiXmlNode::NextSiblingElement()
|
||
|
{
|
||
|
TiXmlNode* node;
|
||
|
|
||
|
for ( node = NextSibling();
|
||
|
node;
|
||
|
node = node->NextSibling() )
|
||
|
{
|
||
|
if ( node->ToElement() )
|
||
|
return node->ToElement();
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const
|
||
|
{
|
||
|
const TiXmlNode* node;
|
||
|
|
||
|
for ( node = NextSibling( _value );
|
||
|
node;
|
||
|
node = node->NextSibling( _value ) )
|
||
|
{
|
||
|
if ( node->ToElement() )
|
||
|
return node->ToElement();
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value )
|
||
|
{
|
||
|
TiXmlNode* node;
|
||
|
|
||
|
for ( node = NextSibling( _value );
|
||
|
node;
|
||
|
node = node->NextSibling( _value ) )
|
||
|
{
|
||
|
if ( node->ToElement() )
|
||
|
return node->ToElement();
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
const TiXmlDocument* TiXmlNode::GetDocument() const
|
||
|
{
|
||
|
const TiXmlNode* node;
|
||
|
|
||
|
for( node = this; node; node = node->parent )
|
||
|
{
|
||
|
if ( node->ToDocument() )
|
||
|
return node->ToDocument();
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
TiXmlDocument* TiXmlNode::GetDocument()
|
||
|
{
|
||
|
TiXmlNode* node;
|
||
|
|
||
|
for( node = this; node; node = node->parent )
|
||
|
{
|
||
|
if ( node->ToDocument() )
|
||
|
return node->ToDocument();
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
TiXmlElement::TiXmlElement (const char * _value)
|
||
|
: TiXmlNode( TiXmlNode::ELEMENT )
|
||
|
{
|
||
|
firstChild = lastChild = 0;
|
||
|
value = _value;
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifdef TIXML_USE_STL
|
||
|
TiXmlElement::TiXmlElement( const std::string& _value )
|
||
|
: TiXmlNode( TiXmlNode::ELEMENT )
|
||
|
{
|
||
|
firstChild = lastChild = 0;
|
||
|
value = _value;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
TiXmlElement::TiXmlElement( const TiXmlElement& copy)
|
||
|
: TiXmlNode( TiXmlNode::ELEMENT )
|
||
|
{
|
||
|
firstChild = lastChild = 0;
|
||
|
copy.CopyTo( this );
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlElement::operator=( const TiXmlElement& base )
|
||
|
{
|
||
|
ClearThis();
|
||
|
base.CopyTo( this );
|
||
|
}
|
||
|
|
||
|
|
||
|
TiXmlElement::~TiXmlElement()
|
||
|
{
|
||
|
ClearThis();
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlElement::ClearThis()
|
||
|
{
|
||
|
Clear();
|
||
|
while( attributeSet.First() )
|
||
|
{
|
||
|
TiXmlAttribute* node = attributeSet.First();
|
||
|
attributeSet.Remove( node );
|
||
|
delete node;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
const char * TiXmlElement::Attribute( const char * name ) const
|
||
|
{
|
||
|
TIXML_STRING str( name );
|
||
|
const TiXmlAttribute* node = attributeSet.Find( str );
|
||
|
|
||
|
if ( node )
|
||
|
return node->Value();
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
const char * TiXmlElement::Attribute( const char * name, int* i ) const
|
||
|
{
|
||
|
const char * s = Attribute( name );
|
||
|
if ( i )
|
||
|
{
|
||
|
if ( s )
|
||
|
*i = atoi( s );
|
||
|
else
|
||
|
*i = 0;
|
||
|
}
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
|
||
|
const char * TiXmlElement::Attribute( const char * name, double* d ) const
|
||
|
{
|
||
|
const char * s = Attribute( name );
|
||
|
if ( d )
|
||
|
{
|
||
|
if ( s )
|
||
|
*d = atof( s );
|
||
|
else
|
||
|
*d = 0;
|
||
|
}
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
|
||
|
int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const
|
||
|
{
|
||
|
TIXML_STRING str( name );
|
||
|
const TiXmlAttribute* node = attributeSet.Find( str );
|
||
|
if ( !node )
|
||
|
return TIXML_NO_ATTRIBUTE;
|
||
|
|
||
|
return node->QueryIntValue( ival );
|
||
|
}
|
||
|
|
||
|
|
||
|
int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const
|
||
|
{
|
||
|
TIXML_STRING str( name );
|
||
|
const TiXmlAttribute* node = attributeSet.Find( str );
|
||
|
if ( !node )
|
||
|
return TIXML_NO_ATTRIBUTE;
|
||
|
|
||
|
return node->QueryDoubleValue( dval );
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlElement::SetAttribute( const char * name, int val )
|
||
|
{
|
||
|
char buf[64];
|
||
|
#if defined(TIXML_SNPRINTF)
|
||
|
TIXML_SNPRINTF( buf, sizeof(buf), "%d", val );
|
||
|
#else
|
||
|
sprintf( buf, "%d", val );
|
||
|
#endif
|
||
|
SetAttribute( name, buf );
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifdef TIXML_USE_STL
|
||
|
void TiXmlElement::SetAttribute( const std::string& name, int val )
|
||
|
{
|
||
|
std::ostringstream oss;
|
||
|
oss << val;
|
||
|
SetAttribute( name, oss.str() );
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
void TiXmlElement::SetDoubleAttribute( const char * name, double val )
|
||
|
{
|
||
|
char buf[256];
|
||
|
#if defined(TIXML_SNPRINTF)
|
||
|
TIXML_SNPRINTF( buf, sizeof(buf), "%f", val );
|
||
|
#else
|
||
|
sprintf( buf, "%f", val );
|
||
|
#endif
|
||
|
SetAttribute( name, buf );
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlElement::SetAttribute( const char * cname, const char * cvalue )
|
||
|
{
|
||
|
TIXML_STRING _name( cname );
|
||
|
TIXML_STRING _value( cvalue );
|
||
|
|
||
|
TiXmlAttribute* node = attributeSet.Find( _name );
|
||
|
if ( node )
|
||
|
{
|
||
|
node->SetValue( cvalue );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
TiXmlAttribute* attrib = new TiXmlAttribute( cname, cvalue );
|
||
|
if ( attrib )
|
||
|
{
|
||
|
attributeSet.Add( attrib );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TiXmlDocument* document = GetDocument();
|
||
|
if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifdef TIXML_USE_STL
|
||
|
void TiXmlElement::SetAttribute( const std::string& name, const std::string& _value )
|
||
|
{
|
||
|
TiXmlAttribute* node = attributeSet.Find( name );
|
||
|
if ( node )
|
||
|
{
|
||
|
node->SetValue( _value );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
TiXmlAttribute* attrib = new TiXmlAttribute( name, _value );
|
||
|
if ( attrib )
|
||
|
{
|
||
|
attributeSet.Add( attrib );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TiXmlDocument* document = GetDocument();
|
||
|
if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
void TiXmlElement::Print(const GPtr<IO::TextWriter>& textWriter, int depth) const
|
||
|
{
|
||
|
n_assert(textWriter.isvalid());
|
||
|
int i;
|
||
|
for (i = 0; i < depth; i++)
|
||
|
{
|
||
|
textWriter->WriteString(" ");
|
||
|
}
|
||
|
textWriter->WriteFormatted("<%s", value.c_str());
|
||
|
|
||
|
const TiXmlAttribute* attrib;
|
||
|
for (attrib = attributeSet.First(); attrib; attrib = attrib->Next())
|
||
|
{
|
||
|
textWriter->WriteChar(' ');
|
||
|
attrib->Print(textWriter, depth);
|
||
|
}
|
||
|
|
||
|
// There are 3 different formatting approaches:
|
||
|
// 1) An element without children is printed as a <foo /> node
|
||
|
// 2) An element with only a text child is printed as <foo> text </foo>
|
||
|
// 3) An element with children is printed on multiple lines.
|
||
|
TiXmlNode* node;
|
||
|
if (!firstChild)
|
||
|
{
|
||
|
textWriter->WriteString(" />");
|
||
|
}
|
||
|
else if (firstChild == lastChild && firstChild->ToText())
|
||
|
{
|
||
|
textWriter->WriteChar('>');
|
||
|
firstChild->Print(textWriter, depth + 1);
|
||
|
textWriter->WriteFormatted("</%s>", value.c_str());
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
textWriter->WriteChar('>');
|
||
|
for (node = firstChild; node; node=node->NextSibling())
|
||
|
{
|
||
|
if (!node->ToText())
|
||
|
{
|
||
|
textWriter->WriteChar('\n');
|
||
|
}
|
||
|
node->Print(textWriter, depth+1);
|
||
|
}
|
||
|
textWriter->WriteChar('\n');
|
||
|
for(i=0; i<depth; ++i)
|
||
|
{
|
||
|
textWriter->WriteString(" ");
|
||
|
}
|
||
|
textWriter->WriteFormatted("</%s>", value.c_str());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void TiXmlElement::StreamOut( TIXML_OSTREAM * stream ) const
|
||
|
{
|
||
|
(*stream) << "<" << value;
|
||
|
|
||
|
const TiXmlAttribute* attrib;
|
||
|
for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
|
||
|
{
|
||
|
(*stream) << " ";
|
||
|
attrib->StreamOut( stream );
|
||
|
}
|
||
|
|
||
|
// If this node has children, give it a closing tag. Else
|
||
|
// make it an empty tag.
|
||
|
TiXmlNode* node;
|
||
|
if ( firstChild )
|
||
|
{
|
||
|
(*stream) << ">";
|
||
|
|
||
|
for ( node = firstChild; node; node=node->NextSibling() )
|
||
|
{
|
||
|
node->StreamOut( stream );
|
||
|
}
|
||
|
(*stream) << "</" << value << ">";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
(*stream) << " />";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlElement::CopyTo( TiXmlElement* target ) const
|
||
|
{
|
||
|
// superclass:
|
||
|
TiXmlNode::CopyTo( target );
|
||
|
|
||
|
// Element class:
|
||
|
// Clone the attributes, then clone the children.
|
||
|
const TiXmlAttribute* attribute = 0;
|
||
|
for( attribute = attributeSet.First();
|
||
|
attribute;
|
||
|
attribute = attribute->Next() )
|
||
|
{
|
||
|
target->SetAttribute( attribute->Name(), attribute->Value() );
|
||
|
}
|
||
|
|
||
|
TiXmlNode* node = 0;
|
||
|
for ( node = firstChild; node; node = node->NextSibling() )
|
||
|
{
|
||
|
target->LinkEndChild( node->Clone() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
TiXmlNode* TiXmlElement::Clone() const
|
||
|
{
|
||
|
TiXmlElement* clone = new TiXmlElement( Value() );
|
||
|
if ( !clone )
|
||
|
return 0;
|
||
|
|
||
|
CopyTo( clone );
|
||
|
return clone;
|
||
|
}
|
||
|
|
||
|
|
||
|
const char* TiXmlElement::GetText() const
|
||
|
{
|
||
|
const TiXmlNode* child = this->FirstChild();
|
||
|
if ( child ) {
|
||
|
const TiXmlText* childText = child->ToText();
|
||
|
if ( childText ) {
|
||
|
return childText->Value();
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT )
|
||
|
{
|
||
|
tabsize = 4;
|
||
|
useMicrosoftBOM = false;
|
||
|
ClearError();
|
||
|
}
|
||
|
|
||
|
TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT )
|
||
|
{
|
||
|
copy.CopyTo( this );
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlDocument::operator=( const TiXmlDocument& copy )
|
||
|
{
|
||
|
Clear();
|
||
|
copy.CopyTo( this );
|
||
|
}
|
||
|
|
||
|
|
||
|
bool TiXmlDocument::LoadStream(const GPtr<IO::Stream>& stream, TiXmlEncoding encoding)
|
||
|
{
|
||
|
if (!stream.isvalid())
|
||
|
{
|
||
|
SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// Delete the existing data:
|
||
|
Clear();
|
||
|
location.Clear();
|
||
|
|
||
|
// Get the file size, so we can pre-allocate the string. HUGE speed impact.
|
||
|
long length = stream->GetSize();
|
||
|
|
||
|
// Strange case, but good to handle up front.
|
||
|
if (length == 0)
|
||
|
{
|
||
|
SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// If we have a file, assume it is all one big XML file, and read it in.
|
||
|
// The document parser may decide the document ends sooner than the entire file, however.
|
||
|
TIXML_STRING data;
|
||
|
data.reserve(length);
|
||
|
|
||
|
// Subtle bug here. TinyXml did use fgets. But from the XML spec:
|
||
|
// 2.11 End-of-Line Handling
|
||
|
// <snip>
|
||
|
// <quote>
|
||
|
// ...the XML processor MUST behave as if it normalized all line breaks in external
|
||
|
// parsed entities (including the document entity) on input, before parsing, by translating
|
||
|
// both the two-character sequence #xD #xA and any #xD that is not followed by #xA to
|
||
|
// a single #xA character.
|
||
|
// </quote>
|
||
|
//
|
||
|
// It is not clear fgets does that, and certainly isn't clear it works cross platform.
|
||
|
// Generally, you expect fgets to translate from the convention of the OS to the c/unix
|
||
|
// convention, and not work generally.
|
||
|
/*
|
||
|
while (fgets(buf, sizeof(buf), file))
|
||
|
{
|
||
|
data += buf;
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
char* buf = new char[length+1];
|
||
|
buf[0] = 0;
|
||
|
if (stream->Read(buf, length) != length)
|
||
|
{
|
||
|
SetError(TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
const char* lastPos = buf;
|
||
|
const char* p = buf;
|
||
|
|
||
|
buf[length] = 0;
|
||
|
while( *p ) {
|
||
|
assert( p < (buf+length) );
|
||
|
if ( *p == 0xa ) {
|
||
|
// Newline character. No special rules for this. Append all the characters
|
||
|
// since the last string, and include the newline.
|
||
|
data.append( lastPos, (p-lastPos+1) ); // append, include the newline
|
||
|
++p; // move past the newline
|
||
|
lastPos = p; // and point to the new buffer (may be 0)
|
||
|
assert( p <= (buf+length) );
|
||
|
}
|
||
|
else if ( *p == 0xd ) {
|
||
|
// Carriage return. Append what we have so far, then
|
||
|
// handle moving forward in the buffer.
|
||
|
if ( (p-lastPos) > 0 ) {
|
||
|
data.append( lastPos, p-lastPos ); // do not add the CR
|
||
|
}
|
||
|
data += (char)0xa; // a proper newline
|
||
|
|
||
|
if ( *(p+1) == 0xa ) {
|
||
|
// Carriage return - new line sequence
|
||
|
p += 2;
|
||
|
lastPos = p;
|
||
|
assert( p <= (buf+length) );
|
||
|
}
|
||
|
else {
|
||
|
// it was followed by something else...that is presumably characters again.
|
||
|
++p;
|
||
|
lastPos = p;
|
||
|
assert( p <= (buf+length) );
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
++p;
|
||
|
}
|
||
|
}
|
||
|
// Handle any left over characters.
|
||
|
if ( p-lastPos ) {
|
||
|
data.append( lastPos, p-lastPos );
|
||
|
}
|
||
|
delete [] buf;
|
||
|
buf = 0;
|
||
|
|
||
|
Parse( data.c_str(), 0, encoding );
|
||
|
|
||
|
if ( Error() )
|
||
|
return false;
|
||
|
else
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
bool TiXmlDocument::SaveStream(const GPtr<IO::Stream>& stream) const
|
||
|
{
|
||
|
GPtr<IO::TextWriter> textWriter = IO::TextWriter::Create();
|
||
|
textWriter->SetStream(stream);
|
||
|
if (textWriter->Open())
|
||
|
{
|
||
|
if (useMicrosoftBOM)
|
||
|
{
|
||
|
const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
|
||
|
const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
|
||
|
const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
|
||
|
|
||
|
textWriter->WriteChar(TIXML_UTF_LEAD_0);
|
||
|
textWriter->WriteChar(TIXML_UTF_LEAD_1);
|
||
|
textWriter->WriteChar(TIXML_UTF_LEAD_2);
|
||
|
}
|
||
|
Print(textWriter, 0);
|
||
|
textWriter->Close();
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlDocument::CopyTo( TiXmlDocument* target ) const
|
||
|
{
|
||
|
TiXmlNode::CopyTo( target );
|
||
|
|
||
|
target->error = error;
|
||
|
target->errorDesc = errorDesc.c_str ();
|
||
|
|
||
|
TiXmlNode* node = 0;
|
||
|
for ( node = firstChild; node; node = node->NextSibling() )
|
||
|
{
|
||
|
target->LinkEndChild( node->Clone() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
TiXmlNode* TiXmlDocument::Clone() const
|
||
|
{
|
||
|
TiXmlDocument* clone = new TiXmlDocument();
|
||
|
if ( !clone )
|
||
|
return 0;
|
||
|
|
||
|
CopyTo( clone );
|
||
|
return clone;
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlDocument::Print(const GPtr<IO::TextWriter>& textWriter, int depth) const
|
||
|
{
|
||
|
const TiXmlNode* node;
|
||
|
for ( node=FirstChild(); node; node=node->NextSibling() )
|
||
|
{
|
||
|
node->Print(textWriter, depth);
|
||
|
textWriter->WriteChar('\n');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void TiXmlDocument::StreamOut( TIXML_OSTREAM * out ) const
|
||
|
{
|
||
|
const TiXmlNode* node;
|
||
|
for ( node=FirstChild(); node; node=node->NextSibling() )
|
||
|
{
|
||
|
node->StreamOut( out );
|
||
|
|
||
|
// Special rule for streams: stop after the root element.
|
||
|
// The stream in code will only read one element, so don't
|
||
|
// write more than one.
|
||
|
if ( node->ToElement() )
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
const TiXmlAttribute* TiXmlAttribute::Next() const
|
||
|
{
|
||
|
// We are using knowledge of the sentinel. The sentinel
|
||
|
// have a value or name.
|
||
|
if ( next->value.empty() && next->name.empty() )
|
||
|
return 0;
|
||
|
return next;
|
||
|
}
|
||
|
|
||
|
TiXmlAttribute* TiXmlAttribute::Next()
|
||
|
{
|
||
|
// We are using knowledge of the sentinel. The sentinel
|
||
|
// have a value or name.
|
||
|
if ( next->value.empty() && next->name.empty() )
|
||
|
return 0;
|
||
|
return next;
|
||
|
}
|
||
|
|
||
|
const TiXmlAttribute* TiXmlAttribute::Previous() const
|
||
|
{
|
||
|
// We are using knowledge of the sentinel. The sentinel
|
||
|
// have a value or name.
|
||
|
if ( prev->value.empty() && prev->name.empty() )
|
||
|
return 0;
|
||
|
return prev;
|
||
|
}
|
||
|
|
||
|
TiXmlAttribute* TiXmlAttribute::Previous()
|
||
|
{
|
||
|
// We are using knowledge of the sentinel. The sentinel
|
||
|
// have a value or name.
|
||
|
if ( prev->value.empty() && prev->name.empty() )
|
||
|
return 0;
|
||
|
return prev;
|
||
|
}
|
||
|
|
||
|
void TiXmlAttribute::Print(const GPtr<IO::TextWriter>& textWriter, int /*depth*/ ) const
|
||
|
{
|
||
|
TIXML_STRING n, v;
|
||
|
|
||
|
PutString( name, &n );
|
||
|
PutString( value, &v );
|
||
|
|
||
|
if (value.find ('\"') == TIXML_STRING::npos)
|
||
|
textWriter->WriteFormatted("%s=\"%s\"", n.c_str(), v.c_str());
|
||
|
else
|
||
|
textWriter->WriteFormatted("%s='%s'", n.c_str(), v.c_str());
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlAttribute::StreamOut( TIXML_OSTREAM * stream ) const
|
||
|
{
|
||
|
if (value.find( '\"' ) != TIXML_STRING::npos)
|
||
|
{
|
||
|
PutString( name, stream );
|
||
|
(*stream) << "=" << "'";
|
||
|
PutString( value, stream );
|
||
|
(*stream) << "'";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
PutString( name, stream );
|
||
|
(*stream) << "=" << "\"";
|
||
|
PutString( value, stream );
|
||
|
(*stream) << "\"";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int TiXmlAttribute::QueryIntValue( int* ival ) const
|
||
|
{
|
||
|
if ( sscanf( value.c_str(), "%d", ival ) == 1 )
|
||
|
return TIXML_SUCCESS;
|
||
|
return TIXML_WRONG_TYPE;
|
||
|
}
|
||
|
|
||
|
int TiXmlAttribute::QueryDoubleValue( double* dval ) const
|
||
|
{
|
||
|
if ( sscanf( value.c_str(), "%lf", dval ) == 1 )
|
||
|
return TIXML_SUCCESS;
|
||
|
return TIXML_WRONG_TYPE;
|
||
|
}
|
||
|
|
||
|
void TiXmlAttribute::SetIntValue( int _value )
|
||
|
{
|
||
|
char buf [64];
|
||
|
#if defined(TIXML_SNPRINTF)
|
||
|
TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value);
|
||
|
#else
|
||
|
sprintf (buf, "%d", _value);
|
||
|
#endif
|
||
|
SetValue (buf);
|
||
|
}
|
||
|
|
||
|
void TiXmlAttribute::SetDoubleValue( double _value )
|
||
|
{
|
||
|
char buf [256];
|
||
|
#if defined(TIXML_SNPRINTF)
|
||
|
TIXML_SNPRINTF( buf, sizeof(buf), "%lf", _value);
|
||
|
#else
|
||
|
sprintf (buf, "%lf", _value);
|
||
|
#endif
|
||
|
SetValue (buf);
|
||
|
}
|
||
|
|
||
|
int TiXmlAttribute::IntValue() const
|
||
|
{
|
||
|
return atoi (value.c_str ());
|
||
|
}
|
||
|
|
||
|
double TiXmlAttribute::DoubleValue() const
|
||
|
{
|
||
|
return atof (value.c_str ());
|
||
|
}
|
||
|
|
||
|
|
||
|
TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT )
|
||
|
{
|
||
|
copy.CopyTo( this );
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlComment::operator=( const TiXmlComment& base )
|
||
|
{
|
||
|
Clear();
|
||
|
base.CopyTo( this );
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlComment::Print(const GPtr<IO::TextWriter>& textWriter, int depth) const
|
||
|
{
|
||
|
for ( int i=0; i<depth; i++ )
|
||
|
{
|
||
|
textWriter->WriteString(" ");
|
||
|
}
|
||
|
textWriter->WriteFormatted("<!--%s-->", value.c_str());
|
||
|
}
|
||
|
|
||
|
void TiXmlComment::StreamOut( TIXML_OSTREAM * stream ) const
|
||
|
{
|
||
|
(*stream) << "<!--";
|
||
|
//PutString( value, stream );
|
||
|
(*stream) << value;
|
||
|
(*stream) << "-->";
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlComment::CopyTo( TiXmlComment* target ) const
|
||
|
{
|
||
|
TiXmlNode::CopyTo( target );
|
||
|
}
|
||
|
|
||
|
|
||
|
TiXmlNode* TiXmlComment::Clone() const
|
||
|
{
|
||
|
TiXmlComment* clone = new TiXmlComment();
|
||
|
|
||
|
if ( !clone )
|
||
|
return 0;
|
||
|
|
||
|
CopyTo( clone );
|
||
|
return clone;
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlText::Print(const GPtr<IO::TextWriter>& textWriter, int depth) const
|
||
|
{
|
||
|
if (cdata)
|
||
|
{
|
||
|
int i;
|
||
|
textWriter->WriteChar('\n');
|
||
|
for (i=0; i<depth; i++)
|
||
|
{
|
||
|
textWriter->WriteString(" ");
|
||
|
}
|
||
|
textWriter->WriteFormatted("<![CDATA[%s]]>\n", value.c_str());
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TIXML_STRING buffer;
|
||
|
PutString( value, &buffer );
|
||
|
textWriter->WriteString(buffer.c_str());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlText::StreamOut( TIXML_OSTREAM * stream ) const
|
||
|
{
|
||
|
if ( cdata )
|
||
|
{
|
||
|
(*stream) << "<![CDATA[" << value << "]]>";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
PutString( value, stream );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlText::CopyTo( TiXmlText* target ) const
|
||
|
{
|
||
|
TiXmlNode::CopyTo( target );
|
||
|
target->cdata = cdata;
|
||
|
}
|
||
|
|
||
|
|
||
|
TiXmlNode* TiXmlText::Clone() const
|
||
|
{
|
||
|
TiXmlText* clone = 0;
|
||
|
clone = new TiXmlText( "" );
|
||
|
|
||
|
if ( !clone )
|
||
|
return 0;
|
||
|
|
||
|
CopyTo( clone );
|
||
|
return clone;
|
||
|
}
|
||
|
|
||
|
|
||
|
TiXmlDeclaration::TiXmlDeclaration( const char * _version,
|
||
|
const char * _encoding,
|
||
|
const char * _standalone )
|
||
|
: TiXmlNode( TiXmlNode::DECLARATION )
|
||
|
{
|
||
|
version = _version;
|
||
|
encoding = _encoding;
|
||
|
standalone = _standalone;
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifdef TIXML_USE_STL
|
||
|
TiXmlDeclaration::TiXmlDeclaration( const std::string& _version,
|
||
|
const std::string& _encoding,
|
||
|
const std::string& _standalone )
|
||
|
: TiXmlNode( TiXmlNode::DECLARATION )
|
||
|
{
|
||
|
version = _version;
|
||
|
encoding = _encoding;
|
||
|
standalone = _standalone;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy )
|
||
|
: TiXmlNode( TiXmlNode::DECLARATION )
|
||
|
{
|
||
|
copy.CopyTo( this );
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy )
|
||
|
{
|
||
|
Clear();
|
||
|
copy.CopyTo( this );
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlDeclaration::Print(const GPtr<IO::TextWriter>& textWriter, int /*depth*/ ) const
|
||
|
{
|
||
|
textWriter->WriteString("<?xml ");
|
||
|
if ( !version.empty() )
|
||
|
textWriter->WriteFormatted("version=\"%s\" ", version.c_str ());
|
||
|
if ( !encoding.empty() )
|
||
|
textWriter->WriteFormatted("encoding=\"%s\" ", encoding.c_str ());
|
||
|
if ( !standalone.empty() )
|
||
|
textWriter->WriteFormatted("standalone=\"%s\" ", standalone.c_str ());
|
||
|
textWriter->WriteString("?>");
|
||
|
}
|
||
|
|
||
|
void TiXmlDeclaration::StreamOut( TIXML_OSTREAM * stream ) const
|
||
|
{
|
||
|
(*stream) << "<?xml ";
|
||
|
|
||
|
if ( !version.empty() )
|
||
|
{
|
||
|
(*stream) << "version=\"";
|
||
|
PutString( version, stream );
|
||
|
(*stream) << "\" ";
|
||
|
}
|
||
|
if ( !encoding.empty() )
|
||
|
{
|
||
|
(*stream) << "encoding=\"";
|
||
|
PutString( encoding, stream );
|
||
|
(*stream ) << "\" ";
|
||
|
}
|
||
|
if ( !standalone.empty() )
|
||
|
{
|
||
|
(*stream) << "standalone=\"";
|
||
|
PutString( standalone, stream );
|
||
|
(*stream) << "\" ";
|
||
|
}
|
||
|
(*stream) << "?>";
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const
|
||
|
{
|
||
|
TiXmlNode::CopyTo( target );
|
||
|
|
||
|
target->version = version;
|
||
|
target->encoding = encoding;
|
||
|
target->standalone = standalone;
|
||
|
}
|
||
|
|
||
|
|
||
|
TiXmlNode* TiXmlDeclaration::Clone() const
|
||
|
{
|
||
|
TiXmlDeclaration* clone = new TiXmlDeclaration();
|
||
|
|
||
|
if ( !clone )
|
||
|
return 0;
|
||
|
|
||
|
CopyTo( clone );
|
||
|
return clone;
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlUnknown::Print(const GPtr<IO::TextWriter>& textWriter, int depth ) const
|
||
|
{
|
||
|
for ( int i=0; i<depth; i++ )
|
||
|
textWriter->WriteString(" ");
|
||
|
textWriter->WriteFormatted("<%s>", value.c_str());
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlUnknown::StreamOut( TIXML_OSTREAM * stream ) const
|
||
|
{
|
||
|
(*stream) << "<" << value << ">"; // Don't use entities here! It is unknown.
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const
|
||
|
{
|
||
|
TiXmlNode::CopyTo( target );
|
||
|
}
|
||
|
|
||
|
|
||
|
TiXmlNode* TiXmlUnknown::Clone() const
|
||
|
{
|
||
|
TiXmlUnknown* clone = new TiXmlUnknown();
|
||
|
|
||
|
if ( !clone )
|
||
|
return 0;
|
||
|
|
||
|
CopyTo( clone );
|
||
|
return clone;
|
||
|
}
|
||
|
|
||
|
|
||
|
TiXmlAttributeSet::TiXmlAttributeSet()
|
||
|
{
|
||
|
sentinel.next = &sentinel;
|
||
|
sentinel.prev = &sentinel;
|
||
|
}
|
||
|
|
||
|
|
||
|
TiXmlAttributeSet::~TiXmlAttributeSet()
|
||
|
{
|
||
|
assert( sentinel.next == &sentinel );
|
||
|
assert( sentinel.prev == &sentinel );
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlAttributeSet::Add( TiXmlAttribute* addMe )
|
||
|
{
|
||
|
assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set.
|
||
|
|
||
|
addMe->next = &sentinel;
|
||
|
addMe->prev = sentinel.prev;
|
||
|
|
||
|
sentinel.prev->next = addMe;
|
||
|
sentinel.prev = addMe;
|
||
|
}
|
||
|
|
||
|
void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe )
|
||
|
{
|
||
|
TiXmlAttribute* node;
|
||
|
|
||
|
for( node = sentinel.next; node != &sentinel; node = node->next )
|
||
|
{
|
||
|
if ( node == removeMe )
|
||
|
{
|
||
|
node->prev->next = node->next;
|
||
|
node->next->prev = node->prev;
|
||
|
node->next = 0;
|
||
|
node->prev = 0;
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
assert( 0 ); // we tried to remove a non-linked attribute.
|
||
|
}
|
||
|
|
||
|
const TiXmlAttribute* TiXmlAttributeSet::Find( const TIXML_STRING& name ) const
|
||
|
{
|
||
|
const TiXmlAttribute* node;
|
||
|
|
||
|
for( node = sentinel.next; node != &sentinel; node = node->next )
|
||
|
{
|
||
|
if ( node->name == name )
|
||
|
return node;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
TiXmlAttribute* TiXmlAttributeSet::Find( const TIXML_STRING& name )
|
||
|
{
|
||
|
TiXmlAttribute* node;
|
||
|
|
||
|
for( node = sentinel.next; node != &sentinel; node = node->next )
|
||
|
{
|
||
|
if ( node->name == name )
|
||
|
return node;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
#ifdef TIXML_USE_STL
|
||
|
TIXML_ISTREAM & operator >> (TIXML_ISTREAM & in, TiXmlNode & base)
|
||
|
{
|
||
|
TIXML_STRING tag;
|
||
|
tag.reserve( 8 * 1000 );
|
||
|
base.StreamIn( &in, &tag );
|
||
|
|
||
|
base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING );
|
||
|
return in;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
TIXML_OSTREAM & operator<< (TIXML_OSTREAM & out, const TiXmlNode & base)
|
||
|
{
|
||
|
base.StreamOut (& out);
|
||
|
return out;
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifdef TIXML_USE_STL
|
||
|
std::string & operator<< (std::string& out, const TiXmlNode& base )
|
||
|
{
|
||
|
std::ostringstream os_stream( std::ostringstream::out );
|
||
|
base.StreamOut( &os_stream );
|
||
|
|
||
|
out.append( os_stream.str() );
|
||
|
return out;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
TiXmlHandle TiXmlHandle::FirstChild() const
|
||
|
{
|
||
|
if ( node )
|
||
|
{
|
||
|
TiXmlNode* child = node->FirstChild();
|
||
|
if ( child )
|
||
|
return TiXmlHandle( child );
|
||
|
}
|
||
|
return TiXmlHandle( 0 );
|
||
|
}
|
||
|
|
||
|
|
||
|
TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const
|
||
|
{
|
||
|
if ( node )
|
||
|
{
|
||
|
TiXmlNode* child = node->FirstChild( value );
|
||
|
if ( child )
|
||
|
return TiXmlHandle( child );
|
||
|
}
|
||
|
return TiXmlHandle( 0 );
|
||
|
}
|
||
|
|
||
|
|
||
|
TiXmlHandle TiXmlHandle::FirstChildElement() const
|
||
|
{
|
||
|
if ( node )
|
||
|
{
|
||
|
TiXmlElement* child = node->FirstChildElement();
|
||
|
if ( child )
|
||
|
return TiXmlHandle( child );
|
||
|
}
|
||
|
return TiXmlHandle( 0 );
|
||
|
}
|
||
|
|
||
|
|
||
|
TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const
|
||
|
{
|
||
|
if ( node )
|
||
|
{
|
||
|
TiXmlElement* child = node->FirstChildElement( value );
|
||
|
if ( child )
|
||
|
return TiXmlHandle( child );
|
||
|
}
|
||
|
return TiXmlHandle( 0 );
|
||
|
}
|
||
|
|
||
|
|
||
|
TiXmlHandle TiXmlHandle::Child( int count ) const
|
||
|
{
|
||
|
if ( node )
|
||
|
{
|
||
|
int i;
|
||
|
TiXmlNode* child = node->FirstChild();
|
||
|
for ( i=0;
|
||
|
child && i<count;
|
||
|
child = child->NextSibling(), ++i )
|
||
|
{
|
||
|
// nothing
|
||
|
}
|
||
|
if ( child )
|
||
|
return TiXmlHandle( child );
|
||
|
}
|
||
|
return TiXmlHandle( 0 );
|
||
|
}
|
||
|
|
||
|
|
||
|
TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const
|
||
|
{
|
||
|
if ( node )
|
||
|
{
|
||
|
int i;
|
||
|
TiXmlNode* child = node->FirstChild( value );
|
||
|
for ( i=0;
|
||
|
child && i<count;
|
||
|
child = child->NextSibling( value ), ++i )
|
||
|
{
|
||
|
// nothing
|
||
|
}
|
||
|
if ( child )
|
||
|
return TiXmlHandle( child );
|
||
|
}
|
||
|
return TiXmlHandle( 0 );
|
||
|
}
|
||
|
|
||
|
|
||
|
TiXmlHandle TiXmlHandle::ChildElement( int count ) const
|
||
|
{
|
||
|
if ( node )
|
||
|
{
|
||
|
int i;
|
||
|
TiXmlElement* child = node->FirstChildElement();
|
||
|
for ( i=0;
|
||
|
child && i<count;
|
||
|
child = child->NextSiblingElement(), ++i )
|
||
|
{
|
||
|
// nothing
|
||
|
}
|
||
|
if ( child )
|
||
|
return TiXmlHandle( child );
|
||
|
}
|
||
|
return TiXmlHandle( 0 );
|
||
|
}
|
||
|
|
||
|
|
||
|
TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const
|
||
|
{
|
||
|
if ( node )
|
||
|
{
|
||
|
int i;
|
||
|
TiXmlElement* child = node->FirstChildElement( value );
|
||
|
for ( i=0;
|
||
|
child && i<count;
|
||
|
child = child->NextSiblingElement( value ), ++i )
|
||
|
{
|
||
|
// nothing
|
||
|
}
|
||
|
if ( child )
|
||
|
return TiXmlHandle( child );
|
||
|
}
|
||
|
return TiXmlHandle( 0 );
|
||
|
}
|