Merge branch 'attribute' of github.com:leethomason/tinyxml2 into attribute

This commit is contained in:
Lee Thomason 2012-04-18 11:32:11 -07:00
commit 8713775d9b
3 changed files with 65 additions and 36 deletions

View File

@ -1092,34 +1092,33 @@ const char* XMLElement::GetText() const
} }
XMLAttribute* XMLElement::FindOrCreateAttribute( const char* name ) XMLAttribute* XMLElement::FindOrCreateAttribute( const char* name )
{ {
XMLAttribute* attrib = FindAttribute( name ); XMLAttribute* last = 0;
XMLAttribute* attrib = 0;
for( attrib = rootAttribute;
attrib;
last = attrib, attrib = attrib->next )
{
if ( XMLUtil::StringEqual( attrib->Name(), name ) ) {
break;
}
}
if ( !attrib ) { if ( !attrib ) {
attrib = new (document->attributePool.Alloc() ) XMLAttribute(); attrib = new (document->attributePool.Alloc() ) XMLAttribute();
attrib->memPool = &document->attributePool; attrib->memPool = &document->attributePool;
LinkAttribute( attrib ); if ( last ) {
last->next = attrib;
}
else {
rootAttribute = attrib;
}
attrib->SetName( name ); attrib->SetName( name );
} }
return attrib; return attrib;
} }
void XMLElement::LinkAttribute( XMLAttribute* attrib )
{
if ( rootAttribute ) {
XMLAttribute* end = rootAttribute;
while ( end->next )
end = end->next;
end->next = attrib;
}
else {
rootAttribute = attrib;
}
}
void XMLElement::DeleteAttribute( const char* name ) void XMLElement::DeleteAttribute( const char* name )
{ {
XMLAttribute* prev = 0; XMLAttribute* prev = 0;
@ -1142,6 +1141,7 @@ void XMLElement::DeleteAttribute( const char* name )
char* XMLElement::ParseAttributes( char* p ) char* XMLElement::ParseAttributes( char* p )
{ {
const char* start = p; const char* start = p;
XMLAttribute* prevAttribute = 0;
// Read the attributes. // Read the attributes.
while( p ) { while( p ) {
@ -1162,7 +1162,19 @@ char* XMLElement::ParseAttributes( char* p )
document->SetError( XML_ERROR_PARSING_ATTRIBUTE, start, p ); document->SetError( XML_ERROR_PARSING_ATTRIBUTE, start, p );
return 0; return 0;
} }
LinkAttribute( attrib ); // There is a minor bug here: if the attribute in the source xml
// document is duplicated, it will not be detected and the
// attribute will be doubly added. However, tracking the 'prevAttribute'
// avoids re-scanning the attribute list. Preferring performance for
// now, may reconsider in the future.
if ( prevAttribute ) {
prevAttribute->next = attrib;
prevAttribute = attrib;
}
else {
rootAttribute = attrib;
prevAttribute = rootAttribute;
}
} }
// end of the tag // end of the tag
else if ( *p == '/' && *(p+1) == '>' ) { else if ( *p == '/' && *(p+1) == '>' ) {

View File

@ -24,25 +24,13 @@ distribution.
#ifndef TINYXML2_INCLUDED #ifndef TINYXML2_INCLUDED
#define TINYXML2_INCLUDED #define TINYXML2_INCLUDED
#if 1 #include <cctype>
#include <cctype> #include <climits>
#include <climits> #include <cstdio>
#include <cstdio> #include <cstring>
#include <cstring> #include <cstdarg>
#include <cstdarg>
#else
// Not completely sure all the interesting systems
// can handle the new headers; can switch this if
// there is an include problem.
#include <limits.h>
#include <ctype.h>
#include <stdio.h>
#include <memory.h> // Needed by mac.
#endif
/* /*
TODO: add 'lastAttribute' for faster parsing.
TODO: intern strings instead of allocation. TODO: intern strings instead of allocation.
*/ */
/* /*
@ -978,10 +966,13 @@ private:
XMLAttribute* FindAttribute( const char* name ); XMLAttribute* FindAttribute( const char* name );
XMLAttribute* FindOrCreateAttribute( const char* name ); XMLAttribute* FindOrCreateAttribute( const char* name );
void LinkAttribute( XMLAttribute* attrib ); //void LinkAttribute( XMLAttribute* attrib );
char* ParseAttributes( char* p ); char* ParseAttributes( char* p );
int closingType; int closingType;
// The attribute list is ordered; there is no 'lastAttribute'
// because the list needs to be scanned for dupes before adding
// a new attribute.
XMLAttribute* rootAttribute; XMLAttribute* rootAttribute;
}; };

View File

@ -761,6 +761,32 @@ int main( int /*argc*/, const char ** /*argv*/ )
XMLTest( "Error in snprinf handling.", true, doc.Error() ); XMLTest( "Error in snprinf handling.", true, doc.Error() );
} }
{
// Attribute ordering.
static const char* xml = "<element attrib1=\"1\" attrib2=\"2\" attrib3=\"3\" />";
XMLDocument doc;
doc.Parse( xml );
XMLElement* ele = doc.FirstChildElement();
const XMLAttribute* a = ele->FirstAttribute();
XMLTest( "Attribute order", "1", a->Value() );
a = a->Next();
XMLTest( "Attribute order", "2", a->Value() );
a = a->Next();
XMLTest( "Attribute order", "3", a->Value() );
XMLTest( "Attribute order", "attrib3", a->Name() );
ele->DeleteAttribute( "attrib2" );
a = ele->FirstAttribute();
XMLTest( "Attribute order", "1", a->Value() );
a = a->Next();
XMLTest( "Attribute order", "3", a->Value() );
ele->DeleteAttribute( "attrib1" );
ele->DeleteAttribute( "attrib3" );
XMLTest( "Attribute order (empty)", false, ele->FirstAttribute() ? true : false );
}
// -------- Handles ------------ // -------- Handles ------------
{ {
static const char* xml = "<element attrib='bar'><sub>Text</sub></element>"; static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";