Symbian下使用sdk中的xml解析器解析xml文档(测试通过)
1.要使用CParser类,需要在mmp文件中添加XmlFramework.lib
2.要使用CParser类,需要在mmp文件中添加hlplch.lib
同步使用CParser很简单,自己在CXMLHandle中修改即可。
CParser解析是基于sax解析方式,对xml文件结构查询极为不便,所以自己建立一棵树。
代码如下:
XMLHandle.h
/*
============================================================================
Name : XmlHandle.h
Author : pengjianhong
Version : 1.0
Copyright : Copyright 3G.CN
Description : CXmlHandle declaration
============================================================================
*/
#ifndef __XMLHANDLE_H__
#define __XMLHANDLE_H__
#include <e32base.h> // For CActive, link against: euser.lib
#include <e32std.h> // For RTimer, link against: euser.lib
#include <xml\contenthandler.h> // For MContentHandle
#include <xml\parser.h> // For CParser
using namespace Xml;
class RFile;
class CAttribute
{
public:
~CAttribute();
static CAttribute* NewL();
static CAttribute* NewLC();
private:
CAttribute();
void ConstructL();
public:
HBufC8* GetAttrName();
void SetAttrName( const TDesC8& aDes );
HBufC8* GetAttrValue();
void SetAttrValue( const TDesC8& aDes );
private:
HBufC8* iAttrName;
HBufC8* iAttrValue;
};
class CXMLElement
{
public:
~CXMLElement();
static CXMLElement* NewL();
static CXMLElement* NewLC();
private:
CXMLElement();
void ConstructL();
public:
HBufC8* GetElementName();
void SetElementName( const TDesC8& aDes );
HBufC8* GetElementDes();
void SetElementDes( const TDesC8& aDes );
void PushAttributeL( const CAttribute* aAttr );
void AddSubNode( CXMLElement* aElement );
RPointerArray<CAttribute> GetAttributeList();
RPointerArray<CXMLElement> GetSubNodeList();
private:
HBufC8* iName;
HBufC8* iDescription;
RPointerArray<CAttribute> iAttributeArray;
RPointerArray<CXMLElement> iSubNodeArray;
};
class CXmlHandle: public CActive, MContentHandler
{
public:
// Cancel and destroy
~CXmlHandle( );
// Two-phased constructor.
static CXmlHandle* NewL( );
// Two-phased constructor.
static CXmlHandle* NewLC( );
public:
//Public methods
void StartParsingWithAol( const TDesC& aFileName );
private:
// C++ constructor
CXmlHandle( );
// Second-phase constructor
void ConstructL( );
private:
// From CActive
// Handle completion
void RunL( );
// How to cancel me
void DoCancel( );
// Override to handle leaves from RunL(). Default implementation causes
// the active scheduler to panic.
TInt RunError( TInt aError );
public: // From MContentHandler
/**
This method is a callback to indicate the start of the document.
@param aDocParam Specifies the various parameters of the document.
@param aDocParam.iCharacterSetName The character encoding of the document.
@param aErrorCode is the error code.
If this is not KErrNone then special action may be required.
*/
void OnStartDocumentL(const RDocumentParameters& aDocParam, TInt aErrorCode );
/**
This method is a callback to indicate the end of the document.
@param aErrorCode is the error code.
If this is not KErrNone then special action may be required.
*/
void OnEndDocumentL(TInt aErrorCode);
/**
This method is a callback to indicate an element has been parsed.
@param aElement is a handle to the element's details.
@param aAttributes contains the attributes for the element.
@param aErrorCode is the error code.
If this is not KErrNone then special action may be required.
*/
void OnStartElementL(const RTagInfo& aElement, const RAttributeArray& aAttributes,
TInt aErrorCode);
/**
This method is a callback to indicate the end of the element has been reached.
@param aElement is a handle to the element's details.
@param aErrorCode is the error code.
If this is not KErrNone then special action may be required.
*/
void OnEndElementL(const RTagInfo& aElement, TInt aErrorCode);
/**
This method is a callback that sends the content of the element.
Not all the content may be returned in one go. The data may be sent in chunks.
When an OnEndElementL is received this means there is no more content to be sent.
@param aBytes is the raw content data for the element.
The client is responsible for converting the data to the
required character set if necessary.
In some instances the content may be binary and must not be converted.
@param aErrorCode is the error code.
If this is not KErrNone then special action may be required.
*/
void OnContentL(const TDesC8& aBytes, TInt aErrorCode);
/**
This method is a notification of the beginning of the scope of a prefix-URI Namespace mapping.
This method is always called before the corresponding OnStartElementL method.
@param aPrefix is the Namespace prefix being declared.
@param aUri is the Namespace URI the prefix is mapped to.
@param aErrorCode is the error code.
If this is not KErrNone then special action may be required.
*/
void OnStartPrefixMappingL(const RString& aPrefix, const RString& aUri,
TInt aErrorCode);
/**
This method is a notification of the end of the scope of a prefix-URI mapping.
This method is called after the corresponding DoEndElementL method.
@param aPrefix is the Namespace prefix that was mapped.
@param aErrorCode is the error code.
If this is not KErrNone then special action may be required.
*/
void OnEndPrefixMappingL(const RString& aPrefix, TInt aErrorCode);
/**
This method is a notification of ignorable whitespace in element content.
@param aBytes are the ignored bytes from the document being parsed.
@param aErrorCode is the error code.
If this is not KErrNone then special action may be required.
*/
void OnIgnorableWhiteSpaceL(const TDesC8& aBytes, TInt aErrorCode);
/**
This method is a notification of a skipped entity. If the parser encounters an
external entity it does not need to expand it - it can return the entity as aName
for the client to deal with.
@param aName is the name of the skipped entity.
@param aErrorCode is the error code.
If this is not KErrNone then special action may be required.
*/
void OnSkippedEntityL(const RString& aName, TInt aErrorCode);
/**
This method is a receive notification of a processing instruction.
@param aTarget is the processing instruction target.
@param aData is the processing instruction data. If empty none was supplied.
@param aErrorCode is the error code.
If this is not KErrNone then special action may be required.
*/
void OnProcessingInstructionL(const TDesC8& aTarget, const TDesC8& aData,
TInt aErrorCode);
/**
This method indicates an error has occurred.
@param aError is the error code
*/
void OnError(TInt aErrorCode);
/**
This method obtains the interface matching the specified uid.
@return 0 if no interface matching the uid is found.
Otherwise, the this pointer cast to that interface.
@param aUid the uid identifying the required interface.
*/
TAny* GetExtendedInterface(const TInt32 aUid);
private:
CParser* iParser;
HBufC8* iBuffer;
RFile iFile;
CXMLElement* iRootElement; //根节点
RPointerArray<CXMLElement> iElementArray;//临时队列
//RPointerArray<CXMLElement> iRootElementArray;//树林
};
#endif // XMLHANDLE_H
XMLHandle.cpp
/*
============================================================================
Name : XmlHandle.cpp
Author : pengjianhong
Version : 1.0
Copyright : Copyright 3G.CN
Description : CAttribute implementation
============================================================================
*/
#include <coemain.h>
#include <f32file.h>
#include "XmlHandle.h"
const TInt KFileBufferSize = 1024;
_LIT8( KXmlMimeType, "text/xml" );
CAttribute::CAttribute()
:iAttrName( NULL )
,iAttrValue( NULL )
{
}
CAttribute::~CAttribute()
{
delete iAttrName;
delete iAttrValue;
}
CAttribute* CAttribute::NewL()
{
CAttribute* self = CAttribute::NewLC( );
CleanupStack::Pop( ); // self;
return self;
}
CAttribute* CAttribute::NewLC()
{
CAttribute* self = new (ELeave) CAttribute;
CleanupStack::PushL( self );
self->ConstructL( );
return self;
}
void CAttribute::ConstructL()
{
}
inline HBufC8* CAttribute::GetAttrName()
{
return iAttrName;
}
inline void CAttribute::SetAttrName( const TDesC8& aDes )
{
if( NULL != iAttrName )
{
delete iAttrName;
iAttrName = NULL;
}
int nLen = aDes.Length();
iAttrName = HBufC8::NewL( nLen );
iAttrName->Des().Copy( aDes );
}
inline HBufC8* CAttribute::GetAttrValue()
{
return iAttrValue;
}
inline void CAttribute::SetAttrValue( const TDesC8& aDes )
{
if( NULL != iAttrValue )
{
delete iAttrValue;
iAttrValue = NULL;
}
int nLen = aDes.Length();
iAttrValue = HBufC8::NewL( nLen );
iAttrValue->Des().Copy( aDes );
}
/*
============================================================================
Name : XmlHandle.cpp
Author : pengjianhong
Version : 1.0
Copyright : Copyright 3G.CN
Description : CXMLElement implementation
============================================================================
*/
CXMLElement::CXMLElement()
: iName( NULL )
, iDescription( NULL )
{
}
CXMLElement::~CXMLElement()
{
delete iName;
iName = NULL;
delete iDescription;
iDescription = NULL;
iAttributeArray.ResetAndDestroy();
iSubNodeArray.ResetAndDestroy();
}
CXMLElement* CXMLElement::NewL()
{
CXMLElement* self = CXMLElement::NewLC( );
CleanupStack::Pop( ); // self;
return self;
}
CXMLElement* CXMLElement::NewLC()
{
CXMLElement* self = new (ELeave) CXMLElement;
CleanupStack::PushL( self );
self->ConstructL( );
return self;
}
void CXMLElement::ConstructL()
{
}
inline HBufC8* CXMLElement::GetElementName()
{
return iName;
}
inline void CXMLElement::SetElementName( const TDesC8& aDes )
{
if( NULL != iName )
{
delete iName;
iName = NULL;
}
int nLen = aDes.Length();
iName = HBufC8::NewL( nLen );
iName->Des().Copy( aDes );
}
inline HBufC8* CXMLElement::GetElementDes()
{
return iDescription;
}
inline void CXMLElement::SetElementDes( const TDesC8& aDes )
{
if( NULL != iDescription )
{
delete iDescription;
iDescription = NULL;
}
int nLen = aDes.Length();
iDescription = HBufC8::NewL( nLen );
iDescription->Des().Copy( aDes );
}
void CXMLElement::PushAttributeL( const CAttribute* aAttr )
{
if( NULL == aAttr )
{
return ;
}
iAttributeArray.AppendL( aAttr );
}
void CXMLElement::AddSubNode( CXMLElement* aElement )
{
if( NULL == aElement )
{
return ;
}
iSubNodeArray.AppendL( aElement );
}
/*
============================================================================
Name : XmlHandle.cpp
Author : pengjianhong
Version : 1.0
Copyright : Copyright 3G.CN
Description : CXmlHandle implementation
============================================================================
*/
CXmlHandle::CXmlHandle()
:CActive( EPriorityStandard ) // Standard priority
{
CActiveScheduler::Add( this ); // Add to scheduler
}
CXmlHandle* CXmlHandle::NewLC( )
{
CXmlHandle* self = new (ELeave) CXmlHandle( );
CleanupStack::PushL( self );
self->ConstructL( );
return self;
}
CXmlHandle* CXmlHandle::NewL( )
{
CXmlHandle* self = CXmlHandle::NewLC( );
CleanupStack::Pop( ); // self;
return self;
}
void CXmlHandle::ConstructL( )
{
iParser = CParser::NewL( KXmlMimeType, *this );
}
CXmlHandle::~CXmlHandle( )
{
Cancel( ); // Cancel any request, if outstanding
delete iParser;
delete iBuffer;
//iElementArray.ResetAndDestroy();
}
void CXmlHandle::DoCancel( )
{
iParser->ParseEndL();
iFile.Close;
delete iBuffer;
iBuffer = NULL;
}
void CXmlHandle::RunL( )
{
if( KErrNone == iStatus.Int() )
{
if( 0 == iBuffer->Length() )
{
iParser->ParseEndL();
iFile.Close();
delete iBuffer;
iBuffer = NULL;
}
else
{
iParser->ParseL( *iBuffer );
TPtr8 bufferPtr( iBuffer->Des() );
iFile.Read( bufferPtr, KFileBufferSize, iStatus );
SetActive();
}
}
else
{
//TODO:
}
}
TInt CXmlHandle::RunError( TInt aError )
{
return aError;
}
void CXmlHandle::StartParsingWithAol( const TDesC& aFileName )
{
if( IsActive() )
{
Cancel();
}
User::LeaveIfError( iFile.Open(CCoeEnv::Static()->FsSession(), aFileName, EFileRead) );
delete iBuffer;
iBuffer = NULL;
iBuffer = HBufC8::NewL( KFileBufferSize );
TPtr8 bufPtr( iBuffer->Des() );
iFile.Read( bufPtr, KFileBufferSize, iStatus );
SetActive();
iParser->ParseBeginL();
}
void CXmlHandle::OnStartDocumentL(const RDocumentParameters& /*aDocParam*/, TInt /*aErrorCode*/ )
{
}
void CXmlHandle::OnEndDocumentL(TInt /*aErrorCode*/)
{
}
void CXmlHandle::OnStartElementL(const RTagInfo& aElement, const RAttributeArray& aAttributes,
TInt aErrorCode)
{
if( KErrNone == aErrorCode )
{
CXMLElement* pItem = CXMLElement::NewL();
pItem->SetElementName( aElement.LocalName().DesC() );
for( TInt i = 0; i < aAttributes.Count(); ++i )
{
CAttribute* pAttribute = CAttribute::NewL();
pAttribute->SetAttrName( aAttributes[i].Attribute().LocalName().DesC() );
pAttribute->SetAttrValue( aAttributes[i].Value().DesC() );
pItem->PushAttributeL( pAttribute );
}
//将节点加入队列
iElementArray.AppendL( pItem );
//第一次加入队列的为跟节点
if( 1 == iElementArray.Count() )
{
iRootElement = pItem;
}
}
else
{
//TODO:
}
}
void CXmlHandle::OnEndElementL(const RTagInfo& aElement, TInt aErrorCode)
{
if( KErrNone == aErrorCode )
{
TInt nCount = iElementArray.Count();
if( nCount > 0 )
{
CXMLElement* pLastElement = iElementArray[ nCount - 1 ];
if( nCount > 1 )
{
CXMLElement* pFatherElement = iElementArray[ nCount - 2 ];
pFatherElement->AddSubNode( pLastElement );
}
iElementArray.Remove( nCount - 1 );
}
}
else
{
//TODO:
}
}
void CXmlHandle::OnContentL(const TDesC8& aBytes, TInt aErrorCode)
{
if( KErrNone == aErrorCode )
{
TInt nSize = iElementArray.Count();
CXMLElement* pLastElement = iElementArray[ nSize - 1 ];
if( NULL != pLastElement )
{
pLastElement->SetElementDes( aBytes );
}
}
else
{
//TODO:
}
}
void CXmlHandle::OnStartPrefixMappingL(const RString& /*aPrefix*/, const RString& /*aUri*/,
TInt /*aErrorCode*/)
{
}
void CXmlHandle::OnEndPrefixMappingL(const RString& /*aPrefix*/, TInt /*aErrorCode*/)
{
}
void CXmlHandle::OnIgnorableWhiteSpaceL(const TDesC8& /*aBytes*/, TInt /*aErrorCode*/)
{
}
void CXmlHandle::OnSkippedEntityL(const RString& /*aName*/, TInt /*aErrorCode*/)
{
}
void CXmlHandle::OnProcessingInstructionL(const TDesC8& /*aTarget*/, const TDesC8& /*aData*/,
TInt /*aErrorCode*/)
{
}
void CXmlHandle::OnError(TInt /*aErrorCode*/)
{
}
TAny* CXmlHandle::GetExtendedInterface(const TInt32 /*aUid*/)
{
return 0;
}