XmlExample
: Using the XML framework to parse an XML
file
This example application demonstrates the usage of the
XML
framework API to parse XML and WBXML files. It is
located in the folder examples\SysLibs\XmlExample
.
The overview contains the following sections:
The example application demonstrates, how to use the
Xml
framework to parse XML and WBXML files. It takes a
valid XML file with a DTD (Document Type Declaration) definining its structure,
and a WBXML (WAP Binary XML format) file as input. You can generate a WBXML
file from an XML file using any freeware converters. The application's
bld.inf
file specifies the target path to which all the three
files (XML, DTD, WBXML) need to be exported.
The application implements all the pure virtual functions of the
Xml::MContentHandler
class, which is a client interface to
the Xml
framework. These functions inform the client
application about the XML element being parsed, its content, parser errors if
any and so on.
The XML and WBXML files are parsed using an object of the
Xml::CParser
class. The parser object is configured to
report namespace mappings to the client application, using the function
Xml::CParser::EnableFeature()
.
The application first opens a file session using
RFs
to read the XML and WBXML files. Then, the
Xml::ParseL()
function is called to start parsing the
files. The application parses the XML file followed by the WBXML file. While
these files are being parsed, status messages are printed to the console by the
callback functions as and when they are invoked.
For demonstration purposes, the XML file is parsed twice, once by the
Xml::CParser
object created using the MIME type and again
by the CParser
object created using match data criteria. The match
data criteria are specified using an object of the
Xml::CMatchData
class, which is passed to the
Xml::CParser::NewLC()
function while creating the parser
object. This will return a CParser
object that matches the
specified MIME type, variant and so on.
The Symbian OS build process describes how to build an application.
The XmlExample
builds an executable called
xmlexample.exe
in the standard location
(\epoc32\release\winscw\<build_variant>
for CodeWarrior).
After launching the executable, depending on the emulator you are using, you
may need to task away from the application launcher/shell screen to view the
console. Alternatively, adding the string textshell
to the
emulator configuration file,
epoc.ini
, causes the emulator to start in text mode.
// BLD.INF
//
//
// Copyright (c) Symbian Software Ltd 2007. All rights reserved.
//
PRJ_EXPORTS
XmlExample.xml \epoc32\RELEASE\WINSCW\UDEB\Z\private\E80000AE\XmlExample.xml
XmlExample.dtd \epoc32\RELEASE\WINSCW\UDEB\Z\private\E80000AE\XmlExample.dtd
XmlExample.wbxml \epoc32\RELEASE\WINSCW\UDEB\Z\private\E80000AE\XmlExample.wbxml
PRJ_MMPFILES
xmlexample.mmp
// xmlexample.mmp
//
// Copyright (c) Symbian Software Ltd 2007. All rights reserved.
//
TARGET xmlexample.exe
TARGETTYPE exe
UID 0 0xE80000AE
CAPABILITY ReadUserData WriteUserData
SOURCEPATH .
SOURCE XMLEXAMPLE.CPP
USERINCLUDE .
SYSTEMINCLUDE \Epoc32\include
LIBRARY euser.lib efsrv.lib bafl.lib
LIBRARY XmlFramework.lib
// xmlexample.h
// Copyright (c) Symbian Software Ltd 2007. All rights reserved.
//
#ifndef XMLEXAMPLE_H
#define XMLEXAMPLE_H
#include <Xml/ContentHandler.h>
#include <Xml/Parser.h>
class RFile;
/**
CXmlExample demonstrates the usage of the XML Framework to parse an XML and WBXML file.
CXmlExample implements the XML Framework's MContentHandler interface,
which the parser calls to notify the application of parsing events, such
as the start of elements.
*/
class CXmlExample: public CBase, public Xml::MContentHandler
{
public:
static CXmlExample* NewL();
~CXmlExample();
// From MContentHandler
void OnStartDocumentL(const Xml::RDocumentParameters& aDocParam, TInt aErrorCode);
void OnEndDocumentL(TInt aErrorCode);
void OnStartElementL(const Xml::RTagInfo& aElement, const Xml::RAttributeArray& aAttributes, TInt aErrorCode);
void OnEndElementL(const Xml::RTagInfo& aElement, TInt aErrorCode);
void OnContentL(const TDesC8& aBytes, TInt aErrorCode);
void OnStartPrefixMappingL(const RString& aPrefix, const RString& aUri, TInt aErrorCode);
void OnEndPrefixMappingL(const RString& aPrefix, TInt aErrorCode);
void OnIgnorableWhiteSpaceL(const TDesC8& aBytes, TInt aErrorCode);
void OnSkippedEntityL(const RString& aName, TInt aErrorCode) ;
void OnProcessingInstructionL(const TDesC8& aTarget, const TDesC8& aData, TInt aErrorCode);
void OnError(TInt aErrorCode);
TAny* GetExtendedInterface(const TInt32 aUid);
void ParseExampleDocumentsL();
HBufC* Copy8To16LC(const TDesC8& aDes);
public:
TBool iLeaveOnStartElement;
TInt iNumElements;
TInt iNumSkippedEntities;
TInt iNumPrefixMappings;
TInt iNumPrefixUnmappings;
TInt iError;
private:
CXmlExample();
void ConstructL();
/** Pointer to the console interface*/
CConsoleBase* iConsole;
};
#endif // XMLEXAMPLE_H
// xmlexample.cpp
//
// Copyright (c) Symbian Software Ltd 2007. All rights reserved.
//
/**
@file
This example program demonstrates the use of XML Framework APIs.
The code implements all the functions of MContentHandler class.
The example parses the XML file and WBXML file present in the specified path. To know how to
write an XML file you can refer to this URL http://www.w3schools.com/xml/.
*/
#include "xmlexample.h"
#include <Xml/DocumentParameters.h>
#include <Xml/ParserFeature.h>
#include <Xml/MatchData.h>
#include <e32cons.h>
using namespace Xml;
_LIT(KTitle, "XML example");
_LIT(KStartKey, "\nThe example parses the given XML and WBXML files. Press any key to start\n");
_LIT(KPressAKey,"\nPress any key to continue \n");
_LIT(KExit,"\n Press any key to exit the application \n");
_LIT(KParsingXml,"\nParsing the XML file");
_LIT(KParsingWbXml,"\nParsing the WBXML file");
_LIT(KParsingMatch,"\nParsing the XML file using match data criteria");
_LIT(KError,"\n Could not open the XML file. Please check if the file exists.");
_LIT(KOnStartDoc,"\n<!-- CXmlExample::OnStartDocumentL -->\n");
_LIT(KOnEndDoc,"\n<!-- CXmlExample::OnEndDocumentL -->\n");
_LIT(KOnContent,"<!-- CXmlExample::OnContentL -->");
_LIT(KOnProcInstrn,"\n<!-- CXmlExample::OnProcessingInstructionL -->\n");
_LIT(KOnError,"CXmlExample::OnError - ERROR: code=%d\n");
_LIT(KVersion,"<?xml version=\"1.0\" encoding=\"%S\"?>\n");
_LIT(KStartElement,"\nStart of element: <%S>\n");
_LIT(KEndElement,"\nEnd of element: </%S>\n");
_LIT(KContent,"%S\n");
_LIT(KAttrib,"The attribute of element <%S>=\"%S\"");
_LIT(KProcInstrn,"<?%S %S?>\n");
_LIT(KOnSkipped, "Found skipped entity %S");
_LIT(KNameSpaceRep,"\nNamespace mapping reporting enabled\n ");
_LIT(KPrefixMap, "\nThe prefix is %S and URI is %S\n");
_LIT(KPrefixEnd, "End of prefix URI mapping %S\n");
_LIT(KSimpleXmlFile, "z:\\private\\E80000AE\\XmlExample.xml");
_LIT(KSimpleWbXmlFile, "z:\\private\\E80000AE\\XmlExample.wbxml");
_LIT8(KXmlMimeType, "text/xml");
_LIT8(KWbxmlMimeType, "text/wbxml");
/**
Allocates and constructs a CXmlExample object.
Initialises all member data to their default values.
*/
CXmlExample* CXmlExample::NewL()
{
CXmlExample* self = new (ELeave) CXmlExample();
CleanupStack::PushL(self);
self->ConstructL();
CleanupStack::Pop();
return self;
}
CXmlExample::CXmlExample()
:iError(KErrNone)
{
}
void CXmlExample::ConstructL()
{
iConsole = Console::NewL(KTitle,TSize(KConsFullScreen,KConsFullScreen));
iConsole->Printf ( KStartKey);
iConsole->Getch ();
}
/**
Destructor
*/
CXmlExample::~CXmlExample()
{
iConsole->Printf(KExit);
iConsole->Getch();
delete iConsole;
}
/**
A callback to indicate the start of the document.
It retrieves the XML version and encoding details and prints it to the console.
Implementation of the pure virtual function of MContentHandler.
@param aDocParam Specifies the various parameters of the document.
@param aErrorCode The error code.
@leave If aErrorCode is not KErrNone, the function leaves.
*/
void CXmlExample::OnStartDocumentL(const RDocumentParameters& aDocParam, TInt aErrorCode)
{
User::LeaveIfError(aErrorCode);
iConsole->Printf(KOnStartDoc);
const TDesC8& encoding8 = aDocParam.CharacterSetName().DesC();
HBufC* encoding16= Copy8To16LC(encoding8);
iConsole->Printf(KVersion, encoding16);
CleanupStack::PopAndDestroy(encoding16);
}
/**
A callback to indicate the end of the document.
Implementation of the pure virtual function of MContentHandler.
@param aErrorCode The error code.
@leave If aErrorCode is not KErrNone, the function leaves.
*/
void CXmlExample::OnEndDocumentL(TInt aErrorCode)
{
User::LeaveIfError(aErrorCode);
iConsole->Printf(KOnEndDoc);
User::After(700000); // 0.7 seconds
}
/**
A callback to indicate an element has been parsed.
It prints element details on the console.
Implementation of the pure virtual function of MContentHandler.
@param aElement A handle to the element's details.
@param aAttributes Attributes of the element.
@param aErrorCode The error code.
@leave If aErrorCode is not KErrNone, the function leaves.
*/
void CXmlExample::OnStartElementL(const RTagInfo& aElement, const RAttributeArray& aAttributes, TInt aErrorCode)
{
User::LeaveIfError(aErrorCode);
const TDesC8& localName8 = aElement.LocalName().DesC();
HBufC* localName16 = Copy8To16LC(localName8);
iConsole->Printf(KStartElement,localName16);
CleanupStack::PopAndDestroy(); // Delete localName16
TInt nAttributes = aAttributes.Count();
for(TInt i=0; i<nAttributes; i++)
{
const RAttribute& attribute = aAttributes[i];
const RTagInfo& nameInfo = attribute.Attribute();
const TDesC8& localName8 = nameInfo.LocalName().DesC();
const TDesC8& value8 = attribute.Value().DesC();
HBufC* localName16 = Copy8To16LC(localName8);
HBufC* value16 = Copy8To16LC(value8);
iConsole->Printf(KAttrib, localName16, value16);
CleanupStack::PopAndDestroy(2,localName16);
}
User::After(700000); // 0.7 sec
}
/**
A callback to indicate the end of the element has been reached.
Prints element end tag to the console.
Implementation of the pure virtual function of MContentHandler.
@param aElement The handle to the element's details.
@param aErrorCode The error code.
@leave If aErrorCode is not KErrNone, the function leaves.
*/
void CXmlExample::OnEndElementL(const RTagInfo& aElement, TInt aErrorCode)
{
User::LeaveIfError(aErrorCode);
const TDesC8& localName8 = aElement.LocalName().DesC();
HBufC* endBuf16 = Copy8To16LC(localName8);
iConsole->Printf(KEndElement,endBuf16);
CleanupStack::PopAndDestroy(endBuf16);
}
/**
Copies 8 bit descriptor data to 16 bit descriptor
@leave KErrNoMemory, User 11
*/
HBufC* CXmlExample::Copy8To16LC(const TDesC8& aDes)
{
HBufC* buf16 = HBufC::NewLC(aDes.Length());
buf16->Des().Copy(aDes);
return buf16;
}
/**
A callback that sends the content of the element and prints element content data to the console.
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.
Implementation of the pure virtual function of MContentHandler.
@param aData8 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 The error code.
@leave If aErrorCode is not KErrNone, the function leaves.
*/
void CXmlExample::OnContentL(const TDesC8& aData8, TInt aErrorCode)
{
User::LeaveIfError(aErrorCode);
iConsole->Printf(KOnContent);
HBufC* data16 = Copy8To16LC(aData8);
iConsole->Printf(KContent,data16);
CleanupStack::PopAndDestroy(data16);
}
/**
A receive notification of a processing instruction.
It prints the target and data to the console.
Implementation of the pure virtual function of MContentHandler.
@param aTarget The processing instruction target.
@param aData The processing instruction data. If empty, none was supplied.
@param aErrorCode The error code.
@leave If aErrorCode is not KErrNone, the function leaves.
*/
void CXmlExample::OnProcessingInstructionL(const TDesC8& aTarget8, const TDesC8& aData8, TInt aErrorCode)
{
User::LeaveIfError(aErrorCode);
iConsole->Printf(KOnProcInstrn);
HBufC* target16 = Copy8To16LC(aTarget8);
HBufC* data16 = Copy8To16LC(aData8);
iConsole->Printf(KProcInstrn,target16,data16);
CleanupStack::PopAndDestroy(2,target16);
User::After(700000); // 0.7 sec
}
/**
Implementation of the pure virtual function of MContentHandler.
Indicates that an error has occurred.
@param aError The error code
*/
void CXmlExample::OnError(TInt aError)
{
iError = aError;
iConsole->Printf(KOnError,aError);
iConsole->Printf(KPressAKey);
iConsole->Getch();
}
/**
Obtain the interface matching the specified uid.
*/
TAny* CXmlExample::GetExtendedInterface(const TInt32 /*aUid*/)
{
// do nothing.
return NULL;
}
/**
A notification of the beginning of the scope of a prefix-URI Namespace mapping.
Always called before the corresponding OnStartElementL method.
Implementation of the pure virtual function of MContentHandler.
@param aPrefix The Namespace prefix being declared.
@param aUri The Namespace URI the prefix is mapped to.
@param aErrorCode The error code.
@leave KErrNotSupported
*/
void CXmlExample::OnStartPrefixMappingL(const RString& aPrefix, const RString& aUri, TInt aErrorCode)
{
User::LeaveIfError(aErrorCode);
const TDesC8& localPrefix8 = aPrefix.DesC();
HBufC* temp1 = Copy8To16LC(localPrefix8);
const TDesC8& localUri8 = aUri.DesC();
HBufC* temp2 = Copy8To16LC(localUri8);
iConsole->Printf(KPrefixMap, temp1, temp2);
CleanupStack::PopAndDestroy(2, temp1);
iConsole->Printf(KPressAKey);
iConsole->Getch();
}
/**
Notification of the end of the scope of a prefix-URI mapping.
*/
void CXmlExample::OnEndPrefixMappingL(const RString& aPrefix, TInt aErrorCode)
{
User::LeaveIfError(aErrorCode);
const TDesC8& localPrefix8 = aPrefix.DesC();
HBufC* temp = Copy8To16LC(localPrefix8);
iConsole->Printf(KPrefixEnd, temp);
CleanupStack::PopAndDestroy(temp);
}
/**
A notification of ignorable whitespace in element content.
*/
void CXmlExample::OnIgnorableWhiteSpaceL(const TDesC8&, TInt)
{
}
/**
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.
Implementation of the pure virtual function of MContentHandler.
@param aName Name of the skipped entity.
@param aErrorCode The error code.
@leave KErrNotSupported
*/
void CXmlExample::OnSkippedEntityL(const RString& aName, TInt aErrorCode)
{
User::LeaveIfError(aErrorCode);
const TDesC8& localName8 = aName.DesC();
HBufC* temp = Copy8To16LC(localName8);
iConsole->Printf(KOnSkipped, temp);
CleanupStack::PopAndDestroy(temp);
User::After(700000); // 0.7 sec delay
}
/**
Passes an XML and a WBXML file to the framework for parsing.
*/
void CXmlExample::ParseExampleDocumentsL()
{
RFs fs;
User::LeaveIfError(fs.Connect());
CleanupClosePushL(fs);
RFile handle;
TInt err;
// Open an example XML file for parsing
TRAP(err,handle.Open(fs, KSimpleXmlFile, EFileShareReadersOnly));
if (err != KErrNone)
{
iConsole->Printf(KError);
User::Leave(err);
}
CleanupClosePushL(handle);
// Open parser session for text/xml mime type
CParser* parser = CParser::NewLC(KXmlMimeType, *this);
iConsole->Printf(KParsingXml);
iConsole->Printf(KPressAKey);
iConsole->Getch();
err = parser->EnableFeature(EReportNamespaceMapping);
if(err==KErrNone)
{
iConsole->Printf(KNameSpaceRep);
}
// Starts parser session
ParseL(*parser, handle); // this will result in callbacks to handler
// Closes the parser session.
CleanupStack::PopAndDestroy(parser);
CleanupStack::Pop(&handle);
// Open an example WBXML file for parsing
TRAP(err,handle.Open(fs, KSimpleWbXmlFile, EFileShareReadersOnly));
if (err != KErrNone)
{
iConsole->Printf(KError);
User::Leave(err);
}
CleanupClosePushL(handle);
parser = CParser::NewLC(KWbxmlMimeType, *this);
iConsole->Printf(KParsingWbXml);
iConsole->Printf(KPressAKey);
iConsole->Getch();
// Starts parser session and active scheduler.
ParseL(*parser, handle); // this will result in callbacks to handler
CleanupStack::PopAndDestroy(parser);
CleanupStack::Pop(&handle);
// Open an example XML file for parsing using a parser specified with
// MatchData. In this case, the default Symbian OS parser is requested.
TRAP(err,handle.Open(fs, KSimpleXmlFile, EFileShareReadersOnly));
if (err != KErrNone)
{
iConsole->Printf(KError);
User::Leave(err);
}
CleanupClosePushL(handle);
CMatchData *matchData = CMatchData::NewLC();
matchData->SetMimeTypeL(KXmlMimeType);
matchData->SetVariantL(_L8("Symbian"));
iConsole->Printf(KParsingMatch);
iConsole->Printf(KPressAKey);
iConsole->Getch();
parser = CParser::NewLC(*matchData, *this);
ParseL(*parser, handle);
CleanupStack::PopAndDestroy(2,matchData);
CleanupStack::PopAndDestroy(&handle);
CleanupStack::PopAndDestroy(&fs);
}
LOCAL_C void MainL()
{
CXmlExample* app = CXmlExample::NewL();
CleanupStack::PushL(app);
app->ParseExampleDocumentsL();
CleanupStack::PopAndDestroy(app);
}
GLDEF_C TInt E32Main()
{
__UHEAP_MARK;
CTrapCleanup* cleanup = CTrapCleanup::New();
if(cleanup == NULL)
{
return KErrNoMemory;
}
TRAPD(err, MainL());
if(err != KErrNone)
{
User::Panic(_L("Failed to complete"),err);
}
delete cleanup;
__UHEAP_MARKEND;
return KErrNone;
}
<?xml version="1.0" encoding="UTF-8"?>
<?exampletarget example data?>
<!DOCTYPE foobar:DeveloperLibrary SYSTEM "xmlexample.dtd">
<foobar:DeveloperLibrary xmlns:foobar="http://symbian.com/">
<foobar:foo>&unknown;</foobar:foo>
<foobar:file type="xml">XmlExample.xml</foobar:file>
<foobar:SysDoc_Example>
This file shows XML file parsing example of syslibs component using Symbian OS XML parser framework.
</foobar:SysDoc_Example>
<foobar:Company_Copyright>
Copyright (c) Symbian Software Ltd 2007. All rights reserved.
</foobar:Company_Copyright>
<foobar:Message_1>
Happy programming to all
</foobar:Message_1>
</foobar:DeveloperLibrary>
<!ELEMENT foobar:DeveloperLibrary (foobar:foo, foobar:file, foobar:SysDoc_Example, foobar:Company_Copyright, foobar:Message_1)>
<!ATTLIST foobar:DeveloperLibrary
xmlns:foobar CDATA #REQUIRED>
<!ELEMENT foobar:foo (#PCDATA)>
<!ELEMENT foobar:file (#PCDATA)>
<!ATTLIST foobar:file type CDATA #REQUIRED>
<!ELEMENT foobar:SysDoc_Example (#PCDATA)>
<!ELEMENT foobar:Company_Copyright (#PCDATA)>
<!ELEMENT foobar:Message_1 (#PCDATA)>