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

📄 parser.cpp

📁 symbian 下的解析xml文件的源代码 个人感觉这个比较简单
💻 CPP
📖 第 1 页 / 共 2 页
字号:

                ProcessElementL(lex);

                // consume '>' and start parsing free text
                lex.Inc();
                iCoreState = ECoreParsingFreeText;
                lex.Mark();

                continue;
            case KLeftBracket:
                // consume the '['
                lex.Inc();

                // compare the tag parsed so far to the CDATA start string
                start_offs = lex.MarkedOffset() + 1;
                ptr.Set(iDocument.Mid(start_offs, lex.Offset() - start_offs));

                if( ptr.Compare(KCDataSectionStart) == 0 ) {
                    // yes, the element is a CDATA section
                    ProcessCDATASectionL(lex);                    
                }
                continue;
            case KDash:
                // comsume the '-'
                lex.Inc();

                // see if this is a comment
                start_offs = lex.MarkedOffset() + 1;
                ptr.Set(iDocument.Mid(start_offs, lex.Offset() - start_offs));

                if( ptr.Compare(KCommentSectionStart) == 0 ) 
                    {
                    // yes, the element is a comment section
                    ProcessCommentSectionL(lex);                    
                    }
                continue;
            case KDoubleQuote:
                in_string = !in_string;
                break;
            case KNewline:
                // increment line number and let control enter default branch
                iLineNum++;
            default:
                break;
        }

        // consume the character
        lex.Inc();
    }
}

void CEAXPParser::ProcessCommentSectionL( TLex& aLex )
    {
    TInt start_offs = aLex.MarkedOffset() + 1 + KCommentSectionStart().Length();
    TPtrC comment;

    // find the closing "-->"
    while ( !aLex.Eos() )
        {
        if ( aLex.Peek() == KGreaterThan )
            {
            if( iDocument.Mid(aLex.Offset() - 2, 2).Compare(KCommentSectionEnd) == 0 ) 
                {
                comment.Set( iDocument.Mid( start_offs, 
                                            aLex.Offset() - 2 - start_offs) );

                iListener.Comment( comment );

                // consume the '>' and return
                aLex.Inc();
                aLex.Mark();
                iCoreState = ECoreParsingFreeText;
                return;
            }
        }

        // consume the character
        aLex.Inc();
        }
    }

void CEAXPParser::ProcessCDATASectionL(TLex &aLex)
{
    TInt start_offs = aLex.MarkedOffset() + 1 + KCDataSectionStart().Length();
    TPtrC sect;

    while( !aLex.Eos() ) {
        if( aLex.Peek() == KGreaterThan ) {
            if( iDocument.Mid(aLex.Offset() - 2, 2).Compare(KCDataSectionEnd) == 0 ) {
                // found the end of the CDATA section
                sect.Set(iDocument.Mid(start_offs, 
                                       aLex.Offset() - 2 - start_offs));
                //RDebug::Print(_L("CDATA: %S"), &sect);

                iListener.FreeText(sect);

                // consume the '>' and return
                aLex.Inc();
                aLex.Mark();
                iCoreState = ECoreParsingFreeText;
                return;
            }
        }

        // consume the character
        aLex.Inc();
    }   
}

void CEAXPParser::IllegalCharacterMetL(TChar aChar)
{
    _LIT(KIllegalChar, "Illegal character '%c' (%d) on line %d!");

    iErrorReason.Format(KIllegalChar, (TInt)aChar, (TInt)aChar, iLineNum);
    User::Leave(KErrParsingError);
}

void CEAXPParser::ProcessElementL(const TLex &aLex)
{
    TPtrC name, ns;

    TInt start_offs = aLex.MarkedOffset() + 1;
    TInt end_offs = aLex.Offset();

    // extract the element tag
    TPtrC element = iDocument.Mid(start_offs, (end_offs - start_offs));

    RAttributeList attr_list;

    // parse the element name/namespace
    TInt name_end_offs = 0;
    TPtrC elem_name_buf = FindElementNameL(element, name_end_offs);

    //##TODO## assert that name != "/" (case: </ a>)

    // if the element name starts with '?', then discard it 
    if( elem_name_buf[0] == KQuestionMark ) {
        return;
    }

    if( elem_name_buf[0] == KSlash ) {
        // this is the end element (</element>)
        elem_name_buf.Set(elem_name_buf.Right(elem_name_buf.Length() - 1));

        ParseNameL(elem_name_buf, name, ns);
        iListener.EndElement(name, ns);
    } else {
        // check if the name already contains the end element -marker '/'
        TBool end_element = EFalse;
        if( elem_name_buf[elem_name_buf.Length() - 1] == KSlash ) {
            elem_name_buf.Set(elem_name_buf.Left(elem_name_buf.Length() - 1));
            end_element = ETrue;
        }

        // this is the start element (<element ...>)
        ParseNameL(elem_name_buf, name, ns);

        // locate && parse the attribute list
        if( element.Length() > name_end_offs ) {
            ParseAttributeListL(element.Right(element.Length() - name_end_offs), attr_list,
                                end_element);
        }

        iListener.StartElement(name, ns, attr_list);

        // deallocate attribute list
        attr_list.ResetAndDestroy();

        if( end_element ) {
            // the element closes immediately, too (<element .... />)
            iListener.EndElement(name, ns);
        }
    }
}

TPtrC CEAXPParser::FindElementNameL(const TPtrC &aElement, TInt &aEndOffset)
{
    TLex lex(aElement);
    TInt end_offs;

    // make sure there is a tag name in the first place
    if( lex.Peek() == KWhitespace ) {
        _LIT(KNameNotFound, "Name not found in element %S on line %d!");
        iErrorReason.Format(KNameNotFound, &aElement, iLineNum);
        User::Leave(KErrParsingError);
    }

    // by default, assume the tag name extends to the end of element
    end_offs = aElement.Length();

    // find the extends of the element name
    while( !lex.Eos() ) {
        TChar peek = lex.Peek();
        switch( peek ) {
            case KWhitespace:
            case KNewline:
            case KCarriageReturn:
                // found the end of the element name
                end_offs = lex.Offset();

                // set lex to null string to stop parsing
                lex.Assign(KNullDesC);
                break;
            case KEquals:
            case KLessThan:
            case KGreaterThan:
                // illegal character met!
                IllegalCharacterMetL(peek);
                break;
            default:
                // ok character - skip to the next whitespace or end of string
                lex.SkipCharacters();
                continue;
        }

        // consume the character
        lex.Inc();
    }

    aEndOffset = end_offs;

    return aElement.Left(end_offs);
}

void CEAXPParser::ParseNameL(const TPtrC &aNameBuf, TPtrC &aName, TPtrC &aNamespace)
{
    TInt sep_offs = aNameBuf.Locate(KColon);
    if( sep_offs == KErrNotFound ) {
        // namespace not defined (form: <name>)
        aNamespace.Set(KNullDesC);
        aName.Set(aNameBuf);
    } else {
        // namespace defined (form: <ns:name>) - validate both, name and namespace
        if( (sep_offs == 0) || (sep_offs == (aNameBuf.Length() - 1)) ) {
            _LIT(KBadElementName, "Bad element name '%S' on line %d!");
            iErrorReason.Format(KBadElementName, &aNameBuf, iLineNum);
            User::Leave(KErrParsingError);
        }

        aNamespace.Set(aNameBuf.Left(sep_offs));
        aName.Set(aNameBuf.Right(aNameBuf.Length() - sep_offs - 1));
    }
}

void CEAXPParser::ParseAttributeListL(const TPtrC &aAttrBuf, RAttributeList &aAttrList,
                                      TBool &aEndElement)
{
    _LIT(KBadSyntax, "Bad syntax on line %d!");

    aEndElement = EFalse;
    TLex lex(aAttrBuf);
    TAttrParserState state = EAttrNullState;
    TPtrC ptr;
    TPtrC name, ns;

    while( !lex.Eos() ) {
        TChar peek = lex.Peek();
        //RDebug::Print(_L("PEEK: %c"), (TInt)peek);

        switch( peek ) {
            case KTab:
            case KWhitespace:
            case KCarriageReturn:
            case KNewline:
                if( state == EAttrParsingAttrName ) {
                    IllegalCharacterMetL(peek);
                    return;
                } else if( state != EAttrParsingAttrValue ) {
                    lex.SkipSpace(); 
                    state = EAttrNullState;
                } else {
                    lex.Inc();
                }
                continue;
            case KEquals:
                // check state
                if( (state == EAttrNullState) ) {
                    IllegalCharacterMetL(peek);
                    return;
                }

                if( state == EAttrParsingAttrValue ) {
                    lex.Inc();
                    break;
                    }

                // end parsing attribute name
                ptr.Set(aAttrBuf.Mid(lex.MarkedOffset(), 
                                     lex.Offset() - lex.MarkedOffset()));
                ValidateSizeAndCopyL(&iAttrName, ptr);

                // consume and peek for '"'
                lex.Inc();
                if( lex.Peek() != KDoubleQuote ) {
                    IllegalCharacterMetL(lex.Peek());
                    return;
                } else {
                    // consume '"'
                    lex.Inc();
                    lex.Mark();
                    state = EAttrParsingAttrValue;
                }
                break;
            case KDoubleQuote:
                // check state
                if( (state == EAttrNullState) || (state == EAttrParsingAttrName) ) {
                    IllegalCharacterMetL(peek);
                    return;
                }

                // end parsing attr value - add new entry
                ptr.Set(aAttrBuf.Mid(lex.MarkedOffset(), 
                                     lex.Offset() - lex.MarkedOffset()));
                UnescapeL(ptr);
                ParseNameL(*iAttrName, name, ns);
                aAttrList.Append(CAttribute::NewL(name, ns, *iUnescapeBuffer));
                lex.Inc();
                state = EAttrNullState;
                break;
            case KSlash:
                if( state == EAttrNullState ) {
                    // end element -marker met
                    aEndElement = ETrue;
                    return;
                }
                // otherwise allow control proceed to default branch
            default:
                if( state == EAttrNullState ) {
                    // start parsing attribute name
                    state = EAttrParsingAttrName;
                    lex.Mark();
                }

                // consume character
                lex.Inc();
                break;
        }
    }
}

⌨️ 快捷键说明

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