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

📄 parser.cpp

📁 symbian 下的解析xml文件的源代码 个人感觉这个比较简单
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
 * $Id: Parser.cpp,v 1.12 2006/10/20 11:36:39 matti Exp $
 *
 * EAXP - Lightweight XML SAX parser for Symbian Environments
 * Copyright (C) 2004-2006 Matti Dahlbom
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Contact: Matti Dahlbom <matti at 777-team.org>
 */

#include "eaxp.h"

/////////////////////////////////////////////////
// global util functions
/////////////////////////////////////////////////

void XMLStringTrim(TPtr aPtr)
{
    TInt len = aPtr.Length();

    for( TInt i = 0; i < len; i++ ) {
        if( (aPtr[i] == KNewline) || (aPtr[i] == KCarriageReturn) ) {
            aPtr[i] = KWhitespace;
        }
    }
    aPtr.TrimAll();
}

/////////////////////////////////////////////////
// class CAttribute
/////////////////////////////////////////////////

CAttribute* CAttribute::NewL(const TDesC &aName, 
                             const TDesC &aNamespace, 
                             const TDesC &aValue)
{
    CAttribute *attr = new (ELeave) CAttribute();
    CleanupStack::PushL(attr);
    attr->ConstructL(aName, aNamespace, aValue);
    CleanupStack::Pop(); // attr

    return attr;
}

CAttribute::CAttribute()
{
}

CAttribute::~CAttribute()
{
    delete iName;
    delete iNamespace;
    delete iValue;
}

void CAttribute::ConstructL(const TDesC &aName, 
                            const TDesC &aNamespace, 
                            const TDesC &aValue)
{
    iName = aName.AllocL();
    iNamespace = aNamespace.AllocL();
    iValue = aValue.AllocL();

    ::XMLStringTrim(iValue->Des());
}

EXPORT_C const TDesC& CAttribute::GetName() const
{
    return *iName;
}

EXPORT_C const TDesC& CAttribute::GetNamespace() const
{
    return *iNamespace;
}

EXPORT_C const TDesC& CAttribute::GetValue() const
{
    return *iValue;
}

/////////////////////////////////////////////////
// class CEAXPParser
/////////////////////////////////////////////////

EXPORT_C CEAXPParser* CEAXPParser::NewLC(MSAXEventListener &aListener)
{
    CEAXPParser *parser = new (ELeave) CEAXPParser(aListener);
    CleanupStack::PushL(parser);
    parser->ConstructL();

    return parser;
}

EXPORT_C CEAXPParser* CEAXPParser::NewL(MSAXEventListener &aListener)
{
    CEAXPParser *parser = CEAXPParser::NewLC(aListener);
    CleanupStack::Pop(); // parser

    return parser;
}

CEAXPParser::CEAXPParser(MSAXEventListener &aListener)
    : iListener(aListener),
      iCoreState(ECoreNullState)
{
}

CEAXPParser::~CEAXPParser()
{
    // dealloc buffers
    delete iAttrName;
    delete iAttrValue;
    delete iFreeText;
    delete iUnescapeBuffer;
    delete[] iEscapedCharMap;
}

void CEAXPParser::ConstructL()
{
    // construct default size buffers
    AllocateDefaultSizeBuffersL();

    // construct the escaped character mapping tables
    iNumEscapeMappings = 0;
    iEscapeMapCapacity = 10;
    iEscapedCharMap = new (ELeave) TEscapedCharMapping[iEscapeMapCapacity];
    AddEscapeMappingL(_L("amp"), '&');
    AddEscapeMappingL(_L("lt"), '<');
    AddEscapeMappingL(_L("gt"), '>');
    AddEscapeMappingL(_L("quot"), '\"');
    AddEscapeMappingL(_L("apos"), '\'');
}

void CEAXPParser::AllocateDefaultSizeBuffersL()
{
    delete iAttrName;
    iAttrName = NULL;
    iAttrName = HBufC::NewL(32);
    delete iAttrValue;
    iAttrValue = NULL;
    iAttrValue = HBufC::NewL(32);
    delete iFreeText;
    iFreeText = NULL;
    iFreeText = HBufC::NewL(128);
    delete iUnescapeBuffer;
    iUnescapeBuffer = NULL;
    iUnescapeBuffer = HBufC::NewL(128);
}

void CEAXPParser::AddEscapeMappingL(const TDesC &aEscape, TChar aChar)
{
    if( iNumEscapeMappings == iEscapeMapCapacity ) {
        iEscapeMapCapacity *= 2;
        delete[] iEscapedCharMap;
        iEscapedCharMap = NULL;
        iEscapedCharMap = new (ELeave) TEscapedCharMapping[iEscapeMapCapacity];
    }

    TEscapedCharMapping *mapping = iEscapedCharMap + iNumEscapeMappings; 
    iNumEscapeMappings++;
    mapping->iEscape.Copy(aEscape);
    mapping->iChar = aChar;
}

void CEAXPParser::ValidateSizeAndCopyL(HBufC **aTo, const TDesC &aFrom)
{
    // check if need to realloc
    if( (*aTo)->Des().MaxLength() < aFrom.Length() ) {
        delete *aTo;
        *aTo = NULL;
        *aTo = aFrom.AllocL();
    } else {
        // buffer large enough; just copy
        (*aTo)->Des().Copy(aFrom);
    }
}

void CEAXPParser::ValidateSizeL(HBufC **aBuf, TInt aSize)
{
    if( (*aBuf)->Des().MaxLength() < aSize ) {
        delete *aBuf;
        *aBuf = NULL;
        *aBuf = HBufC::NewL(aSize);
    }
}

TChar CEAXPParser::FindEscapeL(const TPtrC &aEscape)
{
    register TEscapedCharMapping *mapping = iEscapedCharMap;
    for( register TInt i = 0; i < iNumEscapeMappings; i++ ) {
        if( mapping->iEscape.Compare(aEscape) == 0 ) {
            return mapping->iChar;
        }
        
        mapping++;
    }

    // escape not found!
    _LIT(KNotSupportedEscape, "Not supported escape sequence &%S; on line %d!");
    iErrorReason.Format(KNotSupportedEscape, &aEscape, iLineNum);
    User::Leave(KErrParsingError);

    // to suppress compiler warning
    return 0;
}

void CEAXPParser::UnescapeL(const TPtrC &aFrom, TBool aTrim)
{
    TLex lex(aFrom);
    TChar esc_char;
    TInt offset;

    ValidateSizeL(&iUnescapeBuffer, aFrom.Length());
    TPtr ptr = iUnescapeBuffer->Des();
    ptr.Zero();

    TBool parsing_escape = EFalse;

    while( !lex.Eos() ) {
        TChar peek = lex.Peek();

        switch( peek ) {
            case KAmpersand:
                // consume ampersand and mark the start of escape
                lex.Inc();
                lex.Mark();
                parsing_escape = ETrue;
                break;
            case KSemicolon:
                if ( parsing_escape )
                    {
                    // consume semicolon and try to replace the escape sequence
                    offset = lex.Offset();
                    esc_char = FindEscapeL(aFrom.Mid(lex.MarkedOffset(), 
                                                     offset - lex.MarkedOffset()));
                    ptr.Append(esc_char);
                    parsing_escape = EFalse;
                    }
                else
                    {
                    // not parsing escape; append the semicolon normally
                    ptr.Append( KSemicolon );
                    }
                lex.Inc();
                break;
            default:
                // other char; consume and add to unescape buffer unless 
                // currently parsing an escape sequence
                lex.Inc();
                if( !parsing_escape ) {
                    ptr.Append(peek);
                }
                break;
        }
    }

    if( aTrim ) {
        iUnescapeBuffer->Des().Trim();
    }
}

EXPORT_C TBool CEAXPParser::ParseL( const TDesC8& aDocument )
    {
    HBufC* buf = HBufC::NewLC( aDocument.Length() );
    buf->Des().Copy( aDocument );
    TBool ret = ParseL( *buf );
    CleanupStack::PopAndDestroy( buf );

    return ret;
    }

EXPORT_C TBool CEAXPParser::ParseL(const TDesC &aDocument)
{
    iDocument.Set(aDocument);
    iLineNum = 1;

    TRAPD(err, ParseImplL());

    // after parsing is complete, make sure the buffers consume only the 
    // default amount of memory
    AllocateDefaultSizeBuffersL();

    if( err == KErrParsingError ) {
        iListener.ParsingError(iErrorReason);
        return EFalse;
    } else if( err != KErrNone ) {
        User::Leave(err);
    }

    return ETrue;
}

void CEAXPParser::ParseImplL()
{
    TLex lex(iDocument);
    TBool in_string = EFalse;
    TInt start_offs = 0;
    TPtrC ptr;

    iCoreState = ECoreNullState;

    // core parsing loop
    while( !lex.Eos() ) {
        TChar peek = lex.Peek();
        switch( peek ) {
            case KLessThan:
                if( iCoreState == ECoreParsingElement ) {
                    IllegalCharacterMetL(peek);
                } else if( iCoreState == ECoreParsingFreeText ) {
                    ValidateSizeAndCopyL(&iFreeText, 
                                         iDocument.Mid(lex.MarkedOffset(),
                                                       lex.Offset() - lex.MarkedOffset()));
                    ::XMLStringTrim(iFreeText->Des());

                    if( iFreeText->Length() > 0 ) {
                        UnescapeL(*iFreeText, ETrue);
                        iListener.FreeText(*iUnescapeBuffer);
                    }
                } 

                lex.Mark();
                iCoreState = ECoreParsingElement;
                break;
            case KGreaterThan:
                if( in_string || (iCoreState == ECoreParsingFreeText) ) {
                    IllegalCharacterMetL(peek);
                }

⌨️ 快捷键说明

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