mirror of https://github.com/AxioDL/tinyxml2.git
Merge branch 'attribute' of github.com:leethomason/tinyxml2 into attribute
This commit is contained in:
commit
8713775d9b
48
tinyxml2.cpp
48
tinyxml2.cpp
|
@ -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) == '>' ) {
|
||||||
|
|
27
tinyxml2.h
27
tinyxml2.h
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
26
xmltest.cpp
26
xmltest.cpp
|
@ -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>";
|
||||||
|
|
Loading…
Reference in New Issue