diff --git a/resources/dictionary.xml b/resources/dictionary.xml new file mode 100644 index 0000000..a9d1786 --- /dev/null +++ b/resources/dictionary.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + +]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tinyxml2.cpp b/tinyxml2.cpp index 53d78bd..8c21672 100755 --- a/tinyxml2.cpp +++ b/tinyxml2.cpp @@ -504,7 +504,8 @@ char* XMLDocument::Identify( char* p, XMLNode** node ) #pragma warning ( push ) #pragma warning ( disable : 4127 ) #endif - TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLUnknown ) ); // use same memory pool + TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLDtd ) ); // use same memory pool + TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLUnknown ) ); // use same memory pool TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLDeclaration ) ); // use same memory pool #if defined(_MSC_VER) #pragma warning (pop) @@ -527,7 +528,7 @@ char* XMLDocument::Identify( char* p, XMLNode** node ) text->SetCData( true ); } else if ( XMLUtil::StringEqual( p, dtdHeader, dtdHeaderLen ) ) { - returnNode = new (_commentPool.Alloc()) XMLUnknown( this ); + returnNode = new (_commentPool.Alloc()) XMLDtd( this ); returnNode->_memPool = &_commentPool; p += dtdHeaderLen; } @@ -1016,6 +1017,65 @@ bool XMLDeclaration::Accept( XMLVisitor* visitor ) const return visitor->Visit( *this ); } +// --------- XMLDtd ---------- // + +XMLDtd::XMLDtd( XMLDocument* doc ) : XMLNode( doc ) +{ +} + + +XMLDtd::~XMLDtd() +{ +} + + +char* XMLDtd::ParseDeep( char* p, StrPair* ) +{ + // Dtd parses as text. + char* start = p; + + // Find closing '>', skipping over any local definition contained between '[' and ']' + + while( *p && *p != '>' && *p != '[') ++p; + + if ( *p == '[' ) + { + while( *p && *p != ']' ) ++p; + while( *p && *p != '>' ) ++p; + } + + if ( *p != '>' ) { + _document->SetError( XML_ERROR_PARSING_UNKNOWN, start, 0 ); + } + + _value.Set(start, p, StrPair::NEEDS_NEWLINE_NORMALIZATION ); + + return p+1; +} + + +XMLNode* XMLDtd::ShallowClone( XMLDocument* doc ) const +{ + if ( !doc ) { + doc = _document; + } + XMLDtd* text = doc->NewDtd( Value() ); // fixme: this will always allocate memory. Intern? + return text; +} + + +bool XMLDtd::ShallowEqual( const XMLNode* compare ) const +{ + const XMLDtd* unknown = compare->ToDtd(); + return ( unknown && XMLUtil::StringEqual( unknown->Value(), Value() )); +} + + +bool XMLDtd::Accept( XMLVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + // --------- XMLUnknown ---------- // XMLUnknown::XMLUnknown( XMLDocument* doc ) : XMLNode( doc ) @@ -1689,6 +1749,14 @@ XMLDeclaration* XMLDocument::NewDeclaration( const char* str ) } +XMLDtd* XMLDocument::NewDtd( const char* str ) +{ + XMLDtd* dtd = new (_commentPool.Alloc()) XMLDtd( this ); + dtd->_memPool = &_commentPool; + dtd->SetValue( str ); + return dtd; +} + XMLUnknown* XMLDocument::NewUnknown( const char* str ) { XMLUnknown* unk = new (_commentPool.Alloc()) XMLUnknown( this ); @@ -2234,6 +2302,12 @@ bool XMLPrinter::Visit( const XMLDeclaration& declaration ) } +bool XMLPrinter::Visit( const XMLDtd& dtd ) +{ + PushUnknown( dtd.Value() ); + return true; +} + bool XMLPrinter::Visit( const XMLUnknown& unknown ) { PushUnknown( unknown.Value() ); diff --git a/tinyxml2.h b/tinyxml2.h index 1fdc928..6766669 100755 --- a/tinyxml2.h +++ b/tinyxml2.h @@ -135,6 +135,7 @@ class XMLComment; class XMLText; class XMLDeclaration; class XMLUnknown; +class XMLDtd; class XMLPrinter; /* @@ -474,6 +475,10 @@ public: virtual bool Visit( const XMLComment& /*comment*/ ) { return true; } + /// Visit a DTD node. + virtual bool Visit( const XMLDtd& /*unknown*/ ) { + return true; + } /// Visit an unknown node. virtual bool Visit( const XMLUnknown& /*unknown*/ ) { return true; @@ -647,6 +652,11 @@ public: virtual XMLDeclaration* ToDeclaration() { return 0; } + /// Safely cast to an DTD, or null. + virtual XMLDtd* ToDtd() { + return 0; + } + /// Safely cast to an Unknown, or null. virtual XMLUnknown* ToUnknown() { return 0; @@ -667,6 +677,10 @@ public: virtual const XMLDeclaration* ToDeclaration() const { return 0; } + virtual const XMLDtd* ToDtd() const { + return 0; + } + virtual const XMLUnknown* ToUnknown() const { return 0; } @@ -992,12 +1006,41 @@ protected: }; +/** The structure can contain internal definition that + may contains other entities. (Otherwise, these could + be handled as XMLUnknown nodes.) + It will be written back to the XML, unchanged, when the file + is saved. +*/ + +class TINYXML2_LIB XMLDtd : public XMLNode +{ + friend class XMLDocument; +public: + virtual XMLDtd* ToDtd() { + return this; + } + virtual const XMLDtd* ToDtd() const { + return this; + } + + virtual bool Accept( XMLVisitor* visitor ) const; + + char* ParseDeep( char*, StrPair* endTag ); + virtual XMLNode* ShallowClone( XMLDocument* document ) const; + virtual bool ShallowEqual( const XMLNode* compare ) const; + +protected: + XMLDtd( XMLDocument* doc ); + virtual ~XMLDtd(); + XMLDtd( const XMLDtd& ); // not supported + XMLDtd& operator=( const XMLDtd& ); // not supported +}; + /** Any tag that TinyXML-2 doesn't recognize is saved as an unknown. It is a tag of text, but should not be modified. It will be written back to the XML, unchanged, when the file is saved. - - DTD tags get thrown into XMLUnknowns. */ class TINYXML2_LIB XMLUnknown : public XMLNode { @@ -1638,6 +1681,13 @@ public: @endverbatim */ XMLDeclaration* NewDeclaration( const char* text=0 ); + /** + Create a new DTD associated with + this Document. The memory for the object + is managed by the Document. + */ + XMLDtd* NewDtd( const char* text ); + /** Create a new Unknown associated with this Document. The memory for the object @@ -1831,6 +1881,10 @@ public: XMLText* ToText() { return ( ( _node == 0 ) ? 0 : _node->ToText() ); } + /// Safe cast to XMLDtd. This can return null. + XMLDtd* ToDtd() { + return ( ( _node == 0 ) ? 0 : _node->ToDtd() ); + } /// Safe cast to XMLUnknown. This can return null. XMLUnknown* ToUnknown() { return ( ( _node == 0 ) ? 0 : _node->ToUnknown() ); @@ -1902,6 +1956,9 @@ public: const XMLText* ToText() const { return ( ( _node == 0 ) ? 0 : _node->ToText() ); } + const XMLDtd* ToDtd() const { + return ( ( _node == 0 ) ? 0 : _node->ToDtd() ); + } const XMLUnknown* ToUnknown() const { return ( ( _node == 0 ) ? 0 : _node->ToUnknown() ); } @@ -2013,6 +2070,7 @@ public: virtual bool Visit( const XMLText& text ); virtual bool Visit( const XMLComment& comment ); virtual bool Visit( const XMLDeclaration& declaration ); + virtual bool Visit( const XMLDtd& dtd); virtual bool Visit( const XMLUnknown& unknown ); /** diff --git a/xmltest.cpp b/xmltest.cpp index 56b6c82..d263ce9 100644 --- a/xmltest.cpp +++ b/xmltest.cpp @@ -90,10 +90,11 @@ void NullLineEndings( char* p ) } -int example_1() +int example_1(const char *xml_file) { XMLDocument doc; - doc.LoadFile( "resources/dream.xml" ); + + doc.LoadFile( xml_file ); return doc.ErrorID(); } @@ -324,7 +325,8 @@ int main( int argc, const char ** argv ) } fclose( fp ); - XMLTest( "Example-1", 0, example_1() ); + XMLTest( "Example-1", 0, example_1("resources/dream.xml") ); + XMLTest( "Example-1", 0, example_1("resources/dictionary.xml") ); XMLTest( "Example-2", 0, example_2() ); XMLTest( "Example-3", 0, example_3() ); XMLTest( "Example-4", true, example_4() ); @@ -455,9 +457,9 @@ int main( int argc, const char ** argv ) XMLTest( "Dream", "xml version=\"1.0\"", doc.FirstChild()->ToDeclaration()->Value() ); - XMLTest( "Dream", true, doc.FirstChild()->NextSibling()->ToUnknown() ? true : false ); + XMLTest( "Dream", true, doc.FirstChild()->NextSibling()->ToDtd() ? true : false ); XMLTest( "Dream", "DOCTYPE PLAY SYSTEM \"play.dtd\"", - doc.FirstChild()->NextSibling()->ToUnknown()->Value() ); + doc.FirstChild()->NextSibling()->ToDtd()->Value() ); XMLTest( "Dream", "And Robin shall restore amends.", doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() ); XMLTest( "Dream", "And Robin shall restore amends.", @@ -467,14 +469,36 @@ int main( int argc, const char ** argv ) doc2.LoadFile( "resources/out/dreamout.xml" ); XMLTest( "Dream-out", "xml version=\"1.0\"", doc2.FirstChild()->ToDeclaration()->Value() ); - XMLTest( "Dream-out", true, doc2.FirstChild()->NextSibling()->ToUnknown() ? true : false ); + XMLTest( "Dream-out", true, doc2.FirstChild()->NextSibling()->ToDtd() ? true : false ); XMLTest( "Dream-out", "DOCTYPE PLAY SYSTEM \"play.dtd\"", - doc2.FirstChild()->NextSibling()->ToUnknown()->Value() ); + doc2.FirstChild()->NextSibling()->ToDtd()->Value() ); XMLTest( "Dream-out", "And Robin shall restore amends.", doc2.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() ); //gNewTotal = gNew - newStart; } + { + // Test: Dictionary + XMLDocument doc; + doc.LoadFile( "resources/dictionary.xml" ); + + doc.SaveFile( "resources/out/dictionaryout.xml" ); + doc.PrintError(); + + XMLTest( "Dictionary", "xml version=\"1.0\" encoding=\"UTF-8\"", + doc.FirstChild()->ToDeclaration()->Value() ); + XMLTest( "Dictionary", true, doc.FirstChild()->NextSibling()->ToDtd() ? true : false ); + XMLTest( "Dictionary", "500M", + doc.LastChild()->LastChild()->FirstChild()->ToElement()->Attribute("size") ); + + XMLDocument doc2; + doc2.LoadFile( "resources/out/dictionaryout.xml" ); + XMLTest( "Dictionary-out", "xml version=\"1.0\" encoding=\"UTF-8\"", + doc2.FirstChild()->ToDeclaration()->Value() ); + XMLTest( "Dictionary-out", true, doc2.FirstChild()->NextSibling()->ToDtd() ? true : false ); + XMLTest( "Dictionary", "500M", + doc2.LastChild()->LastChild()->FirstChild()->ToElement()->Attribute("size") ); + } { @@ -822,7 +846,7 @@ int main( int argc, const char ** argv ) doc.LoadFile( "resources/out/test7.xml" ); doc.Print(); - const XMLUnknown* decl = doc.FirstChild()->NextSibling()->ToUnknown(); + const XMLDtd* decl = doc.FirstChild()->NextSibling()->ToDtd(); XMLTest( "Correct value of unknown.", "DOCTYPE PLAY SYSTEM 'play.dtd'", decl->Value() ); }