📄 xmlhandler.cpp
字号:
// --------------------------------------------------------------------------
// XmlHandler.cpp
//
// Copyright 2007, Antony Pranata
// http://www.antonypranata.com
//
// Example how to parse XML file using SAX on Symbian OS.
//
// There are two methods to parse XML document, i.e.;
// - StartParsingL() -> parse XML document without active object.
// The whole file content is read at once. It is simple, but suitable
// for relatively small file only.
// - StartParsingWithAoL() -> parse XML document with active object.
// --------------------------------------------------------------------------
// INCLUDE FILES
#include <coemain.h>
#include <f32file.h>
#include "XmlHandler.h"
// CONSTANTS
const TInt KBufferSize = 1024; // buffer size to store the result of
// XML parsing -> the actual buffer size
// can expand if needed (see AppendText())
const TInt KFileBufferSize = 1024; // buffer size for file reading
const TInt KOverheadLen = 4; // length of (KOpeningTag + KClosingTag
// + KSlash + KEndOfLine)
_LIT(KOpeningTag, "<" );
_LIT(KClosingTag, ">" );
_LIT(KSlash, "/" );
_LIT(KEndOfLine, "\f" ); // CEikEdwin uses '\f' as EOF mark.
_LIT8( KXmlMimeType, "text/xml" );
// METHODS DEFINITION
// --------------------------------------------------------------------------
CXmlHandler* CXmlHandler::NewL( MXmlHandlerObserver& aObserver )
{
CXmlHandler* self = CXmlHandler::NewLC( aObserver );
CleanupStack::Pop();
return self;
}
// --------------------------------------------------------------------------
CXmlHandler* CXmlHandler::NewLC( MXmlHandlerObserver& aObserver )
{
CXmlHandler* self = new ( ELeave ) CXmlHandler( aObserver );
CleanupStack::PushL( self );
self->ConstructL();
return self;
}
// --------------------------------------------------------------------------
CXmlHandler::~CXmlHandler()
{
Cancel();
delete iParser;
delete iDisplayResult;
delete iBuffer;
}
// --------------------------------------------------------------------------
CXmlHandler::CXmlHandler( MXmlHandlerObserver& aObserver )
:CActive( EPriorityStandard ),
iObserver( aObserver ),
iParser( 0 ),
iDisplayResult( 0 ),
iState( EIdle )
{
CActiveScheduler::Add( this );
}
// --------------------------------------------------------------------------
void CXmlHandler::DoCancel()
{
iParser->ParseEndL();
iFile.Close();
delete iBuffer;
iBuffer = 0;
}
// --------------------------------------------------------------------------
void CXmlHandler::RunL()
{
if ( KErrNone == iStatus.Int() )
{
// If the buffe length is zero, it means if we have reached
// the end of the file.
if ( iBuffer->Length() == 0)
{
iParser->ParseEndL();
iFile.Close();
delete iBuffer;
iBuffer = 0;
}
// Otherwise, we continue reading the next chunk of the XML file.
else
{
// Parse the next "part" of the XML document.
iParser->ParseL( *iBuffer );
// Read the next chunk of the file.
TPtr8 bufferPtr( iBuffer->Des() );
iFile.Read( bufferPtr, KFileBufferSize, iStatus );
// Don't forget to call this... :)
SetActive();
}
}
else
{
iObserver.OnParseCompleted( iStatus.Int() );
}
}
// --------------------------------------------------------------------------
void CXmlHandler::ConstructL()
{
iParser = CParser::NewL( KXmlMimeType, *this );
iDisplayResult = HBufC::NewL( KBufferSize );
}
// --------------------------------------------------------------------------
void CXmlHandler::StartParsingL( const TDesC& aFileName )
{
// Read the whole content of aFileName into iBuffer.
// IMPORTANT: This example reads the whole content within
// one-shot for simplicity reason.
// In reality, you have to read it chunk by chunk
// using active object so that your application doesn't block.
RFile file;
User::LeaveIfError( file.Open( CCoeEnv::Static()->FsSession(), aFileName,
EFileRead ) );
CleanupClosePushL( file );
iDisplayResult->Des().Zero();
TInt size;
User::LeaveIfError( file.Size( size ) );
delete iBuffer;
iBuffer = 0;
iBuffer = HBufC8::NewL( size );
TPtr8 bufferPtr( iBuffer->Des() );
User::LeaveIfError( file.Read( bufferPtr ) );
CleanupStack::PopAndDestroy(); // file
// Now, we have the whole file content in iBuffer.
// We are ready to parse the XML content.
iParser->ParseBeginL();
iParser->ParseL( *iBuffer );
// Since we read the whole file contents within one-shot,
// we can call ParseEndL() right after calling ParseL().
iParser->ParseEndL();
}
// --------------------------------------------------------------------------
void CXmlHandler::StartParsingWithAoL( const TDesC& aFileName )
{
// Remember to cancel any outstanding request first.
if ( IsActive() )
{
Cancel();
}
User::LeaveIfError( iFile.Open( CCoeEnv::Static()->FsSession(), aFileName,
EFileRead ) );
// Create a buffer to store the file content.
// Note that this method uses active object to read the file.
// So we have to call SetActive() at the end. Then we call CParser::ParseL()
// in RunL() method.
iDisplayResult->Des().Zero();
delete iBuffer;
iBuffer = 0;
iBuffer = HBufC8::NewL( KFileBufferSize );
TPtr8 bufferPtr( iBuffer->Des() );
iFile.Read( bufferPtr, KFileBufferSize, iStatus );
SetActive();
// Tell the parser that we are about to parse a XML document.
iParser->ParseBeginL();
}
// --------------------------------------------------------------------------
void CXmlHandler::OnStartDocumentL( const RDocumentParameters& /*aDocParam*/,
TInt aErrorCode )
{
// Display message to the screen stating that this is the starting of
// XML document.
_LIT( KOnStartDocumentL, "*** OnStartDocumentL ***\f" );
AppendText( KOnStartDocumentL );
if ( KErrNone == aErrorCode )
{
// Do something if needed....
}
else
{
iObserver.OnParseCompleted( aErrorCode );
}
}
// --------------------------------------------------------------------------
void CXmlHandler::OnEndDocumentL( TInt aErrorCode )
{
// Display message to the screen stating that this is the starting of
// XML document.
_LIT( KOnEndDocumentL, "*** OnEndDocumentL ***\f" );
AppendText( KOnEndDocumentL );
if ( KErrNone == aErrorCode )
{
// Do something here if needed....
}
iObserver.OnParseCompleted( aErrorCode );
}
// --------------------------------------------------------------------------
void CXmlHandler::OnStartElementL( const RTagInfo& aElement,
const RAttributeArray& /*aAttributes*/, TInt aErrorCode )
{
if ( KErrNone == aErrorCode )
{
// If we find the start of an element, we write to the screen,
// for example: "<tag>"
AppendTag( aElement.LocalName().DesC(), EFalse );
}
else
{
iObserver.OnParseCompleted( aErrorCode );
}
}
// --------------------------------------------------------------------------
void CXmlHandler::OnEndElementL( const RTagInfo &aElement, TInt aErrorCode )
{
if ( KErrNone == aErrorCode )
{
// If we find the end of an element, we write it to the screen,
// for example: "</tag>"
AppendTag( aElement.LocalName().DesC(), ETrue );
}
else
{
iObserver.OnParseCompleted( aErrorCode );
}
}
// --------------------------------------------------------------------------
void CXmlHandler::OnContentL( const TDesC8 &aBytes, TInt aErrorCode )
{
if ( KErrNone == aErrorCode )
{
// Display aBytes on the screen.
// Before we can display it, we have to convert the content
// from TDesC8 to TDesC16.
HBufC* buffer = HBufC::NewLC( aBytes.Length() + 1 );
TPtr bufferPtr( buffer->Des() );
bufferPtr.Copy( aBytes );
AppendText( *buffer );
CleanupStack::PopAndDestroy(); // buffer
}
else
{
iObserver.OnParseCompleted( aErrorCode );
}
}
// --------------------------------------------------------------------------
void CXmlHandler::OnStartPrefixMappingL( const RString& /*aPrefix*/,
const RString& /*aUri*/, TInt aErrorCode )
{
if ( KErrNone == aErrorCode )
{
// Do something here...
}
else
{
iObserver.OnParseCompleted( aErrorCode );
}
}
// --------------------------------------------------------------------------
void CXmlHandler::OnEndPrefixMappingL( const RString& /*aPrefix*/,
TInt aErrorCode )
{
if ( KErrNone == aErrorCode )
{
// Do something here...
}
else
{
iObserver.OnParseCompleted( aErrorCode );
}
}
// --------------------------------------------------------------------------
void CXmlHandler::OnIgnorableWhiteSpaceL( const TDesC8& /*aBytes*/,
TInt aErrorCode )
{
if ( KErrNone == aErrorCode )
{
// Do something here...
}
else
{
iObserver.OnParseCompleted( aErrorCode );
}
}
// --------------------------------------------------------------------------
void CXmlHandler::OnSkippedEntityL( const RString& /*aName*/,
TInt aErrorCode )
{
if ( KErrNone == aErrorCode )
{
// Do something here...
}
else
{
iObserver.OnParseCompleted( aErrorCode );
}
}
// --------------------------------------------------------------------------
void CXmlHandler::OnProcessingInstructionL( const TDesC8& /*aTarget*/,
const TDesC8& /*aData*/, TInt aErrorCode )
{
if ( KErrNone == aErrorCode )
{
// Do something here...
}
else
{
iObserver.OnParseCompleted( aErrorCode );
}
}
// --------------------------------------------------------------------------
void CXmlHandler::OnError( TInt aErrorCode )
{
_LIT( KErrorMessage, "*** OnError ***\f" );
AppendText( KErrorMessage );
iObserver.OnParseCompleted( aErrorCode );
}
// --------------------------------------------------------------------------
TAny* CXmlHandler::GetExtendedInterface( const TInt32 /*aUid*/ )
{
return 0;
}
// --------------------------------------------------------------------------
void CXmlHandler::AppendText( const TDesC& aText )
{
TPtr displayResultPtr( iDisplayResult->Des() );
if ( displayResultPtr.Length() + aText.Length() > displayResultPtr.MaxLength() )
{
iDisplayResult = iDisplayResult->ReAllocL( displayResultPtr.MaxLength()
+ KBufferSize );
displayResultPtr.Set( iDisplayResult->Des() );
}
displayResultPtr.Append( aText );
}
// --------------------------------------------------------------------------
void CXmlHandler::AppendTag( const TDesC8& aTag, TBool aIsClosingTag )
{
// Instantiate buffer to display tag information.
HBufC* buffer = HBufC::NewLC( aTag.Length()
+ ( ( aIsClosingTag ) ? KOverheadLen : KOverheadLen - 1 ) );
TPtr bufferPtr( buffer->Des() );
// Convert tag name from TDesC8 to TDesC16.
bufferPtr.Copy( aTag );
// Add opening tag.
if ( aIsClosingTag )
{
bufferPtr.Insert( 0, KSlash );
}
bufferPtr.Insert( 0, KOpeningTag );
// Add closing tag.
bufferPtr.Append( KClosingTag );
bufferPtr.Append( KEndOfLine );
// Add to the result text and then destroy it.
AppendText( *buffer );
CleanupStack::PopAndDestroy(); // buffer
}
// End of File
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -