better end element parsing
diff --git a/tinyxml2.cpp b/tinyxml2.cpp
index 51cf795..73a4143 100644
--- a/tinyxml2.cpp
+++ b/tinyxml2.cpp
@@ -358,7 +358,7 @@
p = XMLUtil::SkipWhiteSpace( p );
if( !p || !*p )
{
- return 0;
+ return p;
}
// What is this thing?
@@ -409,11 +409,6 @@
returnNode = new (elementPool.Alloc()) XMLElement( this );
returnNode->memPool = &elementPool;
p += elementHeaderLen;
-
- p = XMLUtil::SkipWhiteSpace( p );
- if ( p && *p == '/' ) {
- ((XMLElement*)returnNode)->closingType = XMLElement::CLOSING;
- }
}
else {
returnNode = new (textPool.Alloc()) XMLText( this );
@@ -602,7 +597,7 @@
}
-char* XMLNode::ParseDeep( char* p )
+char* XMLNode::ParseDeep( char* p, StrPair* parentEnd )
{
// This is a recursive method, but thinking about it "at the current level"
// it is a pretty simple flat list:
@@ -617,69 +612,67 @@
// Where the closing element (/foo) *must* be the next thing after the opening
// element, and the names must match. BUT the tricky bit is that the closing
// element will be read by the child.
+ //
+ // 'endTag' is the end tag for this node, it is returned by a call to a child.
+ // 'parentEnd' is the end tag for the parent, which is filled in and returned.
while( p && *p ) {
XMLNode* node = 0;
- char* mark = p;
p = document->Identify( p, &node );
- if ( p == 0 ) {
+ if ( p == 0 || node == 0 ) {
break;
}
- // We read the end tag. Back up and return.
- if ( node && node->ToElement() && node->ToElement()->ClosingType() == XMLElement::CLOSING ) {
+ StrPair endTag;
+ p = node->ParseDeep( p, &endTag );
+ if ( !p ) {
DELETE_NODE( node );
- return mark;
+ node = 0;
+ break;
}
- if ( node ) {
- p = node->ParseDeep( p );
- if ( !p ) {
- DELETE_NODE( node );
- node = 0;
- break;
+ // We read the end tag. Return it to the parent.
+ if ( node->ToElement() && node->ToElement()->ClosingType() == XMLElement::CLOSING ) {
+ if ( parentEnd ) {
+ *parentEnd = ((XMLElement*)node)->value;
}
-
- XMLElement* ele = node->ToElement();
- if ( ele && ele->ClosingType() == XMLElement::OPEN ) {
- XMLNode* closingNode = 0;
- p = document->Identify( p, &closingNode );
- XMLElement* closingEle = closingNode ? closingNode->ToElement() : 0;
+ DELETE_NODE( node );
+ return p;
+ }
- if ( closingEle == 0 ) {
+ // Handle an end tag returned to this level.
+ // And handle a bunch of annoying errors.
+ XMLElement* ele = node->ToElement();
+ if ( ele ) {
+ if ( endTag.Empty() && ele->ClosingType() == XMLElement::OPEN ) {
+ document->SetError( ERROR_MISMATCHED_ELEMENT, node->Value(), 0 );
+ p = 0;
+ }
+ else if ( !endTag.Empty() && ele->ClosingType() != XMLElement::OPEN ) {
+ document->SetError( ERROR_MISMATCHED_ELEMENT, node->Value(), 0 );
+ p = 0;
+ }
+ else if ( !endTag.Empty() ) {
+ if ( !XMLUtil::StringEqual( endTag.GetStr(), node->Value() )) {
document->SetError( ERROR_MISMATCHED_ELEMENT, node->Value(), 0 );
p = 0;
}
- else if ( closingEle->ClosingType() != XMLElement::CLOSING ) {
- document->SetError( ERROR_MISMATCHED_ELEMENT, node->Value(), 0 );
- p = 0;
- }
- else
- {
- p = closingEle->ParseDeep( p );
- if ( !XMLUtil::StringEqual( closingEle->Value(), node->Value() )) {
- document->SetError( ERROR_MISMATCHED_ELEMENT, node->Value(), 0 );
- p = 0;
- }
- }
- // Else everything is fine, but we need to throw away the node.
- DELETE_NODE( closingNode );
- if ( p == 0 ) {
- DELETE_NODE( node );
- node = 0;
- }
}
- if ( node ) {
- this->InsertEndChild( node );
- }
+ }
+ if ( p == 0 ) {
+ DELETE_NODE( node );
+ node = 0;
+ }
+ if ( node ) {
+ this->InsertEndChild( node );
}
}
return 0;
}
// --------- XMLText ---------- //
-char* XMLText::ParseDeep( char* p )
+char* XMLText::ParseDeep( char* p, StrPair* )
{
const char* start = p;
if ( this->CData() ) {
@@ -721,7 +714,7 @@
}
-char* XMLComment::ParseDeep( char* p )
+char* XMLComment::ParseDeep( char* p, StrPair* )
{
// Comment parses as text.
const char* start = p;
@@ -752,7 +745,7 @@
}
-char* XMLDeclaration::ParseDeep( char* p )
+char* XMLDeclaration::ParseDeep( char* p, StrPair* )
{
// Declaration parses as text.
const char* start = p;
@@ -781,7 +774,7 @@
}
-char* XMLUnknown::ParseDeep( char* p )
+char* XMLUnknown::ParseDeep( char* p, StrPair* )
{
// Unknown parses as text.
const char* start = p;
@@ -1056,7 +1049,7 @@
// <ele></ele>
// <ele>foo<b>bar</b></ele>
//
-char* XMLElement::ParseDeep( char* p )
+char* XMLElement::ParseDeep( char* p, StrPair* strPair )
{
// Read the element name.
p = XMLUtil::SkipWhiteSpace( p );
@@ -1079,7 +1072,8 @@
if ( !p || !*p || closingType )
return p;
- p = XMLNode::ParseDeep( p );
+ p = XMLNode::ParseDeep( p, strPair );
+ // FIXME: proces end tage here??
return p;
}
@@ -1207,7 +1201,7 @@
return errorID;
}
- ParseDeep( charBuffer + (p-charBuffer) );
+ ParseDeep( charBuffer + (p-charBuffer), 0 );
return errorID;
}
@@ -1242,7 +1236,7 @@
memcpy( charBuffer, p, len+1 );
- ParseDeep( charBuffer );
+ ParseDeep( charBuffer, 0 );
return errorID;
}