⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xmlparser.cpp

📁 简单的xml解析类
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	// ---------------------------------------------------------------------------------------------------------------------

	bool XmlParser::readGeneral( Tokenizer& tokenizer )
	{
		String token;
		Tokenizer::token_type_e type;
		if( tokenizer.getNextToken(token, type) == false ) {
			return (true);
		}

		if( type == Tokenizer::TOKEN_BRACKET_L ) {
			tokenizer.getNextToken(token, type);

			switch(type)
			{
			case Tokenizer::TOKEN_ALPHANUMERIC:
				readElement(tokenizer, token);
				break;

			case Tokenizer::TOKEN_SLASH:
				readElement(tokenizer, token);
				if( m_elemIdx < 0 ) {
					return (false); // encountered last element, stop parsing xml document
				}
				break;

			case Tokenizer::TOKEN_EXCLAMATION:
				readExclamation(tokenizer);
				break;

			case Tokenizer::TOKEN_QUESTION:
				readProcInst(tokenizer);
				break;

			default:
				throw XmlSyntaxException("Unexpected token encountered: '" + token + "'");
			}

			tokenizer.readUntil("<", false, false);
		}
		else {
			switch(type)
			{
			case Tokenizer::TOKEN_ALPHANUMERIC:
			case Tokenizer::TOKEN_SLASH:
			case Tokenizer::TOKEN_EQUALS:
			case Tokenizer::TOKEN_QUESTION:
			case Tokenizer::TOKEN_EXCLAMATION:
			case Tokenizer::TOKEN_BRACKET_R:
				// todo: check for retain-whitespace flag
				xmlElementText( decodeText(token.trim()) );
				break;

			case Tokenizer::TOKEN_WHITESPACE:
				break;
			default:
				throw XmlSyntaxException("Invalid token encountered in XML document: '" + token + "'");
			}
		}

		return (true);
	}

	// ---------------------------------------------------------------------------------------------------------------------

	void XmlParser::readElement( Tokenizer& tokenizer, String elementToken )
	{
		Tokenizer::token_type_e elementType = tokenizer.getTokenType(elementToken);

		if( elementType == Tokenizer::TOKEN_ALPHANUMERIC ) {
			tokenizer.readUntil(">", false, false);

			String token;
			Tokenizer::token_type_e type;
			tokenizer.getNextToken(token, type);

			bool emptyElement;
			if( (emptyElement = token.endsWith("/")) == true ) {
				token = token.stripFromRight(1);
			}

			elementPush(elementToken);

			if( token.trim().getLength() > 0 ) {
				Array<String> attributes = parseAttributes(token);
				if( attributes.getSize() > 0 ) {
					if( attributes.getSize() % 2 != 0 ) {
						throw XmlSyntaxException("Invalid attribute list in element: '" + token + "'");
					}

					for( int iA = 0; iA < attributes.getSize(); iA += 2 ) {
						String att = attributes[iA + 0];
						String val = attributes[iA + 1];

						xmlElementAttribute(att, val);
					}
				}
			}

			if( emptyElement ) {
				elementPop();
			}

			// remove ">" from input stream
			tokenizer.getNextToken(token, type);
		}
		else if( elementType == Tokenizer::TOKEN_SLASH ) {
			tokenizer.readUntil(">", false, false);

			String token;
			Tokenizer::token_type_e type;
			tokenizer.getNextToken(token, type);

			if( m_elemIdx < 0 ) {
				throw XmlSyntaxException("End tag '" + token + "' encountered before an open tag");
			}
			if( token != m_elemNames[m_elemIdx] ) {
				throw XmlSyntaxException("End tag '" + token + "' does not match open tag '" + m_elemNames[m_elemIdx] + "'");
			}

			elementPop();

			// remove ">" from input stream
			tokenizer.getNextToken(token, type);
		}
	}

	// ---------------------------------------------------------------------------------------------------------------------

	void XmlParser::readExclamation( Tokenizer& tokenizer )
	{
		String token;
		Tokenizer::token_type_e type;

		tokenizer.getNextToken(token, type);

		if( token.beginsWith("--") ) {
			tokenizer.readUntil("--", false);
			String remain;
			tokenizer.getNextToken(remain, type);
			
			String comment = token.subString(2) + remain.stripFromRight(2);

			tokenizer.getNextToken(token, type);
			if( type != Tokenizer::TOKEN_BRACKET_R ) {
				throw XmlSyntaxException($("Expected end of comment"));
			}
			
			xmlComment(comment.trim());		
		}
		else if( token.beginsWith("[CDATA[") ) {
			tokenizer.readUntil("]]>", false);
			String remain;
			tokenizer.getNextToken(remain, type);
			
			String cdata = token.subString(7) + remain.stripFromRight(3);
			xmlElementCData(cdata);
		}
		else if( token.beginsWith("[") ) {
			// conditional
			tokenizer.readUntil("]]>", false);
			tokenizer.getNextToken(token, type);
		}
		else if( token.beginsWith("DOCTYPE") ) {
			if( m_elemIdx >= 0 || m_elemNames[0] != String::null ) {
				throw XmlSyntaxException($("DOCTYPE cannot be declared outside of a prolog"));
			}

			// This code is temporary until doctypes can be properly supported

			tokenizer.readUntil(">", true);
			tokenizer.getNextToken(token, type);

			int brackPos = token.findPos("[");
			if( brackPos != String::npos ) {
				if( !token.endsWith("]>") ) {
					String search = token.left(brackPos);
					char quotes = 0;
					for( int i = 0; i < search.getLength(); ++i ) {
						if( quotes != 0 ) {
							if( search[i] == quotes ) {
								quotes = 0;
							}
						}
						else if( search[i] == '\"' || search[i] == '\'' ) {
							quotes = search[i];
						}
					}
					if( quotes == 0 ) {
						throw XmlException($("Imbedded DOCTYPE declarations are not supported"));
					}
				}
			}
		}
		else {
			// unsupport type
			tokenizer.readUntil(">", true);
			tokenizer.getNextToken(token, type);
		}	
	}

	// ---------------------------------------------------------------------------------------------------------------------

	void XmlParser::readProcInst( Tokenizer& tokenizer )
	{
		String instruction, token;
		Tokenizer::token_type_e type;

		tokenizer.getNextToken(instruction, type);

		xmlProcInstBegin(instruction);

		tokenizer.readUntil(">", false, false);
		tokenizer.getNextToken(token, type);

		if( token.trim().getLength() > 0 ) {
			Array<String> attributes = parseAttributes(token);
			if( attributes.getSize() > 0 ) {
				if( attributes.getSize() % 2 != 0 ) {
					throw XmlSyntaxException("Invalid attribute list in processing instruction: '" + token + "'");
				}

				processInstruction(instruction, attributes);

				for( int iA = 0; iA < attributes.getSize(); iA += 2 ) {
					String att = attributes[iA + 0];
					String val = attributes[iA + 1];

					xmlProcInstAttribute(att, val);
				}
			}
		}

		xmlProcInstEnd(instruction);

		// remove ">" from input stream
		tokenizer.getNextToken(token, type);
	}

	// ---------------------------------------------------------------------------------------------------------------------

	Array<String> XmlParser::parseAttributes( String list )
	{
		Array<String> result;

		while(true) {
			int posEq = list.findPos("=");
			if( posEq == String::npos ) {
				break;
			}

			String att = list.left(posEq).trim();

			list = list.stripFromLeft(posEq + 1).trim();
			String quo = list.left(1);

			if( quo != "\"" && quo != "\'" ) {
				throw XmlSyntaxException($("Error parsing attributes, expecting opening quotes"));
			}

			int posQuo = list.findPos(quo, 1);
			if( posQuo == String::npos ) {
				throw XmlSyntaxException($("Error parsing attributes, expecting ending quotes"));
			}

			String val = decodeText( list.left(posQuo).stripFromLeft(1) );
			list = list.stripFromLeft(posQuo + 1);

			result.append(att);
			result.append(val);
		}

		return (result);
	}

	// ---------------------------------------------------------------------------------------------------------------------

	void XmlParser::processInstruction( String instruction, Array<String> attributes )
	{
		if( instruction.equalsIgnoreCase("xml") ) {
			for( int iA = 0; iA < attributes.getSize(); iA += 2 ) {
				String att = attributes[iA + 0];
				String val = attributes[iA + 1];
				if( att == "version" ) {
					if( val.trim() != "1.0" ) {
						throw XmlException("Unsupported XML version specified: " + val);
					}
				}
				if( att == "encoding" ) {
					if( val.trim().equalsIgnoreCase("utf-8") != true && val.trim().equalsIgnoreCase("iso-8859-1") != true ) {
						throw XmlException("Unsupported XML encoding specified: " + val);
					}
				}
			}
		}
	}

	// ---------------------------------------------------------------------------------------------------------------------

	void XmlParser::elementPush( String& name )
	{
		if( m_elemIdx == m_elemNames.getSize() - 1 ) {
			m_elemNames.resize( m_elemNames.getSize() * 2 );
		}

		++m_elemIdx;
		m_elemNames[m_elemIdx] = name;

		xmlElementBegin(name);
	}

	// ---------------------------------------------------------------------------------------------------------------------

	void XmlParser::elementPop()
	{
		xmlElementEnd(m_elemNames[m_elemIdx]);

		m_elemNames[m_elemIdx];
		--m_elemIdx;
	}


}}}	// namespaces

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -