Symbian
Symbian OS Library

SYMBIAN OS V9.3

[Index] [Spacer] [Previous] [Next]



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:


Description

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.

[Top]


Class summary

[Top]


Build

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.

[Top]


Example code


bld.inf

// 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

// 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

// 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

// 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;
    }


XmlExample.xml

<?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>


xmlexample.dtd

<!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)>