📄 xmlparser.cpp
字号:
// ---------------------------------------------------------------------------------------------------------------------
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 + -