brandingserver/tools/bsimport/src/cbsimportxmlparser.cpp
changeset 0 e6b17d312c8b
child 21 cfd5c2994f10
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/brandingserver/tools/bsimport/src/cbsimportxmlparser.cpp	Thu Dec 17 08:54:49 2009 +0200
@@ -0,0 +1,779 @@
+/*
+* Copyright (c) 2006-2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Parses XML content and stores data to storage
+*
+*/
+
+
+#include <e32cons.h>
+#include <gmxmlelement.h>
+#include <gmxmltext.h>
+#include <utf.h>
+#include <AknUtils.h>
+#include <bselementfactory.h>
+#include <cbsbitmap.h>
+
+#include "cbsimportxmlparser.h"
+#include "cbsimportstoragemanager.h"
+#include "cbsimportstorage.h"
+#include "cbsimportconstants.h"
+#include "importlogwriter.h"
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// CBSImportXMLParser::NewL
+// ---------------------------------------------------------------------------
+//
+CBSImportXMLParser* CBSImportXMLParser::NewL( CBSImportStorageManager* aStorage )
+    {
+    CBSImportXMLParser* self = NewLC( aStorage );
+    CleanupStack::Pop();
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// CBSImportXMLParser::NewLC
+// ---------------------------------------------------------------------------
+//
+CBSImportXMLParser* CBSImportXMLParser::NewLC( CBSImportStorageManager* aStorage )
+    {
+    CBSImportXMLParser* self = new (ELeave) CBSImportXMLParser( aStorage );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// CBSImportXMLParser::ConstructL
+// ---------------------------------------------------------------------------
+//
+void CBSImportXMLParser::ConstructL()
+    {
+    }
+    
+// ---------------------------------------------------------------------------
+// CBSImportXMLParser::~CBSImportXMLParser
+// ---------------------------------------------------------------------------
+//
+CBSImportXMLParser::~CBSImportXMLParser()
+    {
+    }
+
+// ---------------------------------------------------------------------------
+// CBSImportXMLParser::CBSImportXMLParser
+// ---------------------------------------------------------------------------
+//
+CBSImportXMLParser::CBSImportXMLParser( CBSImportStorageManager* aStorage ) :
+    iStorage( aStorage )
+    {
+    }
+    
+// ---------------------------------------------------------------------------
+// CBSImportXMLParser::ParseDocumentL
+// ---------------------------------------------------------------------------
+//
+void CBSImportXMLParser::ParseDocumentL( CMDXMLDocument& aDocument )
+    {
+    if( !iStorage )
+        {
+        // No storage --> can't continue
+        User::Leave( KErrNotReady );
+        }
+
+    CMDXMLElement* element = aDocument.DocumentElement();
+    ParseDocumentBaseL( element );
+    }
+
+// ---------------------------------------------------------------------------
+// CBSImportXMLParser::ParseDocumentBaseL
+// ---------------------------------------------------------------------------
+//
+void CBSImportXMLParser::ParseDocumentBaseL( CMDXMLNode* aElement )
+    {
+    if( aElement->HasChildNodes() )
+        {
+        // Verify that <branding> element is the first one
+        CMDXMLNode* brandingNode = aElement->FirstChild();
+        if( !brandingNode->HasChildNodes() )
+            {
+            IMPORT_DP_TXT("ERROR: empty <branding> tag found" );
+            User::Leave( KErrCorrupt ); 
+            }
+
+        // Parse through all <brand> elements
+        CMDXMLNode* brandNode = brandingNode->FirstChild();
+        while( brandNode )
+            {
+            if( 0 == brandNode->NodeName().CompareC( KBrandTag ) )
+                {
+                if( !brandNode->HasChildNodes() )
+                    {
+                    IMPORT_DP_TXT("ERROR: empty <brand> tag found" );
+                    User::Leave( KErrCorrupt ); 
+                    }
+
+                // Create a new storage for each <brand> element
+                iStorage->CreateStorageL();
+
+                // Scan through all elements inside <brand> tags
+                // and store them to storage
+                CMDXMLNode* kidNode = brandNode->FirstChild();
+                while( kidNode )
+                    {
+                    TRAPD( err, AnalyzeNodeL( kidNode ) );
+                    if( err )
+                        {
+                        IMPORT_DP( D_IMPORT_LIT("ERROR: Error parsing content of <brand> (%d)"), err );
+                        User::Leave( err ); 
+                        }
+                    kidNode = kidNode->NextSibling();
+                    }
+                }
+            
+            // move to next brand package
+            brandNode = brandNode->NextSibling();
+            }
+        }
+    else
+        {
+        // no elements in file --> corrupt
+        IMPORT_DP_TXT("ERROR: Empty XML content" );
+        User::Leave( KErrCorrupt ); 
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CBSImportXMLParser::AnalyzeNodeL
+// ---------------------------------------------------------------------------
+//
+void CBSImportXMLParser::AnalyzeNodeL( CMDXMLNode* aNode )
+    {
+    switch( SolveTagTypeL( aNode ) )
+        {
+        case EBrandID:
+            {
+            if( aNode->HasChildNodes() )
+                {
+                HBufC* id = NodeTextLC( aNode );
+                iStorage->Storage()->SetStorageIdL( *id );
+                CleanupStack::PopAndDestroy();
+                }
+            else
+                {
+                IMPORT_DP_TXT("WARNING: BrandID has no value" );
+                User::Leave( KErrNotFound ); 
+                }
+            break;
+            }
+        case EBrandAppID:
+            {
+            if( aNode->HasChildNodes() )
+                {
+                HBufC* id = NodeTextLC( aNode );
+                iStorage->Storage()->SetApplicationIdL( *id );
+                CleanupStack::PopAndDestroy();
+                }
+            else
+                {
+                IMPORT_DP_TXT("WARNING: ApplicationID has no value" );
+                User::Leave( KErrNotFound ); 
+                }
+            break;
+            }
+        case EBrandLanguage:
+            {
+            if( aNode->HasChildNodes() )
+                {
+                TInt lang = ELangTest;
+                TRAPD( err, lang = NodeIntL( aNode ) );
+                if( err )
+                    {
+                    // not a number. Check if language is "SC"
+                    HBufC* langBuf = NodeTextLC( aNode );
+                    TPtr langText( langBuf->Des() );
+                    langText.UpperCase();
+                    if( 0 != langText.CompareC( KDefaultLanguage ) ) 
+                        {
+                        IMPORT_DP_TXT("ERROR: Language field has invalid value (has to be a number or 'SC')" );
+                        User::Leave( KErrArgument );
+                        }
+                    CleanupStack::PopAndDestroy( langBuf );
+                    }
+                iStorage->Storage()->SetLanguageL( (TLanguage)lang );
+                }
+            else
+                {
+                IMPORT_DP_TXT("WARNING: Language field has no value" );
+                User::Leave( KErrNotFound ); 
+                }
+            break;
+            }
+        case EBrandVersion:
+            {
+            if( aNode->HasChildNodes() )
+                {
+                iStorage->Storage()->SetVersion( NodeIntL( aNode ) );
+                }
+            else
+                {
+                IMPORT_DP_TXT("WARNING: Version field has no value" );
+                User::Leave( KErrNotFound ); 
+                }
+            break;
+            }
+        case EBrandElement:
+            {
+            if( aNode->HasChildNodes() )
+                {
+                iStorage->Storage()->AppendElement( ParseBrandElementL( aNode ) );
+                }
+            else
+                {
+                IMPORT_DP_TXT("WARNING: Empty <element> tag found" );
+                User::Leave( KErrNotFound ); 
+                }
+            break;
+            }
+        case EBrandUnknown: // flowthrough
+        default:
+            {
+            TPtrC ptr( aNode->NodeName() );
+            IMPORT_DP( D_IMPORT_LIT("WARNING: Unknown XML tag encountered: <%S>"), &ptr );
+            break;
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CBSImportXMLParser::SolveTagTypeL
+// ---------------------------------------------------------------------------
+//
+CBSImportXMLParser::TXMLBaseTagTypes CBSImportXMLParser::SolveTagTypeL( CMDXMLNode* aNode )
+    {
+    TPtrC node( aNode->NodeName() );
+    if( 0 == node.CompareF( KBrandElementTag ) )
+        return EBrandElement;
+    
+    if( 0 == node.CompareF( KBrandIDTag ) )
+        return EBrandID;
+
+    if( 0 == node.CompareF( KBrandLanguageTag ) )
+        return EBrandLanguage;
+
+    if( 0 == node.CompareF( KBrandVersionTag ) )
+        return EBrandVersion;
+    
+    if( 0 == node.CompareF( KBrandAppIdTag ) )
+        return EBrandAppID;
+    
+    return EBrandUnknown;
+    }
+
+// ---------------------------------------------------------------------------
+// CBSImportXMLParser::ParseBrandElementL
+// ---------------------------------------------------------------------------
+//
+MBSElement* CBSImportXMLParser::ParseBrandElementL( CMDXMLNode* aNode )
+    {
+    if( !aNode->HasChildNodes() || 
+        0 != aNode->NodeName().CompareC( KBrandElementTag ))
+        {
+        // invalid element block
+        User::Leave( KErrCorrupt );
+        }
+    
+    // Check <element> tag attributes
+    CMDXMLElement* elNode = (CMDXMLElement*)(aNode);
+    TInt elType( KErrNotFound );
+    HBufC8* elID = NULL;
+    TInt attrNum = elNode->NumAttributes();
+    for( TInt i = 0; i < attrNum; i++ )
+        {
+        TPtrC name;
+        TPtrC value;
+        elNode->AttributeDetails( i, name, value );
+        
+        // <element ... type="xxx" ...>
+        if( 0 == name.CompareC( KElementTypeName ) ) 
+            {
+            elType = SolveElementType( value );
+            }
+        // <element ... id="xxx" ...>
+        else if( 0 == name.CompareC( KElementTypeID ) && !elID )
+            {
+            elID = HBufC8::NewL( value.Length() );
+            CleanupStack::PushL( elID );
+            TPtr8 ptrID( elID->Des() );
+            CnvUtfConverter::ConvertFromUnicodeToUtf8( ptrID, value );
+            }
+        }
+    
+    // Verify type
+    if( elType == KErrNotFound )
+        {
+        // Element type missing!
+        IMPORT_DP_TXT("ERROR: Element's 'type' attribute is missing!" );
+        User::Leave( KErrCorrupt );
+        }
+    
+    // Create empty ID if element didn't have one
+    if( !elID )
+        {
+        elID = KNullDesC8().AllocL();
+        CleanupStack::PushL( elID );
+        }
+    
+    // Parse element according to type
+    MBSElement* elem = NULL;
+    switch( elType )
+        {
+        case EBSInt:
+            {
+            TInt intValue;
+            TRAPD( err, DoParseIntegerL( elNode, intValue ) )
+            if( !err )
+                {
+                TPtr8 ptr( elID->Des() );
+                // Codescanner warning: neglected to put variable on cleanup stack (id:35)
+                // This method cannot leave after this line
+                elem = BSElementFactory::CreateBSElementL( ptr, EBSInt, intValue ); // CSI: 35 # See above
+                }
+            else
+                {
+                IMPORT_DP_TXT("ERROR: Invalid value in integer element!" );
+                User::Leave( err );
+                }
+            break;
+            }
+        case EBSFile:
+            {
+            HBufC* text = NULL;
+            TRAPD( err, DoParseFileL( elNode, text ) )
+            if( !err )
+                {
+                TPtr8 ptr( elID->Des() );
+                CleanupStack::PushL( text );
+                elem = BSElementFactory::CreateBSElementL( ptr, EBSFile, *text );
+                CleanupStack::PopAndDestroy( text );
+                }
+            else
+                {
+                IMPORT_DP_TXT("ERROR: Invalid value in file element!" );
+                User::Leave( err );
+                }
+
+            break;
+            }
+        case EBSBuffer:
+        case EBSText:
+            {
+            HBufC* text = NULL;
+            TRAPD( err, DoParseTextL( elNode, text ) )
+            if( !err )
+                {
+                TPtr8 ptr( elID->Des() );
+                CleanupStack::PushL( text );
+                
+                if( EBSText == elType ) // 16-bit descriptor
+                    {
+                    // Element takes ownership of text
+                    elem = BSElementFactory::CreateBSElementL( ptr, EBSText, *text );
+                    }
+                else // EBuffer: 8-bit descriptor
+                    {
+                    // convert to 8-bit
+                    HBufC8* conv = HBufC8::NewLC( text->Length() );
+                    TPtr8 ptrconv( conv->Des() );
+                    CnvUtfConverter::ConvertFromUnicodeToUtf8( ptrconv, *text );
+                    elem = BSElementFactory::CreateBSElementL( ptr, EBSBuffer, *conv );
+                    CleanupStack::PopAndDestroy( conv );
+                    }
+                CleanupStack::PopAndDestroy( text );
+                }
+            else
+                {
+                // Error parsing text element
+                IMPORT_DP_TXT("ERROR: Invalid value in text element!" );
+                User::Leave( err );
+                }
+            break;
+            }
+        case EBSList:
+            {
+            RBSObjOwningPtrArray<MBSElement> elementArray;
+            CleanupClosePushL( elementArray );
+            TRAPD( err, DoParseListL( aNode, elementArray ) );
+            if( !err )
+                {
+                // Create list element
+                TPtr8 ptr( elID->Des() );
+                // Codescanner warning: neglected to put variable on cleanup stack (id:35)
+                // This method cannot leave after this line
+                elem = BSElementFactory::CreateBSElementL( ptr, EBSList, elementArray ); // CSI: 35 # See above
+                CleanupStack::Pop(); // elementArray
+                }
+            else
+                {
+                IMPORT_DP_TXT("ERROR: List element parse failed!" );
+                User::Leave( err );
+                }
+            break;
+            }
+        case EBSBitmap:
+            {
+            CBSBitmap* bitmap = NULL;
+            TRAPD( err, DoParseBitmapL( elNode, bitmap ) )
+            if( !err )
+                {
+                CleanupStack::PushL( bitmap );
+                // Create list element
+                TPtr8 ptr( elID->Des() );
+                elem = BSElementFactory::CreateBSElementL( ptr, EBSBitmap, bitmap );
+                CleanupStack::Pop( bitmap );
+                }
+            break;
+            }
+        default:
+            {
+            // Invalid element type
+            break;
+            }
+        }
+
+    // return parsed element
+    CleanupStack::PopAndDestroy( elID );
+    return elem;
+    }
+
+// ---------------------------------------------------------------------------
+// CBSImportXMLParser::SolveElementType
+// ---------------------------------------------------------------------------
+//
+TInt CBSImportXMLParser::SolveElementType( const TDesC& aType )
+    {
+    if( 0 == aType.CompareC( KElementTypeList ) )
+        return EBSList;
+
+    if( 0 == aType.CompareC( KElementTypeBitmap ) )
+        return EBSBitmap;
+
+    if( 0 == aType.CompareC( KElementTypeBuffer ) )
+        return EBSBuffer;
+
+    if( 0 == aType.CompareC( KElementTypeInt ) )
+        return EBSInt;
+    
+    if( 0 == aType.CompareC( KElementTypeText ) )
+        return EBSText;
+    
+    if( 0 == aType.CompareC( KElementTypeFile ) )
+        return EBSFile;
+    
+    return KErrNotFound;
+    }
+
+// ---------------------------------------------------------------------------
+// CBSImportXMLParser::DoParseIntegerL
+// ---------------------------------------------------------------------------
+//
+void CBSImportXMLParser::DoParseIntegerL( CMDXMLNode* aNode, TInt& aValue )
+    {
+    // Integer element has only one child element. e.g:
+    // <element_value>
+    //  12345
+    // </element_value>
+    //
+    CMDXMLNode* kidNode = aNode->FirstChild();
+    while( kidNode )
+        {
+        if( 0 == KElementValueTag().CompareC( kidNode->NodeName() ) )
+            {
+            aValue = NodeIntL( kidNode );
+            return;
+            }
+        kidNode = kidNode->NextSibling();
+        }
+    User::Leave( KErrNotFound );
+    }
+
+// ---------------------------------------------------------------------------
+// CBSImportXMLParser::DoParseTextL
+// ---------------------------------------------------------------------------
+//
+void CBSImportXMLParser::DoParseTextL( CMDXMLNode* aNode, HBufC*& aText )
+    {
+    // Text element has only one valuable child element. e.g:
+    // <element_value>
+    //  some important text
+    // </element_value>
+    //
+    CMDXMLNode* kidNode = SearchChild( aNode, KElementValueTag );
+    if( kidNode )
+        {
+        aText = NodeTextLC( kidNode );
+        CleanupStack::Pop( aText );
+        return;
+        }
+    
+    // didn't find a valid value
+    IMPORT_DP_TXT( "ERROR: Text element is missing it's value" );
+    User::Leave( KErrNotFound );
+    }
+
+// ---------------------------------------------------------------------------
+// CBSImportXMLParser::DoParseFileL
+// ---------------------------------------------------------------------------
+//
+void CBSImportXMLParser::DoParseFileL( CMDXMLNode* aNode, HBufC*& aText )
+    {
+    // File element has only one valuable text value element. e.g:
+    // <element_value>
+    //   <file_name> c:\data\file.txt </file_name>
+    // </element_value>
+    //
+    CMDXMLNode* kidNode = SearchChild( aNode, KElementValueTag );
+    if( kidNode )
+        {
+        // check <file_name> tag
+        CMDXMLNode* subKidNode = SearchChild( kidNode, KFileFileNameTag );
+        if( subKidNode )
+            {
+            // Get filename from tag
+            aText = NodeTextLC( subKidNode );
+            CleanupStack::Pop( aText );
+            return;
+            }
+        }
+
+    // didn't find a valid value
+    IMPORT_DP_TXT( "ERROR: File element is missing it's value" );
+    User::Leave( KErrNotFound );
+    }
+
+// ---------------------------------------------------------------------------
+// CBSImportXMLParser::DoParseListL
+// ---------------------------------------------------------------------------
+//
+void CBSImportXMLParser::DoParseListL( 
+    CMDXMLNode* aNode, 
+    RBSObjOwningPtrArray<MBSElement>& aElementArray )
+    {
+    // Scan trough elements inside this list element
+    // <element_value>
+    //  <element ...>
+    //   ...
+    //  </element>
+    //  <element ...>
+    //   ...
+    //  </element>
+    // </element_value>
+    //
+    CMDXMLNode* kidNode = SearchChild( aNode, KElementValueTag );
+    if( kidNode )
+        {
+        CMDXMLNode* subKidNode = kidNode->FirstChild();
+        while( subKidNode )
+            {
+            // verify that this really is <element> node.
+            if( 0 == subKidNode->NodeName().CompareC( KBrandElementTag ) )
+                {
+                MBSElement* el = ParseBrandElementL( subKidNode );
+                if( el )
+                    {
+                    aElementArray.Append( el );
+                    }
+                }
+            subKidNode = subKidNode->NextSibling();
+            }
+        }
+    else
+        {
+        // No elements found inside list!
+        IMPORT_DP_TXT( "ERROR: List element is missing it's value" );
+        User::Leave( KErrNotFound );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CBSImportXMLParser::DoParseBitmapL
+// ---------------------------------------------------------------------------
+//
+void CBSImportXMLParser::DoParseBitmapL( 
+    CMDXMLNode* aNode, 
+    CBSBitmap*& aBitmap )
+    {
+/// XSP MOD: added support for <bitmap_file_id>
+    // Bitmap element has 5 child elements. e.g:
+    // <element_value>
+    //  <bitmap_file_id>
+    //  <bitmap_id> 65 </bitmap_id>
+    //  <mask_id> 66 </mask_id>
+    //  <skin_id_major> 190 </skin_id_major>
+    //  <skin_id_minor> 191 </skin_id_minor>
+    // </element_value>
+    //
+    TInt bmpId = KErrNotFound;
+    TInt bmpMaskId = KErrNotFound;
+    TInt skinId = KErrNotFound;
+    TInt skinMaskId = KErrNotFound;
+    HBufC8* fileId = NULL;
+    
+    CMDXMLNode* kidNode = SearchChild( aNode, KElementValueTag );
+    if( kidNode )
+        {
+        CMDXMLNode* subKidNode = kidNode->FirstChild();
+        TInt readCheck = 0;
+        while( subKidNode )
+            {
+            TPtrC ptr = subKidNode->NodeName();
+            if( 0 == KBitmapIdTag().CompareC( subKidNode->NodeName() ) )
+                {
+                bmpId = NodeIntL( subKidNode );
+                readCheck |= 0x1;
+                }
+            else if( 0 == KBitmapMaskIdTag().CompareC( subKidNode->NodeName() ) )
+                {
+                bmpMaskId = NodeIntL( subKidNode );
+                readCheck |= 0x2;
+                }
+            else if( 0 == KBitmapSkinIdTag().CompareC( subKidNode->NodeName() ) )
+                {
+                skinId = NodeIntL( subKidNode );
+                readCheck |= 0x4;
+                }
+            else if( 0 == KBitmapSkinMaskIdTag().CompareC( subKidNode->NodeName() ) )
+                {
+                skinMaskId = NodeIntL( subKidNode );
+                readCheck |= 0x8;
+                }
+/// XSP MOD: added support for madatory KBitmapFileIdTag field                
+            else if( 0 == KBitmapFileIdTag().CompareC( subKidNode->NodeName() ) )
+                {
+                // Ignore following file id elements if 
+                // bitmap element has more than one of them.
+                if ( !fileId )
+                    {
+                    HBufC* tmp = NodeTextLC( subKidNode );
+                	fileId = CnvUtfConverter::ConvertFromUnicodeToUtf8L( *tmp );
+                	CleanupStack::PopAndDestroy( tmp );
+                	tmp = NULL;
+                    CleanupStack::PushL( fileId );
+                    readCheck |= 0x10;
+                    }
+                }
+
+            subKidNode = subKidNode->NextSibling();
+            }
+        
+        if( readCheck != 0x1F )/// XSP MOD:check that all 5 values were found
+            {
+            // Some bitmap elements are missing!
+            IMPORT_DP_TXT( "ERROR: Bitmap element is missing some mandatory values" );
+            User::Leave( KErrNotFound );
+            }
+        
+        // create bitmap
+        TPtrC8 pFileId( KNullDesC8 );
+        if ( fileId )
+            {
+            pFileId.Set( *fileId );
+            }
+        aBitmap = CBSBitmap::NewL( bmpId, bmpMaskId, skinId, skinMaskId, pFileId );
+        if ( fileId )
+            {
+            CleanupStack::PopAndDestroy( fileId );
+            fileId = NULL;
+            }
+        }
+    else
+        {
+        IMPORT_DP_TXT( "ERROR: Bitmap element is missing it's value" );
+        User::Leave( KErrNotFound );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CBSImportXMLParser::NodeTextLC
+// ---------------------------------------------------------------------------
+//
+HBufC* CBSImportXMLParser::NodeTextLC( CMDXMLNode* aNode )
+    {
+    CMDXMLNode* kidNode = aNode->FirstChild();
+    if( !kidNode )
+        {
+        // empty content
+        return KNullDesC().AllocLC();
+        }
+        
+    if( kidNode->HasChildNodes() )
+        {
+        // not a valid text element!
+        User::Leave( KErrCorrupt );        
+        }
+
+    HBufC* text = static_cast<CMDXMLText*>(kidNode)->Data().AllocL();
+    CleanupStack::PushL( text );
+    
+    // Remove extra characters from text
+    TPtr ptr( text->Des() );
+    AknTextUtils::StripCharacters( ptr, KCommonControlCharacters );
+    ptr.TrimAll();
+    
+    return text;
+    }
+
+// ---------------------------------------------------------------------------
+// CBSImportXMLParser::NodeIntL
+// ---------------------------------------------------------------------------
+//
+TInt CBSImportXMLParser::NodeIntL( CMDXMLNode* aNode )
+    {
+    CMDXMLNode* kidNode = aNode->FirstChild();
+    if( !kidNode || kidNode->HasChildNodes() )
+        {
+        // not a valid text element!
+        User::Leave( KErrCorrupt );        
+        }
+
+    TLex lex( static_cast<CMDXMLText*>(kidNode)->Data() );
+    TInt value;
+    User::LeaveIfError( lex.Val( value ) );
+    return value;
+    }
+
+// ---------------------------------------------------------------------------
+// CBSImportXMLParser::FindTag
+// ---------------------------------------------------------------------------
+//
+CMDXMLNode* CBSImportXMLParser::SearchChild( CMDXMLNode* aNode, const TDesC& aChildName )
+    {
+    if( aNode->HasChildNodes() )
+        {
+        CMDXMLNode* kidNode = aNode->FirstChild();
+        while( kidNode )
+            {
+            if( 0 == aChildName.CompareC( kidNode->NodeName() ) )
+                {
+                // found it
+                return kidNode;
+                }
+            kidNode = kidNode->NextSibling();
+            }
+        }
+    // not found
+    return NULL;
+    }
+
+// End of file