?? tinyxml.cpp
字號:
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( FILE* cfile, int depth ) const
{
int i;
for ( i=0; i<depth; i++ )
{
fprintf( cfile, " " );
}
fprintf( cfile, "<%s", value.c_str() );
const TiXmlAttribute* attrib;
for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
{
fprintf( cfile, " " );
attrib->Print( cfile, 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 )
{
fprintf( cfile, " />" );
}
else if ( firstChild == lastChild && firstChild->ToText() )
{
fprintf( cfile, ">" );
firstChild->Print( cfile, depth + 1 );
fprintf( cfile, "</%s>", value.c_str() );
}
else
{
fprintf( cfile, ">" );
for ( node = firstChild; node; node=node->NextSibling() )
{
if ( !node->ToText() )
{
fprintf( cfile, "\n" );
}
node->Print( cfile, depth+1 );
}
fprintf( cfile, "\n" );
for( i=0; i<depth; ++i )
fprintf( cfile, " " );
fprintf( cfile, "</%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 char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
{
tabsize = 4;
useMicrosoftBOM = false;
value = documentName;
ClearError();
}
#ifdef TIXML_USE_STL
TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
{
tabsize = 4;
useMicrosoftBOM = false;
value = documentName;
ClearError();
}
#endif
TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT )
{
copy.CopyTo( this );
}
void TiXmlDocument::operator=( const TiXmlDocument& copy )
{
Clear();
copy.CopyTo( this );
}
bool TiXmlDocument::LoadFile( TiXmlEncoding encoding )
{
// See STL_STRING_BUG below.
StringToBuffer buf( value );
if ( buf.buffer && LoadFile( buf.buffer, encoding ) )
return true;
return false;
}
bool TiXmlDocument::SaveFile() const
{
// See STL_STRING_BUG below.
StringToBuffer buf( value );
if ( buf.buffer && SaveFile( buf.buffer ) )
return true;
return false;
}
bool TiXmlDocument::LoadFile( const char* filename, TiXmlEncoding encoding )
{
// There was a really terrifying little bug here. The code:
// value = filename
// in the STL case, cause the assignment method of the std::string to
// be called. What is strange, is that the std::string had the same
// address as it's c_str() method, and so bad things happen. Looks
// like a bug in the Microsoft STL implementation.
// See STL_STRING_BUG above.
// Fixed with the StringToBuffer class.
value = filename;
// reading in binary mode so that tinyxml can normalize the EOL
FILE* file = fopen( value.c_str (), "rb" );
if ( file )
{
bool result = LoadFile( file, encoding );
fclose( file );
return result;
}
else
{
SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
return false;
}
}
bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding )
{
if ( !file )
{
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 = 0;
fseek( file, 0, SEEK_END );
length = ftell( file );
fseek( file, 0, SEEK_SET );
// 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 ( fread( buf, length, 1, file ) != 1 ) {
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::SaveFile( const char * filename ) const
{
// The old c stuff lives on...
FILE* fp = fopen( filename, "w" );
if ( fp )
{
bool result = SaveFile( fp );
fclose( fp );
return result;
}
return false;
}
bool TiXmlDocument::SaveFile( FILE* fp ) const
{
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;
fputc( TIXML_UTF_LEAD_0, fp );
fputc( TIXML_UTF_LEAD_1, fp );
fputc( TIXML_UTF_LEAD_2, fp );
}
Print( fp, 0 );
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;
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -