improved the streamer interface so it doesn't require text parent. now possible to connect visitor and streamer.

This commit is contained in:
Lee Thomason 2012-02-09 18:16:58 -08:00
parent 43f59307cc
commit 56bdd0259e
3 changed files with 206 additions and 74 deletions

View File

@ -128,9 +128,9 @@ const char* StringPool::Intern( const char* str )
*/ */
// --------- XMLBase ----------- // // --------- XMLUtil ----------- //
char* XMLBase::ParseText( char* p, StrPair* pair, const char* endTag, int strFlags ) char* StrPair::ParseText( char* p, const char* endTag, int strFlags )
{ {
TIXMLASSERT( endTag && *endTag ); TIXMLASSERT( endTag && *endTag );
@ -141,7 +141,7 @@ char* XMLBase::ParseText( char* p, StrPair* pair, const char* endTag, int strFla
// Inner loop of text parsing. // Inner loop of text parsing.
while ( *p ) { while ( *p ) {
if ( *p == endChar && strncmp( p, endTag, length ) == 0 ) { if ( *p == endChar && strncmp( p, endTag, length ) == 0 ) {
pair->Set( start, p, strFlags ); Set( start, p, strFlags );
return p + length; return p + length;
} }
++p; ++p;
@ -150,7 +150,7 @@ char* XMLBase::ParseText( char* p, StrPair* pair, const char* endTag, int strFla
} }
char* XMLBase::ParseName( char* p, StrPair* pair ) char* StrPair::ParseName( char* p )
{ {
char* start = p; char* start = p;
@ -159,12 +159,12 @@ char* XMLBase::ParseName( char* p, StrPair* pair )
return 0; return 0;
} }
if ( !IsAlpha( *p ) ) { if ( !XMLUtil::IsAlpha( *p ) ) {
return 0; return 0;
} }
while( *p && ( while( *p && (
IsAlphaNum( (unsigned char) *p ) XMLUtil::IsAlphaNum( (unsigned char) *p )
|| *p == '_' || *p == '_'
|| *p == '-' || *p == '-'
|| *p == '.' || *p == '.'
@ -174,7 +174,7 @@ char* XMLBase::ParseName( char* p, StrPair* pair )
} }
if ( p > start ) { if ( p > start ) {
pair->Set( start, p, 0 ); Set( start, p, 0 );
return p; return p;
} }
return 0; return 0;
@ -185,7 +185,7 @@ char* XMLDocument::Identify( char* p, XMLNode** node )
{ {
XMLNode* returnNode = 0; XMLNode* returnNode = 0;
char* start = p; char* start = p;
p = XMLBase::SkipWhiteSpace( p ); p = XMLUtil::SkipWhiteSpace( p );
if( !p || !*p ) if( !p || !*p )
{ {
return 0; return 0;
@ -210,18 +210,18 @@ 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 ( XMLBase::StringEqual( p, commentHeader, commentHeaderLen ) ) { if ( XMLUtil::StringEqual( p, commentHeader, commentHeaderLen ) ) {
returnNode = new (commentPool.Alloc()) XMLComment( this ); returnNode = new (commentPool.Alloc()) XMLComment( this );
returnNode->memPool = &commentPool; returnNode->memPool = &commentPool;
p += commentHeaderLen; p += commentHeaderLen;
} }
else if ( XMLBase::StringEqual( p, elementHeader, elementHeaderLen ) ) { else if ( XMLUtil::StringEqual( p, elementHeader, elementHeaderLen ) ) {
returnNode = new (elementPool.Alloc()) XMLElement( this ); returnNode = new (elementPool.Alloc()) XMLElement( this );
returnNode->memPool = &elementPool; returnNode->memPool = &elementPool;
p += elementHeaderLen; p += elementHeaderLen;
} }
// fixme: better text detection // fixme: better text detection
else if ( (*p != '<') && XMLBase::IsAlphaNum( *p ) ) { else if ( (*p != '<') && XMLUtil::IsAlphaNum( *p ) ) {
returnNode = new (textPool.Alloc()) XMLText( this ); returnNode = new (textPool.Alloc()) XMLText( this );
returnNode->memPool = &textPool; returnNode->memPool = &textPool;
p = start; // Back it up, all the text counts. p = start; // Back it up, all the text counts.
@ -235,6 +235,20 @@ char* XMLDocument::Identify( char* p, XMLNode** node )
} }
bool XMLDocument::Accept( XMLVisitor* visitor ) const
{
if ( visitor->VisitEnter( *this ) )
{
for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() )
{
if ( !node->Accept( visitor ) )
break;
}
}
return visitor->VisitExit( *this );
}
// --------- XMLNode ----------- // // --------- XMLNode ----------- //
XMLNode::XMLNode( XMLDocument* doc ) : XMLNode::XMLNode( XMLDocument* doc ) :
@ -314,12 +328,12 @@ XMLNode* XMLNode::InsertEndChild( XMLNode* addThis )
} }
XMLElement* XMLNode::FirstChildElement( const char* value ) const XMLElement* XMLNode::FirstChildElement( const char* value ) const
{ {
for( XMLNode* node=firstChild; node; node=node->next ) { for( XMLNode* node=firstChild; node; node=node->next ) {
XMLElement* element = node->ToElement(); XMLElement* element = node->ToElement();
if ( element ) { if ( element ) {
if ( !value || XMLBase::StringEqual( element->Name(), value ) ) { if ( !value || XMLUtil::StringEqual( element->Name(), value ) ) {
return element; return element;
} }
} }
@ -328,6 +342,27 @@ XMLElement* XMLNode::FirstChildElement( const char* value )
} }
const XMLElement* XMLNode::LastChildElement( const char* value ) const
{
for( XMLNode* node=lastChild; node; node=node->prev ) {
XMLElement* element = node->ToElement();
if ( element ) {
if ( !value || XMLUtil::StringEqual( element->Name(), value ) ) {
return element;
}
}
}
return 0;
}
void XMLNode::DeleteChild( XMLNode* node )
{
TIXMLASSERT( node->parent == this );
TIXMLASSERT( 0 );
}
void XMLNode::Print( XMLStreamer* streamer ) void XMLNode::Print( XMLStreamer* streamer )
{ {
for( XMLNode* node = firstChild; node; node=node->next ) { for( XMLNode* node = firstChild; node; node=node->next ) {
@ -357,7 +392,7 @@ char* XMLNode::ParseDeep( char* p )
// --------- XMLText ---------- // // --------- XMLText ---------- //
char* XMLText::ParseDeep( char* p ) char* XMLText::ParseDeep( char* p )
{ {
p = XMLBase::ParseText( p, &value, "<", StrPair::TEXT_ELEMENT ); p = value.ParseText( p, "<", StrPair::TEXT_ELEMENT );
// consumes the end tag. // consumes the end tag.
if ( p && *p ) { if ( p && *p ) {
return p-1; return p-1;
@ -373,6 +408,12 @@ void XMLText::Print( XMLStreamer* streamer )
} }
bool XMLText::Accept( XMLVisitor* visitor ) const
{
return visitor->Visit( *this );
}
// --------- XMLComment ---------- // // --------- XMLComment ---------- //
XMLComment::XMLComment( XMLDocument* doc ) : XMLNode( doc ) XMLComment::XMLComment( XMLDocument* doc ) : XMLNode( doc )
@ -397,19 +438,25 @@ void XMLComment::Print( XMLStreamer* streamer )
char* XMLComment::ParseDeep( char* p ) char* XMLComment::ParseDeep( char* p )
{ {
// Comment parses as text. // Comment parses as text.
return XMLBase::ParseText( p, &value, "-->", StrPair::COMMENT ); return value.ParseText( p, "-->", StrPair::COMMENT );
} }
bool XMLComment::Accept( XMLVisitor* visitor ) const
{
return visitor->Visit( *this );
}
// --------- XMLAttribute ---------- // // --------- XMLAttribute ---------- //
char* XMLAttribute::ParseDeep( char* p ) char* XMLAttribute::ParseDeep( char* p )
{ {
p = XMLBase::ParseText( p, &name, "=", StrPair::ATTRIBUTE_NAME ); p = name.ParseText( p, "=", StrPair::ATTRIBUTE_NAME );
if ( !p || !*p ) return 0; if ( !p || !*p ) return 0;
char endTag[2] = { *p, 0 }; char endTag[2] = { *p, 0 };
++p; ++p;
p = XMLBase::ParseText( p, &value, endTag, StrPair::ATTRIBUTE_VALUE ); p = value.ParseText( p, endTag, StrPair::ATTRIBUTE_VALUE );
if ( value.Empty() ) return 0; if ( value.Empty() ) return 0;
return p; return p;
} }
@ -452,14 +499,14 @@ char* XMLElement::ParseAttributes( char* p, bool* closedElement )
// Read the attributes. // Read the attributes.
while( p ) { while( p ) {
p = XMLBase::SkipWhiteSpace( p ); p = XMLUtil::SkipWhiteSpace( p );
if ( !p || !(*p) ) { if ( !p || !(*p) ) {
document->SetError( XMLDocument::ERROR_PARSING_ELEMENT, start, Name() ); document->SetError( XMLDocument::ERROR_PARSING_ELEMENT, start, Name() );
return 0; return 0;
} }
// attribute. // attribute.
if ( XMLBase::IsAlpha( *p ) ) { if ( XMLUtil::IsAlpha( *p ) ) {
XMLAttribute* attrib = new (document->attributePool.Alloc() ) XMLAttribute( this ); XMLAttribute* attrib = new (document->attributePool.Alloc() ) XMLAttribute( this );
attrib->memPool = &document->attributePool; attrib->memPool = &document->attributePool;
@ -508,7 +555,7 @@ char* XMLElement::ParseAttributes( char* p, bool* closedElement )
char* XMLElement::ParseDeep( char* p ) char* XMLElement::ParseDeep( char* p )
{ {
// Read the element name. // Read the element name.
p = XMLBase::SkipWhiteSpace( p ); p = XMLUtil::SkipWhiteSpace( p );
if ( !p ) return 0; if ( !p ) return 0;
const char* start = p; const char* start = p;
@ -520,7 +567,7 @@ char* XMLElement::ParseDeep( char* p )
++p; ++p;
} }
p = XMLBase::ParseName( p, &value ); p = value.ParseName( p );
if ( value.Empty() ) return 0; if ( value.Empty() ) return 0;
bool elementClosed=false; bool elementClosed=false;
@ -539,7 +586,7 @@ void XMLElement::Print( XMLStreamer* streamer )
// PrintSpace( cfile, depth ); // PrintSpace( cfile, depth );
//} //}
//fprintf( cfile, "<%s", Name() ); //fprintf( cfile, "<%s", Name() );
streamer->OpenElement( Name(), IsTextParent() ); streamer->OpenElement( Name() );
for( XMLAttribute* attrib=rootAttribute; attrib; attrib=attrib->next ) { for( XMLAttribute* attrib=rootAttribute; attrib; attrib=attrib->next ) {
//fprintf( cfile, " " ); //fprintf( cfile, " " );
@ -554,6 +601,21 @@ void XMLElement::Print( XMLStreamer* streamer )
} }
bool XMLElement::Accept( XMLVisitor* visitor ) const
{
if ( visitor->VisitEnter( *this, rootAttribute ) )
{
for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() )
{
if ( !node->Accept( visitor ) )
break;
}
}
return visitor->VisitExit( *this );
}
// --------- XMLDocument ----------- // // --------- XMLDocument ----------- //
XMLDocument::XMLDocument() : XMLDocument::XMLDocument() :
XMLNode( 0 ), XMLNode( 0 ),
@ -678,7 +740,7 @@ const char* StringStack::Pop() {
*/ */
XMLStreamer::XMLStreamer( FILE* file ) : fp( file ), depth( 0 ), elementJustOpened( false ) XMLStreamer::XMLStreamer( FILE* file ) : fp( file ), depth( 0 ), elementJustOpened( false ), textDepth( -1 )
{ {
for( int i=0; i<ENTITY_RANGE; ++i ) { for( int i=0; i<ENTITY_RANGE; ++i ) {
entityFlag[i] = false; entityFlag[i] = false;
@ -733,18 +795,18 @@ void XMLStreamer::PrintString( const char* p )
} }
} }
void XMLStreamer::OpenElement( const char* name, bool textParent ) void XMLStreamer::OpenElement( const char* name )
{ {
if ( elementJustOpened ) { if ( elementJustOpened ) {
SealElement(); SealElement();
} }
if ( !TextOnStack() ) { stack.Push( name );
if ( textDepth < 0 && depth > 0) {
fprintf( fp, "\n" );
PrintSpace( depth ); PrintSpace( depth );
} }
stack.Push( name );
text.Push( textParent ? 'T' : 'e' );
// fixme: can names have entities?
fprintf( fp, "<%s", name ); fprintf( fp, "<%s", name );
elementJustOpened = true; elementJustOpened = true;
++depth; ++depth;
@ -764,25 +826,22 @@ void XMLStreamer::CloseElement()
{ {
--depth; --depth;
const char* name = stack.Pop(); const char* name = stack.Pop();
bool wasText = TextOnStack();
text.Pop();
if ( elementJustOpened ) { if ( elementJustOpened ) {
fprintf( fp, "/>" ); fprintf( fp, "/>" );
if ( !wasText ) {
fprintf( fp, "\n" );
}
} }
else { else {
if ( !wasText ) { if ( textDepth < 0 ) {
fprintf( fp, "\n" );
PrintSpace( depth ); PrintSpace( depth );
} }
// fixme can names have entities?
fprintf( fp, "</%s>", name ); fprintf( fp, "</%s>", name );
if ( !TextOnStack() ) {
fprintf( fp, "\n" );
}
} }
if ( textDepth == depth )
textDepth = -1;
if ( depth == 0 )
fprintf( fp, "\n" );
elementJustOpened = false; elementJustOpened = false;
} }
@ -791,14 +850,13 @@ void XMLStreamer::SealElement()
{ {
elementJustOpened = false; elementJustOpened = false;
fprintf( fp, ">" ); fprintf( fp, ">" );
if ( !TextOnStack() ) {
fprintf( fp, "\n" );
}
} }
void XMLStreamer::PushText( const char* text ) void XMLStreamer::PushText( const char* text )
{ {
textDepth = depth-1;
if ( elementJustOpened ) { if ( elementJustOpened ) {
SealElement(); SealElement();
} }

View File

@ -12,7 +12,7 @@
- make constructors protected - make constructors protected
- hide copy constructor - hide copy constructor
- hide = operator - hide = operator
- UTF8 support: isAlpha, etc. X UTF8 support: isAlpha, etc.
*/ */
#include <limits.h> #include <limits.h>
@ -74,6 +74,9 @@ public:
bool Empty() const { return start == end; } bool Empty() const { return start == end; }
void SetInternedStr( const char* str ) { this->start = (char*) str; this->end = 0; this->flags = 0; } void SetInternedStr( const char* str ) { this->start = (char*) str; this->end = 0; this->flags = 0; }
char* ParseText( char* in, const char* endTag, int strFlags );
char* ParseName( char* in );
private: private:
enum { enum {
@ -278,16 +281,59 @@ private:
}; };
*/ */
class XMLBase
/**
Implements the interface to the "Visitor pattern" (see the Accept() method.)
If you call the Accept() method, it requires being passed a XMLVisitor
class to handle callbacks. For nodes that contain other nodes (Document, Element)
you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves
are simply called with Visit().
If you return 'true' from a Visit method, recursive parsing will continue. If you return
false, <b>no children of this node or its sibilings</b> will be Visited.
All flavors of Visit methods have a default implementation that returns 'true' (continue
visiting). You need to only override methods that are interesting to you.
Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting.
You should never change the document from a callback.
@sa XMLNode::Accept()
*/
class XMLVisitor
{ {
public: public:
virtual ~XMLVisitor() {}
/// Visit a document.
virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { return true; }
/// Visit a document.
virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; }
/// Visit an element.
virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) { return true; }
/// Visit an element.
virtual bool VisitExit( const XMLElement& /*element*/ ) { return true; }
/// Visit a declaration
//virtual bool Visit( const TiXmlDeclaration& /*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; }
};
class XMLUtil
{
public: public:
XMLBase() {} // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
virtual ~XMLBase() {} // correct, but simple, and usually works.
static const char* SkipWhiteSpace( const char* p ) { while( IsUTF8Continuation(*p) || isspace( *p ) ) { ++p; } return p; }
static const char* SkipWhiteSpace( const char* p ) { while( isspace( *p ) ) { ++p; } return p; } static char* SkipWhiteSpace( char* p ) { while( IsUTF8Continuation(*p) || isspace( *p ) ) { ++p; } return p; }
static char* SkipWhiteSpace( char* p ) { while( isspace( *p ) ) { ++p; } return p; }
inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) { inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
int n = 0; int n = 0;
@ -303,13 +349,8 @@ public:
return false; return false;
} }
inline static int IsUTF8Continuation( unsigned char p ) { return p & 0x80; } inline static int IsUTF8Continuation( unsigned char p ) { return p & 0x80; }
inline static int IsAlphaNum( unsigned char anyByte ) { return ( anyByte <= 127 ) ? isalnum( anyByte ) : 1; } inline static int IsAlphaNum( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalnum( anyByte ) : 1; }
inline static int IsAlpha( unsigned char anyByte ) { return ( anyByte <= 127 ) ? isalpha( anyByte ) : 1; } inline static int IsAlpha( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalpha( anyByte ) : 1; }
static char* ParseText( char* in, StrPair* pair, const char* endTag, int strFlags );
static char* ParseName( char* in, StrPair* pair );
private:
}; };
@ -318,25 +359,50 @@ class XMLNode
friend class XMLDocument; friend class XMLDocument;
friend class XMLElement; friend class XMLElement;
public: public:
//void* operator new( size_t size, MemPool* pool ); XMLDocument* GetDocument() { return document; }
//void operator delete( void* mem, MemPool* pool );
XMLNode* InsertEndChild( XMLNode* addThis ); virtual XMLElement* ToElement() { return 0; }
virtual void Print( XMLStreamer* streamer ); virtual XMLText* ToText() { return 0; }
virtual XMLComment* ToComment() { return 0; }
virtual XMLDocument* ToDocument() { return 0; }
const char* Value() const { return value.GetStr(); } const char* Value() const { return value.GetStr(); }
void SetValue( const char* val ) { value.SetInternedStr( val ); } void SetValue( const char* val ) { value.SetInternedStr( val ); }
virtual XMLElement* ToElement() { return 0; } const XMLNode* FirstChild() const { return firstChild; }
virtual XMLText* ToText() { return 0; } XMLNode* FirstChild() { return firstChild; }
virtual XMLComment* ToComment() { return 0; } const XMLElement* FirstChildElement( const char* value=0 ) const;
XMLElement* FirstChildElement( const char* value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value )); }
XMLNode* FirstChild() { return firstChild; } const XMLNode* LastChild() const { return lastChild; }
XMLElement* FirstChildElement( const char* value=0 ); XMLNode* LastChild() { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() ); }
const XMLElement* LastChildElement( const char* value=0 ) const;
XMLElement* LastChildElement( const char* value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) ); }
const XMLNode* PreviousSibling() const { return prev; }
XMLNode* PreviousSibling() { return prev; }
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 XMLNode* NextSibling() const { return next; }
XMLNode* NextSibling() { return next; }
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 ) ); }
XMLNode* InsertEndChild( XMLNode* addThis );
XMLNode* InsertFirstChild( XMLNode* addThis );
XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
void ClearChildren();
void DeleteChild( XMLNode* node );
virtual bool Accept( XMLVisitor* visitor ) const = 0;
virtual void Print( XMLStreamer* streamer );
// fixme: guarentee null terminator to avoid internal checks
virtual char* ParseDeep( char* ); virtual char* ParseDeep( char* );
void SetTextParent() { isTextParent = true; } void SetTextParent() { isTextParent = true; }
bool IsTextParent() const { return isTextParent; } bool IsTextParent() const { return isTextParent; }
virtual bool IsClosingElement() const { return false; } virtual bool IsClosingElement() const { return false; }
@ -345,8 +411,6 @@ protected:
XMLNode( XMLDocument* ); XMLNode( XMLDocument* );
virtual ~XMLNode(); virtual ~XMLNode();
void ClearChildren();
XMLDocument* document; XMLDocument* document;
XMLNode* parent; XMLNode* parent;
bool isTextParent; bool isTextParent;
@ -373,6 +437,7 @@ public:
const char* Value() { return value.GetStr(); } const char* Value() { return value.GetStr(); }
void SetValue( const char* ); void SetValue( const char* );
virtual bool Accept( XMLVisitor* visitor ) const;
virtual XMLText* ToText() { return this; } virtual XMLText* ToText() { return this; }
char* ParseDeep( char* ); char* ParseDeep( char* );
@ -394,6 +459,7 @@ public:
virtual XMLComment* ToComment() { return this; } virtual XMLComment* ToComment() { return this; }
const char* Value() { return value.GetStr(); } const char* Value() { return value.GetStr(); }
virtual bool Accept( XMLVisitor* visitor ) const;
char* ParseDeep( char* ); char* ParseDeep( char* );
@ -405,7 +471,7 @@ private:
}; };
class XMLAttribute : public XMLBase class XMLAttribute
{ {
friend class XMLElement; friend class XMLElement;
public: public:
@ -434,6 +500,7 @@ public:
virtual void Print( XMLStreamer* ); virtual void Print( XMLStreamer* );
virtual XMLElement* ToElement() { return this; } virtual XMLElement* ToElement() { return this; }
virtual bool Accept( XMLVisitor* visitor ) const;
// internal: // internal:
virtual bool IsClosingElement() const { return closing; } virtual bool IsClosingElement() const { return closing; }
@ -459,11 +526,14 @@ public:
XMLDocument(); XMLDocument();
~XMLDocument(); ~XMLDocument();
virtual XMLDocument* ToDocument() { return this; }
int Parse( const char* ); int Parse( const char* );
int Load( const char* ); int Load( const char* );
int Load( FILE* ); int Load( FILE* );
void Print( XMLStreamer* streamer=0 ); void Print( XMLStreamer* streamer=0 );
virtual bool Accept( XMLVisitor* visitor ) const;
XMLElement* NewElement( const char* name ); XMLElement* NewElement( const char* name );
@ -500,13 +570,13 @@ private:
}; };
class XMLStreamer class XMLStreamer
{ {
public: public:
XMLStreamer( FILE* file ); XMLStreamer( FILE* file );
~XMLStreamer() {} ~XMLStreamer() {}
void OpenElement( const char* name, bool textParent ); void OpenElement( const char* name );
void PushAttribute( const char* name, const char* value ); void PushAttribute( const char* name, const char* value );
void CloseElement(); void CloseElement();
@ -517,24 +587,26 @@ private:
void SealElement(); void SealElement();
void PrintSpace( int depth ); void PrintSpace( int depth );
void PrintString( const char* ); // prints out, after detecting entities. void PrintString( const char* ); // prints out, after detecting entities.
bool TextOnStack() const { /* bool TextOnStack() const {
for( int i=0; i<text.Size(); ++i ) { for( int i=0; i<text.Size(); ++i ) {
if ( text[i] == 'T' ) if ( text[i] == 'T' )
return true; return true;
} }
return false; return false;
} }*/
FILE* fp; FILE* fp;
int depth; int depth;
bool elementJustOpened; bool elementJustOpened;
int textDepth;
enum { enum {
ENTITY_RANGE = 64 ENTITY_RANGE = 64
}; };
bool entityFlag[ENTITY_RANGE]; bool entityFlag[ENTITY_RANGE];
DynArray< const char*, 10 > stack; DynArray< const char*, 10 > stack;
DynArray< char, 10 > text; //DynArray< char, 10 > text;
}; };

View File

@ -52,6 +52,7 @@ int main( int argc, const char* argv )
printf( "----------------------------------------------\n" ); printf( "----------------------------------------------\n" );
} }
} }
#if 0
{ {
static const char* test = "<element>Text before.</element>"; static const char* test = "<element>Text before.</element>";
XMLDocument doc; XMLDocument doc;
@ -67,5 +68,6 @@ int main( int argc, const char* argv )
doc->Parse( test ); doc->Parse( test );
delete doc; delete doc;
} }
#endif
return 0; return 0;
} }