소스 검색

Patching up incorrect boilerplate code. Added clone/equal methods.

Lee Thomason 14 년 전
부모
커밋
7d00b9ab95
3개의 변경된 파일306개의 추가작업 그리고 30개의 파일을 삭제
  1. 198 8
      tinyxml2.cpp
  2. 74 22
      tinyxml2.h
  3. 34 0
      xmltest.cpp

+ 198 - 8
tinyxml2.cpp

@@ -402,12 +402,15 @@ char* XMLDocument::Identify( char* p, XMLNode** node )
 	static const int cdataHeaderLen		= 9;
 	static const int cdataHeaderLen		= 9;
 	static const int elementHeaderLen	= 1;
 	static const int elementHeaderLen	= 1;
 
 
+#if defined(_MSC_VER)
 #pragma warning ( push )
 #pragma warning ( push )
 #pragma warning ( disable : 4127 )
 #pragma warning ( disable : 4127 )
+#endif
 	TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLUnknown ) );		// use same memory pool
 	TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLUnknown ) );		// use same memory pool
 	TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLDeclaration ) );	// use same memory pool
 	TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLDeclaration ) );	// use same memory pool
+#if defined(_MSC_VER)
 #pragma warning (pop)
 #pragma warning (pop)
-
+#endif
 	if ( XMLUtil::StringEqual( p, xmlHeader, xmlHeaderLen ) ) {
 	if ( XMLUtil::StringEqual( p, xmlHeader, xmlHeaderLen ) ) {
 		returnNode = new (commentPool.Alloc()) XMLDeclaration( this );
 		returnNode = new (commentPool.Alloc()) XMLDeclaration( this );
 		returnNode->memPool = &commentPool;
 		returnNode->memPool = &commentPool;
@@ -622,6 +625,32 @@ const XMLElement* XMLNode::LastChildElement( const char* value ) const
 }
 }
 
 
 
 
+const XMLElement* XMLNode::NextSiblingElement( const char* value ) const
+{
+	for( XMLNode* element=this->next; element; element = element->next ) {
+		if (    element->ToElement() 
+			 && (!value || XMLUtil::StringEqual( value, element->Value() ))) 
+		{
+			return element->ToElement();
+		}
+	}
+	return 0;
+}
+
+
+const XMLElement* XMLNode::PreviousSiblingElement( const char* value ) const
+{
+	for( XMLNode* element=this->prev; element; element = element->prev ) {
+		if (    element->ToElement()
+			 && (!value || XMLUtil::StringEqual( value, element->Value() ))) 
+		{
+			return element->ToElement();
+		}
+	}
+	return 0;
+}
+
+
 char* XMLNode::ParseDeep( char* p, StrPair* parentEnd )
 char* XMLNode::ParseDeep( char* p, StrPair* parentEnd )
 {
 {
 	// This is a recursive method, but thinking about it "at the current level"
 	// This is a recursive method, but thinking about it "at the current level"
@@ -723,6 +752,23 @@ char* XMLText::ParseDeep( char* p, StrPair* )
 }
 }
 
 
 
 
+XMLNode* XMLText::ShallowClone( XMLDocument* doc ) const
+{
+	if ( !doc ) {
+		doc = document;
+	}
+	XMLText* text = doc->NewText( Value() );	// fixme: this will always allocate memory. Intern?
+	text->SetCData( this->CData() );
+	return text;
+}
+
+
+bool XMLText::ShallowEqual( const XMLNode* compare ) const
+{
+	return ( compare->ToText() && XMLUtil::StringEqual( compare->ToText()->Value(), Value() ));
+}
+
+
 bool XMLText::Accept( XMLVisitor* visitor ) const
 bool XMLText::Accept( XMLVisitor* visitor ) const
 {
 {
 	return visitor->Visit( *this );
 	return visitor->Visit( *this );
@@ -754,6 +800,22 @@ char* XMLComment::ParseDeep( char* p, StrPair* )
 }
 }
 
 
 
 
+XMLNode* XMLComment::ShallowClone( XMLDocument* doc ) const
+{
+	if ( !doc ) {
+		doc = document;
+	}
+	XMLComment* comment = doc->NewComment( Value() );	// fixme: this will always allocate memory. Intern?
+	return comment;
+}
+
+
+bool XMLComment::ShallowEqual( const XMLNode* compare ) const
+{
+	return ( compare->ToComment() && XMLUtil::StringEqual( compare->ToComment()->Value(), Value() ));
+}
+
+
 bool XMLComment::Accept( XMLVisitor* visitor ) const
 bool XMLComment::Accept( XMLVisitor* visitor ) const
 {
 {
 	return visitor->Visit( *this );
 	return visitor->Visit( *this );
@@ -785,6 +847,23 @@ char* XMLDeclaration::ParseDeep( char* p, StrPair* )
 }
 }
 
 
 
 
+XMLNode* XMLDeclaration::ShallowClone( XMLDocument* doc ) const
+{
+	if ( !doc ) {
+		doc = document;
+	}
+	XMLDeclaration* dec = doc->NewDeclaration( Value() );	// fixme: this will always allocate memory. Intern?
+	return dec;
+}
+
+
+bool XMLDeclaration::ShallowEqual( const XMLNode* compare ) const
+{
+	return ( compare->ToDeclaration() && XMLUtil::StringEqual( compare->ToDeclaration()->Value(), Value() ));
+}
+
+
+
 bool XMLDeclaration::Accept( XMLVisitor* visitor ) const
 bool XMLDeclaration::Accept( XMLVisitor* visitor ) const
 {
 {
 	return visitor->Visit( *this );
 	return visitor->Visit( *this );
@@ -815,6 +894,22 @@ char* XMLUnknown::ParseDeep( char* p, StrPair* )
 }
 }
 
 
 
 
+XMLNode* XMLUnknown::ShallowClone( XMLDocument* doc ) const
+{
+	if ( !doc ) {
+		doc = document;
+	}
+	XMLUnknown* text = doc->NewUnknown( Value() );	// fixme: this will always allocate memory. Intern?
+	return text;
+}
+
+
+bool XMLUnknown::ShallowEqual( const XMLNode* compare ) const
+{
+	return ( compare->ToUnknown() && XMLUtil::StringEqual( compare->ToUnknown()->Value(), Value() ));
+}
+
+
 bool XMLUnknown::Accept( XMLVisitor* visitor ) const
 bool XMLUnknown::Accept( XMLVisitor* visitor ) const
 {
 {
 	return visitor->Visit( *this );
 	return visitor->Visit( *this );
@@ -840,7 +935,7 @@ void XMLAttribute::SetName( const char* n )
 }
 }
 
 
 
 
-int XMLAttribute::QueryIntAttribute( int* value ) const
+int XMLAttribute::QueryIntValue( int* value ) const
 {
 {
 	if ( TIXML_SSCANF( Value(), "%d", value ) == 1 )
 	if ( TIXML_SSCANF( Value(), "%d", value ) == 1 )
 		return XML_NO_ERROR;
 		return XML_NO_ERROR;
@@ -848,7 +943,7 @@ int XMLAttribute::QueryIntAttribute( int* value ) const
 }
 }
 
 
 
 
-int XMLAttribute::QueryUnsignedAttribute( unsigned int* value ) const
+int XMLAttribute::QueryUnsignedValue( unsigned int* value ) const
 {
 {
 	if ( TIXML_SSCANF( Value(), "%u", value ) == 1 )
 	if ( TIXML_SSCANF( Value(), "%u", value ) == 1 )
 		return XML_NO_ERROR;
 		return XML_NO_ERROR;
@@ -856,10 +951,10 @@ int XMLAttribute::QueryUnsignedAttribute( unsigned int* value ) const
 }
 }
 
 
 
 
-int XMLAttribute::QueryBoolAttribute( bool* value ) const
+int XMLAttribute::QueryBoolValue( bool* value ) const
 {
 {
 	int ival = -1;
 	int ival = -1;
-	QueryIntAttribute( &ival );
+	QueryIntValue( &ival );
 
 
 	if ( ival > 0 || XMLUtil::StringEqual( Value(), "true" ) ) {
 	if ( ival > 0 || XMLUtil::StringEqual( Value(), "true" ) ) {
 		*value = true;
 		*value = true;
@@ -873,7 +968,7 @@ int XMLAttribute::QueryBoolAttribute( bool* value ) const
 }
 }
 
 
 
 
-int XMLAttribute::QueryDoubleAttribute( double* value ) const
+int XMLAttribute::QueryDoubleValue( double* value ) const
 {
 {
 	if ( TIXML_SSCANF( Value(), "%lf", value ) == 1 )
 	if ( TIXML_SSCANF( Value(), "%lf", value ) == 1 )
 		return XML_NO_ERROR;
 		return XML_NO_ERROR;
@@ -881,7 +976,7 @@ int XMLAttribute::QueryDoubleAttribute( double* value ) const
 }
 }
 
 
 
 
-int XMLAttribute::QueryFloatAttribute( float* value ) const
+int XMLAttribute::QueryFloatValue( float* value ) const
 {
 {
 	if ( TIXML_SSCANF( Value(), "%f", value ) == 1 )
 	if ( TIXML_SSCANF( Value(), "%f", value ) == 1 )
 		return XML_NO_ERROR;
 		return XML_NO_ERROR;
@@ -1103,6 +1198,43 @@ char* XMLElement::ParseDeep( char* p, StrPair* strPair )
 }
 }
 
 
 
 
+
+XMLNode* XMLElement::ShallowClone( XMLDocument* doc ) const
+{
+	if ( !doc ) {
+		doc = document;
+	}
+	XMLElement* element = doc->NewElement( Value() );					// fixme: this will always allocate memory. Intern?
+	for( const XMLAttribute* a=FirstAttribute(); a; a=a->Next() ) {
+		element->SetAttribute( a->Name(), a->Value() );					// fixme: this will always allocate memory. Intern?
+	}
+	return element;
+}
+
+
+bool XMLElement::ShallowEqual( const XMLNode* compare ) const
+{
+	const XMLElement* other = compare->ToElement();
+	if ( other && XMLUtil::StringEqual( other->Value(), Value() )) {
+
+		const XMLAttribute* a=FirstAttribute();
+		const XMLAttribute* b=other->FirstAttribute();
+
+		while ( a && b ) {
+			if ( !XMLUtil::StringEqual( a->Value(), b->Value() ) ) {
+				return false;
+			}
+		}	
+		if ( a || b ) {
+			// different count
+			return false;
+		}
+		return true;
+	}
+	return false;
+}
+
+
 bool XMLElement::Accept( XMLVisitor* visitor ) const
 bool XMLElement::Accept( XMLVisitor* visitor ) const
 {
 {
 	if ( visitor->VisitEnter( *this, rootAttribute ) ) 
 	if ( visitor->VisitEnter( *this, rootAttribute ) ) 
@@ -1114,9 +1246,9 @@ bool XMLElement::Accept( XMLVisitor* visitor ) const
 		}
 		}
 	}
 	}
 	return visitor->VisitExit( *this );
 	return visitor->VisitExit( *this );
-
 }
 }
 
 
+
 // --------- XMLDocument ----------- //
 // --------- XMLDocument ----------- //
 XMLDocument::XMLDocument() :
 XMLDocument::XMLDocument() :
 	XMLNode( 0 ),
 	XMLNode( 0 ),
@@ -1185,15 +1317,37 @@ XMLText* XMLDocument::NewText( const char* str )
 }
 }
 
 
 
 
+XMLDeclaration* XMLDocument::NewDeclaration( const char* str )
+{
+	XMLDeclaration* dec = new (commentPool.Alloc()) XMLDeclaration( this );
+	dec->memPool = &commentPool;
+	dec->SetValue( str );
+	return dec;
+}
+
+
+XMLUnknown* XMLDocument::NewUnknown( const char* str )
+{
+	XMLUnknown* unk = new (commentPool.Alloc()) XMLUnknown( this );
+	unk->memPool = &commentPool;
+	unk->SetValue( str );
+	return unk;
+}
+
+
 int XMLDocument::LoadFile( const char* filename )
 int XMLDocument::LoadFile( const char* filename )
 {
 {
 	DeleteChildren();
 	DeleteChildren();
 	InitDocument();
 	InitDocument();
 
 
+#if defined(_MSC_VER)
 #pragma warning ( push )
 #pragma warning ( push )
 #pragma warning ( disable : 4996 )		// Fail to see a compelling reason why this should be deprecated.
 #pragma warning ( disable : 4996 )		// Fail to see a compelling reason why this should be deprecated.
+#endif
 	FILE* fp = fopen( filename, "rb" );
 	FILE* fp = fopen( filename, "rb" );
+#if defined(_MSC_VER)
 #pragma warning ( pop )
 #pragma warning ( pop )
+#endif
 	if ( !fp ) {
 	if ( !fp ) {
 		SetError( ERROR_FILE_NOT_FOUND, filename, 0 );
 		SetError( ERROR_FILE_NOT_FOUND, filename, 0 );
 		return errorID;
 		return errorID;
@@ -1236,10 +1390,14 @@ int XMLDocument::LoadFile( FILE* fp )
 
 
 void XMLDocument::SaveFile( const char* filename )
 void XMLDocument::SaveFile( const char* filename )
 {
 {
+#if defined(_MSC_VER)
 #pragma warning ( push )
 #pragma warning ( push )
 #pragma warning ( disable : 4996 )		// Fail to see a compelling reason why this should be deprecated.
 #pragma warning ( disable : 4996 )		// Fail to see a compelling reason why this should be deprecated.
+#endif
 	FILE* fp = fopen( filename, "w" );
 	FILE* fp = fopen( filename, "w" );
+#if defined(_MSC_VER)
 #pragma warning ( pop )
 #pragma warning ( pop )
+#endif
 	XMLPrinter stream( fp );
 	XMLPrinter stream( fp );
 	Print( &stream );
 	Print( &stream );
 	fclose( fp );
 	fclose( fp );
@@ -1452,6 +1610,38 @@ void XMLPrinter::PushAttribute( const char* name, const char* value )
 }
 }
 
 
 
 
+void XMLPrinter::PushAttribute( const char* name, int v )
+{
+	char buf[BUF_SIZE];
+	TIXML_SNPRINTF( buf, BUF_SIZE-1, "%d", v );	
+	PushAttribute( name, buf );
+}
+
+
+void XMLPrinter::PushAttribute( const char* name, unsigned v )
+{
+	char buf[BUF_SIZE];
+	TIXML_SNPRINTF( buf, BUF_SIZE-1, "%u", v );	
+	PushAttribute( name, buf );
+}
+
+
+void XMLPrinter::PushAttribute( const char* name, bool v )
+{
+	char buf[BUF_SIZE];
+	TIXML_SNPRINTF( buf, BUF_SIZE-1, "%d", v ? 1 : 0 );	
+	PushAttribute( name, buf );
+}
+
+
+void XMLPrinter::PushAttribute( const char* name, double v )
+{
+	char buf[BUF_SIZE];
+	TIXML_SNPRINTF( buf, BUF_SIZE-1, "%f", v );	
+	PushAttribute( name, buf );
+}
+
+
 void XMLPrinter::CloseElement()
 void XMLPrinter::CloseElement()
 {
 {
 	--depth;
 	--depth;

+ 74 - 22
tinyxml2.h

@@ -21,7 +21,7 @@ must not be misrepresented as being the original software.
 distribution.
 distribution.
 */
 */
 
 
-#ifndef TINYXML_INCLUDED
+#ifndef TINYXML2_INCLUDED
 #define TINYXML2_INCLUDED
 #define TINYXML2_INCLUDED
 
 
 
 
@@ -30,8 +30,9 @@ distribution.
 #include <stdio.h>
 #include <stdio.h>
 #include <memory.h>
 #include <memory.h>
 
 
-/* TODO: create main page description.
+/* 
    TODO: add 'lastAttribute' for faster parsing.
    TODO: add 'lastAttribute' for faster parsing.
+   TODO: intern strings instead of allocation.
 */
 */
 /*
 /*
 	gcc: g++ -Wall tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
 	gcc: g++ -Wall tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
@@ -482,16 +483,16 @@ public:
 	XMLNode*	PreviousSibling()							{ return prev; }
 	XMLNode*	PreviousSibling()							{ return prev; }
 
 
 	/// Get the previous (left) sibling element of this node, with an opitionally supplied name.
 	/// Get the previous (left) sibling element of this node, with an opitionally supplied name.
-	const XMLNode*	PreviousSiblingElement( const char* value=0 ) const ;
-	XMLNode*	PreviousSiblingElement( const char* value=0 ) { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) ); }
+	const XMLElement*	PreviousSiblingElement( const char* value=0 ) const ;
+	XMLElement*	PreviousSiblingElement( const char* value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) ); }
 	
 	
 	/// Get the next (right) sibling node of this node.
 	/// Get the next (right) sibling node of this node.
 	const XMLNode*	NextSibling() const						{ return next; }
 	const XMLNode*	NextSibling() const						{ return next; }
 	XMLNode*	NextSibling()								{ return next; }
 	XMLNode*	NextSibling()								{ return next; }
 		
 		
 	/// Get the next (right) sibling element of this node, with an opitionally supplied name.
 	/// Get the next (right) sibling element of this node, with an opitionally supplied name.
-	const XMLNode*	NextSiblingElement( const char* value=0 ) const;
- 	XMLNode*	NextSiblingElement( const char* value=0 )	{ return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) ); }
+	const XMLElement*	NextSiblingElement( const char* value=0 ) const;
+ 	XMLElement*	NextSiblingElement( const char* value=0 )	{ return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) ); }
 
 
 	/**
 	/**
 		Add a child node as the last (right) child.
 		Add a child node as the last (right) child.
@@ -516,6 +517,25 @@ public:
 	*/
 	*/
 	void DeleteChild( XMLNode* node );
 	void DeleteChild( XMLNode* node );
 
 
+	/**
+		Make a copy of this node, but not its children.
+		You may pass in a Document pointer that will be
+		the owner of the new Node. If the 'document' is 
+		null, then the node returned will be allocated
+		from the current Document. (this->GetDocument())
+
+		Note: if called on a XMLDocument, this will return null.
+	*/
+	virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
+
+	/**
+		Test if 2 nodes are the same, but don't test children.
+		The 2 nodes do not need to be in the same Document.
+
+		Note: if called on a XMLDocument, this will return false.
+	*/
+	virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
+
 	/** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the 
 	/** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the 
 		XML tree will be conditionally visited and the host will be called back
 		XML tree will be conditionally visited and the host will be called back
 		via the TiXmlVisitor interface.
 		via the TiXmlVisitor interface.
@@ -593,6 +613,9 @@ public:
 	bool CData() const						{ return isCData; }
 	bool CData() const						{ return isCData; }
 
 
 	char* ParseDeep( char*, StrPair* endTag );
 	char* ParseDeep( char*, StrPair* endTag );
+	virtual XMLNode* ShallowClone( XMLDocument* document ) const;
+	virtual bool ShallowEqual( const XMLNode* compare ) const;
+
 
 
 protected:
 protected:
 	XMLText( XMLDocument* doc )	: XMLNode( doc ), isCData( false )	{}
 	XMLText( XMLDocument* doc )	: XMLNode( doc ), isCData( false )	{}
@@ -616,6 +639,8 @@ public:
 	virtual bool Accept( XMLVisitor* visitor ) const;
 	virtual bool Accept( XMLVisitor* visitor ) const;
 
 
 	char* ParseDeep( char*, StrPair* endTag );
 	char* ParseDeep( char*, StrPair* endTag );
+	virtual XMLNode* ShallowClone( XMLDocument* document ) const;
+	virtual bool ShallowEqual( const XMLNode* compare ) const;
 
 
 protected:
 protected:
 	XMLComment( XMLDocument* doc );
 	XMLComment( XMLDocument* doc );
@@ -648,6 +673,8 @@ public:
 	virtual bool Accept( XMLVisitor* visitor ) const;
 	virtual bool Accept( XMLVisitor* visitor ) const;
 
 
 	char* ParseDeep( char*, StrPair* endTag );
 	char* ParseDeep( char*, StrPair* endTag );
+	virtual XMLNode* ShallowClone( XMLDocument* document ) const;
+	virtual bool ShallowEqual( const XMLNode* compare ) const;
 
 
 protected:
 protected:
 	XMLDeclaration( XMLDocument* doc );
 	XMLDeclaration( XMLDocument* doc );
@@ -674,6 +701,8 @@ public:
 	virtual bool Accept( XMLVisitor* visitor ) const;
 	virtual bool Accept( XMLVisitor* visitor ) const;
 
 
 	char* ParseDeep( char*, StrPair* endTag );
 	char* ParseDeep( char*, StrPair* endTag );
+	virtual XMLNode* ShallowClone( XMLDocument* document ) const;
+	virtual bool ShallowEqual( const XMLNode* compare ) const;
 
 
 protected:
 protected:
 	XMLUnknown( XMLDocument* doc );
 	XMLUnknown( XMLDocument* doc );
@@ -685,6 +714,7 @@ protected:
 
 
 enum {
 enum {
 	XML_NO_ERROR = 0,
 	XML_NO_ERROR = 0,
+	XML_SUCCESS = 0,
 
 
 	NO_ATTRIBUTE,
 	NO_ATTRIBUTE,
 	WRONG_ATTRIBUTE_TYPE,
 	WRONG_ATTRIBUTE_TYPE,
@@ -723,29 +753,29 @@ public:
 	    If the value isn't an integer, 0 will be returned. There is no error checking;
 	    If the value isn't an integer, 0 will be returned. There is no error checking;
 		use QueryIntAttribute() if you need error checking.
 		use QueryIntAttribute() if you need error checking.
 	*/
 	*/
-	int		 IntAttribute() const				{ int i=0;		QueryIntAttribute( &i );		return i; }
+	int		 IntValue() const				{ int i=0;		QueryIntValue( &i );		return i; }
 	/// Query as an unsigned integer. See IntAttribute()
 	/// Query as an unsigned integer. See IntAttribute()
-	unsigned UnsignedAttribute() const			{ unsigned i=0; QueryUnsignedAttribute( &i );	return i; }
+	unsigned UnsignedValue() const			{ unsigned i=0; QueryUnsignedValue( &i );	return i; }
 	/// Query as a boolean. See IntAttribute()
 	/// Query as a boolean. See IntAttribute()
-	bool	 BoolAttribute() const				{ bool b=false; QueryBoolAttribute( &b );		return b; }
+	bool	 BoolValue() const				{ bool b=false; QueryBoolValue( &b );		return b; }
 	/// Query as a double. See IntAttribute()
 	/// Query as a double. See IntAttribute()
-	double 	 DoubleAttribute() const			{ double d=0;	QueryDoubleAttribute( &d );		return d; }
+	double 	 DoubleValue() const			{ double d=0;	QueryDoubleValue( &d );		return d; }
 	/// Query as a float. See IntAttribute()
 	/// Query as a float. See IntAttribute()
-	float	 FloatAttribute() const				{ float f=0;	QueryFloatAttribute( &f );		return f; }
+	float	 FloatValue() const				{ float f=0;	QueryFloatValue( &f );		return f; }
 
 
 	/** QueryIntAttribute interprets the attribute as an integer, and returns the value
 	/** QueryIntAttribute interprets the attribute as an integer, and returns the value
 		in the provided paremeter. The function will return XML_NO_ERROR on success,
 		in the provided paremeter. The function will return XML_NO_ERROR on success,
 		and WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
 		and WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
 	*/
 	*/
-	int QueryIntAttribute( int* value ) const;
+	int QueryIntValue( int* value ) const;
 	/// See QueryIntAttribute
 	/// See QueryIntAttribute
-	int QueryUnsignedAttribute( unsigned int* value ) const;
+	int QueryUnsignedValue( unsigned int* value ) const;
 	/// See QueryIntAttribute
 	/// See QueryIntAttribute
-	int QueryBoolAttribute( bool* value ) const;
+	int QueryBoolValue( bool* value ) const;
 	/// See QueryIntAttribute
 	/// See QueryIntAttribute
-	int QueryDoubleAttribute( double* value ) const;
+	int QueryDoubleValue( double* value ) const;
 	/// See QueryIntAttribute
 	/// See QueryIntAttribute
-	int QueryFloatAttribute( float* value ) const;
+	int QueryFloatValue( float* value ) const;
 
 
 	/// Set the attribute to a string value.
 	/// Set the attribute to a string value.
 	void SetAttribute( const char* value );
 	void SetAttribute( const char* value );
@@ -829,15 +859,15 @@ public:
 		QueryIntAttribute( "foo", &value );		// if "foo" isn't found, value will still be 10
 		QueryIntAttribute( "foo", &value );		// if "foo" isn't found, value will still be 10
 		@endverbatim
 		@endverbatim
 	*/
 	*/
-	int QueryIntAttribute( const char* name, int* value ) const					{ const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryIntAttribute( value ); } 
+	int QueryIntAttribute( const char* name, int* value ) const					{ const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryIntValue( value ); } 
 	/// See QueryIntAttribute()
 	/// See QueryIntAttribute()
-	int QueryUnsignedAttribute( const char* name, unsigned int* value ) const	{ const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryUnsignedAttribute( value ); }
+	int QueryUnsignedAttribute( const char* name, unsigned int* value ) const	{ const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryUnsignedValue( value ); }
 	/// See QueryIntAttribute()
 	/// See QueryIntAttribute()
-	int QueryBoolAttribute( const char* name, bool* value ) const				{ const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryBoolAttribute( value ); }
+	int QueryBoolAttribute( const char* name, bool* value ) const				{ const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryBoolValue( value ); }
 	/// See QueryIntAttribute()
 	/// See QueryIntAttribute()
-	int QueryDoubleAttribute( const char* name, double* value ) const			{ const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryDoubleAttribute( value ); }
+	int QueryDoubleAttribute( const char* name, double* value ) const			{ const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryDoubleValue( value ); }
 	/// See QueryIntAttribute()
 	/// See QueryIntAttribute()
-	int QueryFloatAttribute( const char* name, float* value ) const				{ const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryFloatAttribute( value ); }
+	int QueryFloatAttribute( const char* name, float* value ) const				{ const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryFloatValue( value ); }
 
 
 	/// Sets the named attribute to value.
 	/// Sets the named attribute to value.
 	void SetAttribute( const char* name, const char* value )	{ XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
 	void SetAttribute( const char* name, const char* value )	{ XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
@@ -898,6 +928,8 @@ public:
 	};
 	};
 	int ClosingType() const { return closingType; }
 	int ClosingType() const { return closingType; }
 	char* ParseDeep( char* p, StrPair* endTag );
 	char* ParseDeep( char* p, StrPair* endTag );
+	virtual XMLNode* ShallowClone( XMLDocument* document ) const;
+	virtual bool ShallowEqual( const XMLNode* compare ) const;
 
 
 private:
 private:
 	XMLElement( XMLDocument* doc );
 	XMLElement( XMLDocument* doc );
@@ -999,6 +1031,18 @@ public:
 		is managed by the Document.
 		is managed by the Document.
 	*/
 	*/
 	XMLText* NewText( const char* text );
 	XMLText* NewText( const char* text );
+	/**
+		Create a new Declaration associated with
+		this Document. The memory for the object
+		is managed by the Document.
+	*/
+	XMLDeclaration* NewDeclaration( const char* text );
+	/**
+		Create a new Unknown associated with
+		this Document. The memory for the object
+		is managed by the Document.
+	*/
+	XMLUnknown* NewUnknown( const char* text );
 
 
 	/**
 	/**
 		Delete a node associated with this documented.
 		Delete a node associated with this documented.
@@ -1022,6 +1066,9 @@ public:
 	// internal
 	// internal
 	char* Identify( char* p, XMLNode** node );
 	char* Identify( char* p, XMLNode** node );
 
 
+	virtual XMLNode* ShallowClone( XMLDocument* document ) const	{ return 0; }
+	virtual bool ShallowEqual( const XMLNode* compare ) const	{ return false; }
+
 private:
 private:
 	XMLDocument( const XMLDocument& );	// not supported
 	XMLDocument( const XMLDocument& );	// not supported
 	void operator=( const XMLDocument& );	// not supported
 	void operator=( const XMLDocument& );	// not supported
@@ -1101,6 +1148,10 @@ public:
 	void OpenElement( const char* name );
 	void OpenElement( const char* name );
 	/// If streaming, add an attribute to an open element.
 	/// If streaming, add an attribute to an open element.
 	void PushAttribute( const char* name, const char* value );
 	void PushAttribute( const char* name, const char* value );
+	void PushAttribute( const char* name, int value );
+	void PushAttribute( const char* name, unsigned value );
+	void PushAttribute( const char* name, bool value );
+	void PushAttribute( const char* name, double value );
 	/// If streaming, close the Element.
 	/// If streaming, close the Element.
 	void CloseElement();
 	void CloseElement();
 
 
@@ -1142,7 +1193,8 @@ private:
 	int textDepth;
 	int textDepth;
 
 
 	enum {
 	enum {
-		ENTITY_RANGE = 64
+		ENTITY_RANGE = 64,
+		BUF_SIZE = 200
 	};
 	};
 	bool entityFlag[ENTITY_RANGE];
 	bool entityFlag[ENTITY_RANGE];
 	bool restrictedEntityFlag[ENTITY_RANGE];
 	bool restrictedEntityFlag[ENTITY_RANGE];

+ 34 - 0
xmltest.cpp

@@ -302,11 +302,15 @@ int main( int /*argc*/, const char* /*argv*/ )
 		int okay = 0;
 		int okay = 0;
 
 
 
 
+#if defined(_MSC_VER)
 #pragma warning ( push )
 #pragma warning ( push )
 #pragma warning ( disable : 4996 )		// Fail to see a compelling reason why this should be deprecated.
 #pragma warning ( disable : 4996 )		// Fail to see a compelling reason why this should be deprecated.
+#endif
 		FILE* saved  = fopen( "utf8testout.xml", "r" );
 		FILE* saved  = fopen( "utf8testout.xml", "r" );
 		FILE* verify = fopen( "utf8testverify.xml", "r" );
 		FILE* verify = fopen( "utf8testverify.xml", "r" );
+#if defined(_MSC_VER)
 #pragma warning ( pop )
 #pragma warning ( pop )
+#endif
 
 
 		if ( saved && verify )
 		if ( saved && verify )
 		{
 		{
@@ -419,20 +423,28 @@ int main( int /*argc*/, const char* /*argv*/ )
 
 
 		XMLTest( "Entity transformation: read. ", expected, context, true );
 		XMLTest( "Entity transformation: read. ", expected, context, true );
 
 
+#if defined(_MSC_VER)
 #pragma warning ( push )
 #pragma warning ( push )
 #pragma warning ( disable : 4996 )		// Fail to see a compelling reason why this should be deprecated.
 #pragma warning ( disable : 4996 )		// Fail to see a compelling reason why this should be deprecated.
+#endif
 		FILE* textfile = fopen( "textfile.txt", "w" );
 		FILE* textfile = fopen( "textfile.txt", "w" );
+#if defined(_MSC_VER)
 #pragma warning ( pop )
 #pragma warning ( pop )
+#endif
 		if ( textfile )
 		if ( textfile )
 		{
 		{
 			XMLPrinter streamer( textfile );
 			XMLPrinter streamer( textfile );
 			psg->Accept( &streamer );
 			psg->Accept( &streamer );
 			fclose( textfile );
 			fclose( textfile );
 		}
 		}
+#if defined(_MSC_VER)
 #pragma warning ( push )
 #pragma warning ( push )
 #pragma warning ( disable : 4996 )		// Fail to see a compelling reason why this should be deprecated.
 #pragma warning ( disable : 4996 )		// Fail to see a compelling reason why this should be deprecated.
+#endif
 		textfile = fopen( "textfile.txt", "r" );
 		textfile = fopen( "textfile.txt", "r" );
+#if defined(_MSC_VER)
 #pragma warning ( pop )
 #pragma warning ( pop )
+#endif
 		TIXMLASSERT( textfile );
 		TIXMLASSERT( textfile );
 		if ( textfile )
 		if ( textfile )
 		{
 		{
@@ -618,6 +630,28 @@ int main( int /*argc*/, const char* /*argv*/ )
 		XMLTest( "Infinite loop test.", true, true );
 		XMLTest( "Infinite loop test.", true, true );
 	}
 	}
 #endif
 #endif
+	{
+		const char* pub = "<?xml version='1.0'?> <element><sub/></element> <!--comment--> <!DOCTYPE>";
+		XMLDocument doc;
+		doc.Parse( pub );
+
+		XMLDocument clone;
+		for( const XMLNode* node=doc.FirstChild(); node; node=node->NextSibling() ) {
+			XMLNode* copy = node->ShallowClone( &clone );
+			clone.InsertEndChild( copy );
+		}
+
+		clone.Print();
+
+		int count=0;
+		const XMLNode* a=clone.FirstChild();
+		const XMLNode* b=doc.FirstChild();
+		for( ; a && b; a=a->NextSibling(), b=b->NextSibling() ) {
+			++count;
+			XMLTest( "Clone and Equal", true, a->ShallowEqual( b ));
+		}
+		XMLTest( "Clone and Equal", 4, count );
+	}
 
 
 	#if defined( _MSC_VER )
 	#if defined( _MSC_VER )
 		_CrtMemCheckpoint( &endMemState );  
 		_CrtMemCheckpoint( &endMemState );