diff --git a/tinyxml2.cpp b/tinyxml2.cpp index c860c07..ee0f88c 100644 --- a/tinyxml2.cpp +++ b/tinyxml2.cpp @@ -210,24 +210,45 @@ char* XMLDocument::Identify( char* p, XMLNode** node ) static const int cdataHeaderLen = 9; static const int elementHeaderLen = 1; - if ( XMLUtil::StringEqual( p, commentHeader, commentHeaderLen ) ) { + TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLUnknown ) ); // use same memory pool + TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLDeclaration ) ); // use same memory pool + + if ( XMLUtil::StringEqual( p, xmlHeader, xmlHeaderLen ) ) { + returnNode = new (commentPool.Alloc()) XMLDeclaration( this ); + returnNode->memPool = &commentPool; + p += xmlHeaderLen; + } + else if ( XMLUtil::StringEqual( p, commentHeader, commentHeaderLen ) ) { returnNode = new (commentPool.Alloc()) XMLComment( this ); returnNode->memPool = &commentPool; p += commentHeaderLen; } + else if ( XMLUtil::StringEqual( p, cdataHeader, cdataHeaderLen ) ) { + XMLText* text = new (textPool.Alloc()) XMLText( this ); + returnNode = text; + returnNode->memPool = &textPool; + p += cdataHeaderLen; + text->SetCData( true ); + } + else if ( XMLUtil::StringEqual( p, dtdHeader, dtdHeaderLen ) ) { + returnNode = new (commentPool.Alloc()) XMLUnknown( this ); + returnNode->memPool = &commentPool; + p += dtdHeaderLen; + } else if ( XMLUtil::StringEqual( p, elementHeader, elementHeaderLen ) ) { returnNode = new (elementPool.Alloc()) XMLElement( this ); returnNode->memPool = &elementPool; p += elementHeaderLen; } - // fixme: better text detection else if ( (*p != '<') && XMLUtil::IsAlphaNum( *p ) ) { returnNode = new (textPool.Alloc()) XMLText( this ); returnNode->memPool = &textPool; p = start; // Back it up, all the text counts. } else { - TIXMLASSERT( 0 ); + this->SetError( ERROR_IDENTIFYING_TAG, p, 0 ); + p = 0; + returnNode = 0; } *node = returnNode; @@ -393,24 +414,21 @@ char* XMLNode::ParseDeep( char* p ) // --------- XMLText ---------- // char* XMLText::ParseDeep( char* p ) { - p = value.ParseText( p, "<", StrPair::TEXT_ELEMENT ); - // consumes the end tag. - if ( p && *p ) { - return p-1; + if ( this->CData() ) { + p = value.ParseText( p, "]]>", StrPair::NEEDS_NEWLINE_NORMALIZATION ); + return p; + } + else { + p = value.ParseText( p, "<", StrPair::TEXT_ELEMENT ); + // consumes the end tag. + if ( p && *p ) { + return p-1; + } } return 0; } -/* -void XMLText::Print( XMLStreamer* streamer ) -{ - const char* v = value.GetStr(); - streamer->PushText( v ); -} -*/ - - bool XMLText::Accept( XMLVisitor* visitor ) const { return visitor->Visit( *this ); @@ -430,16 +448,6 @@ XMLComment::~XMLComment() } -/* -void XMLComment::Print( XMLStreamer* streamer ) -{ -// XMLNode::Print( fp, depth ); -// fprintf( fp, "\n", value.GetStr() ); - streamer->PushComment( value.GetStr() ); -} -*/ - - char* XMLComment::ParseDeep( char* p ) { // Comment parses as text. @@ -453,6 +461,55 @@ bool XMLComment::Accept( XMLVisitor* visitor ) const } +// --------- XMLDeclaration ---------- // + +XMLDeclaration::XMLDeclaration( XMLDocument* doc ) : XMLNode( doc ) +{ +} + + +XMLDeclaration::~XMLDeclaration() +{ + //printf( "~XMLDeclaration\n" ); +} + + +char* XMLDeclaration::ParseDeep( char* p ) +{ + // Declaration parses as text. + return value.ParseText( p, ">", StrPair::NEEDS_NEWLINE_NORMALIZATION ); +} + + +bool XMLDeclaration::Accept( XMLVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + +// --------- XMLUnknown ---------- // + +XMLUnknown::XMLUnknown( XMLDocument* doc ) : XMLNode( doc ) +{ +} + + +XMLUnknown::~XMLUnknown() +{ +} + + +char* XMLUnknown::ParseDeep( char* p ) +{ + // Unknown parses as text. + return value.ParseText( p, ">", StrPair::NEEDS_NEWLINE_NORMALIZATION ); +} + + +bool XMLUnknown::Accept( XMLVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + // --------- XMLAttribute ---------- // char* XMLAttribute::ParseDeep( char* p ) { @@ -862,14 +919,18 @@ void XMLStreamer::SealElement() } -void XMLStreamer::PushText( const char* text ) +void XMLStreamer::PushText( const char* text, bool cdata ) { textDepth = depth-1; if ( elementJustOpened ) { SealElement(); } + if ( cdata ) + fprintf( fp, "" ); } diff --git a/tinyxml2.h b/tinyxml2.h index d02e5cd..27f38c9 100644 --- a/tinyxml2.h +++ b/tinyxml2.h @@ -1,4 +1,4 @@ -#ifndef TINYXML2_INCLUDED +#ifndef TINYXML_INCLUDED #define TINYXML2_INCLUDED /* @@ -50,6 +50,8 @@ class XMLAttribute; class XMLComment; class XMLNode; class XMLText; +class XMLDeclaration; +class XMLUnknown; class XMLStreamer; @@ -267,13 +269,13 @@ public: virtual bool VisitExit( const XMLElement& /*element*/ ) { return true; } /// Visit a declaration - //virtual bool Visit( const TiXmlDeclaration& /*declaration*/ ) { return true; } + virtual bool Visit( const XMLDeclaration& /*declaration*/ ) { return true; } /// Visit a text node virtual bool Visit( const XMLText& /*text*/ ) { return true; } /// Visit a comment node virtual bool Visit( const XMLComment& /*comment*/ ) { return true; } /// Visit an unknown node - //virtual bool Visit( const TiXmlUnknown& /*unknown*/ ) { return true; } + virtual bool Visit( const XMLUnknown& /*unknown*/ ) { return true; } }; @@ -316,11 +318,15 @@ public: virtual XMLText* ToText() { return 0; } virtual XMLComment* ToComment() { return 0; } virtual XMLDocument* ToDocument() { return 0; } + virtual XMLDeclaration* ToDeclaration() { return 0; } + virtual XMLUnknown* ToUnknown() { return 0; } - virtual const XMLElement* ToElement() const { return 0; } - virtual const XMLText* ToText() const { return 0; } - virtual const XMLComment* ToComment() const { return 0; } - virtual const XMLDocument* ToDocument() const { return 0; } + virtual const XMLElement* ToElement() const { return 0; } + virtual const XMLText* ToText() const { return 0; } + virtual const XMLComment* ToComment() const { return 0; } + virtual const XMLDocument* ToDocument() const { return 0; } + virtual const XMLDeclaration* ToDeclaration() const { return 0; } + virtual const XMLUnknown* ToUnknown() const { return 0; } const char* Value() const { return value.GetStr(); } void SetValue( const char* val ) { value.SetInternedStr( val ); } @@ -328,8 +334,8 @@ public: const XMLNode* Parent() const { return parent; } XMLNode* Parent() { return parent; } - /// Returns true if this node has no children. - bool NoChildren() const { return !firstChild; } + /// Returns true if this node has no children. + bool NoChildren() const { return !firstChild; } const XMLNode* FirstChild() const { return firstChild; } XMLNode* FirstChild() { return firstChild; } @@ -395,25 +401,26 @@ class XMLText : public XMLNode friend class XMLBase; friend class XMLDocument; public: - //virtual void Print( XMLStreamer* streamer ); - virtual bool Accept( XMLVisitor* visitor ) const; virtual XMLText* ToText() { return this; } virtual const XMLText* ToText() const { return this; } + void SetCData( bool value ) { isCData = true; } + bool CData() const { return isCData; } + char* ParseDeep( char* ); protected: - XMLText( XMLDocument* doc ) : XMLNode( doc ) {} - virtual ~XMLText() {} + XMLText( XMLDocument* doc ) : XMLNode( doc ), isCData( false ) {} + virtual ~XMLText() {} private: + bool isCData; }; class XMLComment : public XMLNode { - friend class XMLBase; friend class XMLDocument; public: virtual XMLComment* ToComment() { return this; } @@ -431,6 +438,40 @@ private: }; +class XMLDeclaration : public XMLNode +{ + friend class XMLDocument; +public: + virtual XMLDeclaration* ToDeclaration() { return this; } + virtual const XMLDeclaration* ToDeclaration() const { return this; } + + virtual bool Accept( XMLVisitor* visitor ) const; + + char* ParseDeep( char* ); + +protected: + XMLDeclaration( XMLDocument* doc ); + virtual ~XMLDeclaration(); +}; + + +class XMLUnknown : public XMLNode +{ + friend class XMLDocument; +public: + virtual XMLUnknown* ToUnknown() { return this; } + virtual const XMLUnknown* ToUnknown() const { return this; } + + virtual bool Accept( XMLVisitor* visitor ) const; + + char* ParseDeep( char* ); + +protected: + XMLUnknown( XMLDocument* doc ); + virtual ~XMLUnknown(); +}; + + class XMLAttribute { friend class XMLElement; @@ -470,20 +511,20 @@ public: int QueryIntAttribute( const char* name, int* value ) const; int QueryUnsignedAttribute( const char* name, unsigned int* value ) const; int QueryBoolAttribute( const char* name, bool* value ) const; - int QueryDoubleAttribute( const char* name, double* _value ) const; - int QueryFloatAttribute( const char* name, float* _value ) const; - - void SetAttribute( const char* name, const char* value ); - void SetAttribute( const char* name, int value ); - void SetAttribute( const char* name, unsigned value ); - void SetAttribute( const char* name, bool value ); - void SetAttribute( const char* name, double value ); - - void RemoveAttribute( const char* name ); + int QueryDoubleAttribute( const char* name, double* _value ) const; + int QueryFloatAttribute( const char* name, float* _value ) const; + + void SetAttribute( const char* name, const char* value ); + void SetAttribute( const char* name, int value ); + void SetAttribute( const char* name, unsigned value ); + void SetAttribute( const char* name, bool value ); + void SetAttribute( const char* name, double value ); + + void RemoveAttribute( const char* name ); const XMLAttribute* FirstAttribute() const { return rootAttribute; } - const char* GetText() const; + const char* GetText() const; // internal: virtual bool IsClosingElement() const { return closing; } @@ -525,7 +566,8 @@ public: NO_ERROR = 0, ERROR_ELEMENT_MISMATCH, ERROR_PARSING_ELEMENT, - ERROR_PARSING_ATTRIBUTE + ERROR_PARSING_ATTRIBUTE, + ERROR_IDENTIFYING_TAG }; void SetError( int error, const char* str1, const char* str2 ); @@ -563,7 +605,7 @@ public: void PushAttribute( const char* name, const char* value ); void CloseElement(); - void PushText( const char* text ); + void PushText( const char* text, bool cdata=false ); void PushComment( const char* comment ); virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { return true; }