📄 tinyxmlparser.c
字号:
// Do we have text? if( in->good() && in->peek() != '<' ) { // Yep, text. TiXmlText text( "" ); text.StreamIn( in, tag ); // What follows text is a closing tag or another node. // Go around again and figure it out. continue; } // We now have either a closing tag...or another node. // We should be at a "<", regardless. if( !in->good() ) return; assert( in->peek() == '<' ); int tagIndex = tag->length(); bool closingTag = false; bool firstCharFound = false; for( ;; ) { if( !in->good() ) return; int c = in->peek(); if( c == '>' ) break; *tag += c; in->get(); if( !firstCharFound && c != '<' && !IsWhiteSpace( c ) ) { firstCharFound = true; if( c == '/' ) closingTag = true; } } // If it was a closing tag, then read in the closing '>' to clean up the input stream. // If it was not, the streaming will be done by the tag. if( closingTag ) { int c = in->get(); assert( c == '>' ); *tag += c; // We are done, once we've found our closing tag. return; } else { // If not a closing tag, id it, and stream. const char* tagloc = tag->c_str() + tagIndex; TiXmlNode* node = Identify( tagloc ); if( !node ) return; node->StreamIn( in, tag ); delete node; node = 0; // No return: go around from the beginning: text, closing tag, or node. } } }}#endifconst char* TiXmlElement::Parse( const char* p ) { p = SkipWhiteSpace( p ); TiXmlDocument* document = GetDocument(); if( !p || !*p || *p != '<' ) { if( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT ); return(const char*)false; } p = SkipWhiteSpace( p+1 ); // Read the name. p = ReadName( p, &value ); if( !p || !*p ) { if( document ) document->SetError( TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME ); return(const char*)false; } TIXML_STRING endTag ("</"); endTag += value; endTag += ">"; // Check for and read attributes. Also look for an empty // tag or an end tag. while( p && *p ) { p = SkipWhiteSpace( p ); if( !p || !*p ) { if( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES ); return 0; } if( *p == '/' ) { ++p; // Empty tag. if( *p != '>' ) { if( document ) document->SetError( TIXML_ERROR_PARSING_EMPTY ); return 0; } return(p+1); } else if( *p == '>' ) { // Done with attributes (if there were any.) // Read the value -- which can include other // elements -- read the end tag, and return. ++p; p = ReadValue( p ); // Note this is an Element method, and will set the error if one happens. if( !p || !*p ) return 0; // We should find the end tag now if( StringEqual( p, endTag.c_str(), false ) ) { p += endTag.length(); return p; } else { if( document ) document->SetError( TIXML_ERROR_READING_END_TAG ); return 0; } } else { // Try to read an element: TiXmlAttribute attrib; attrib.SetDocument( document ); p = attrib.Parse( p ); if( !p || !*p ) { if( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT ); return 0; } SetAttribute( attrib.Name(), attrib.Value() ); } } return p;}const char* TiXmlElement::ReadValue( const char* p ) { TiXmlDocument* document = GetDocument(); // Read in text and elements in any order. p = SkipWhiteSpace( p ); while( p && *p ) { if( *p != '<' ) { // Take what we have, make a text element. TiXmlText* textNode = new TiXmlText( "" ); if( !textNode ) { if( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY ); return 0; } p = textNode->Parse( p ); if( !textNode->Blank() ) LinkEndChild( textNode ); else delete textNode; } else { // We hit a '<' // Have we hit a new element or an end tag? if( StringEqual( p, "</", false ) ) { return p; } else { TiXmlNode* node = Identify( p ); if( node ) { p = node->Parse( p ); LinkEndChild( node ); } else { return 0; } } } p = SkipWhiteSpace( p ); } if( !p ) { if( document ) document->SetError( TIXML_ERROR_READING_ELEMENT_VALUE ); } return p;}#ifdef TIXML_USE_STLvoid TiXmlUnknown::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag ) { while( in->good() ) { int c = in->get(); (*tag) += c; if( c == '>' ) { // All is well. return; } }}#endifconst char* TiXmlUnknown::Parse( const char* p ) { TiXmlDocument* document = GetDocument(); p = SkipWhiteSpace( p ); if( !p || !*p || *p != '<' ) { if( document ) document->SetError( TIXML_ERROR_PARSING_UNKNOWN ); return 0; } ++p; value = ""; while( p && *p && *p != '>' ) { value += *p; ++p; } if( !p ) { if( document ) document->SetError( TIXML_ERROR_PARSING_UNKNOWN ); } if( *p == '>' ) return p+1; return p;}#ifdef TIXML_USE_STLvoid TiXmlComment::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag ) { while( in->good() ) { int c = in->get(); (*tag) += c; if( c == '>' && tag->at( tag->length() - 2 ) == '-' && tag->at( tag->length() - 3 ) == '-' ) { // All is well. return; } }}#endifconst char* TiXmlComment::Parse( const char* p ) { TiXmlDocument* document = GetDocument(); value = ""; p = SkipWhiteSpace( p ); const char* startTag = "<!--"; const char* endTag = "-->"; if( !StringEqual( p, startTag, false ) ) { document->SetError( TIXML_ERROR_PARSING_COMMENT ); return 0; } p += strlen( startTag ); p = ReadText( p, &value, false, endTag, false ); return p;}const char* TiXmlAttribute::Parse( const char* p ) { p = SkipWhiteSpace( p ); if( !p || !*p ) return 0; // Read the name, the '=' and the value. p = ReadName( p, &name ); if( !p || !*p ) { if( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES ); return 0; } p = SkipWhiteSpace( p ); if( !p || !*p || *p != '=' ) { if( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES ); return 0; } ++p; // skip '=' p = SkipWhiteSpace( p ); if( !p || !*p ) { if( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES ); return 0; } const char* end; if( *p == '\'' ) { ++p; end = "\'"; p = ReadText( p, &value, false, end, false ); } else if( *p == '"' ) { ++p; end = "\""; p = ReadText( p, &value, false, end, false ); } else { // All attribute values should be in single or double quotes. // But this is such a common error that the parser will try // its best, even without them. value = ""; while( p && *p // existence && !isspace( *p ) && *p != '\n' && *p != '\r' // whitespace && *p != '/' && *p != '>' ) { // tag end value += *p; ++p; } } return p;}#ifdef TIXML_USE_STLvoid TiXmlText::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag ) { while( in->good() ) { int c = in->peek(); if( c == '<' ) return; (*tag) += c; in->get(); }}#endifconst char* TiXmlText::Parse( const char* p ) { value = ""; //TiXmlDocument* doc = GetDocument(); bool ignoreWhite = true;// if ( doc && !doc->IgnoreWhiteSpace() ) ignoreWhite = false; const char* end = "<"; p = ReadText( p, &value, ignoreWhite, end, false ); if( p ) return p-1; // don't truncate the '<' return 0;}#ifdef TIXML_USE_STLvoid TiXmlDeclaration::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag ) { while( in->good() ) { int c = in->get(); (*tag) += c; if( c == '>' ) { // All is well. return; } }}#endifconst char* TiXmlDeclaration::Parse( const char* p ) { p = SkipWhiteSpace( p ); // Find the beginning, find the end, and look for // the stuff in-between. TiXmlDocument* document = GetDocument(); if( !p || !*p || !StringEqual( p, "<?xml", true ) ) { if( document ) document->SetError( TIXML_ERROR_PARSING_DECLARATION ); return 0; } p += 5;// const char* start = p+5;// const char* end = strstr( start, "?>" ); version = ""; encoding = ""; standalone = ""; while( p && *p ) { if( *p == '>' ) { ++p; return p; } p = SkipWhiteSpace( p ); if( StringEqual( p, "version", true ) ) {// p += 7; TiXmlAttribute attrib; p = attrib.Parse( p ); version = attrib.Value(); } else if( StringEqual( p, "encoding", true ) ) {// p += 8; TiXmlAttribute attrib; p = attrib.Parse( p ); encoding = attrib.Value(); } else if( StringEqual( p, "standalone", true ) ) {// p += 10; TiXmlAttribute attrib; p = attrib.Parse( p ); standalone = attrib.Value(); } else { // Read over whatever it is. while( p && *p && *p != '>' && !isspace( *p ) ) ++p; } } return 0;}bool TiXmlText::Blank() const { for( unsigned i=0; i<value.length(); i++ ) if( !isspace( value[i] ) ) return false; return true;}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -