xml/xmldomandxpath/src/xmlenginedom/xmlengdomparser.cpp
changeset 0 e35f40988205
equal deleted inserted replaced
-1:000000000000 0:e35f40988205
       
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Implements methods for parsing XML data
       
    15 //
       
    16 
       
    17 #include <stdlib.h>
       
    18 
       
    19 #include <xml/dom/xmlengdomparser.h>
       
    20 #include <xml/dom/xmlengdocument.h>
       
    21 #include <xml/dom/xmlengerrors.h>
       
    22 #include <xml/utils/xmlengmem.h>
       
    23 #include <xml/utils/xmlengxestd.h>
       
    24 #include <stdapis/libxml2/libxml2_parser.h>
       
    25 #define PARSER_CTXT (static_cast<xmlParserCtxtPtr>(iInternal))
       
    26 
       
    27 // ---------------------------------------------------------------------------------------------
       
    28 // Default constructor
       
    29 // ---------------------------------------------------------------------------------------------
       
    30 //
       
    31 EXPORT_C RXmlEngDOMParser::RXmlEngDOMParser(): iInternal(NULL), iError(0), iImpl(NULL)
       
    32 	{
       
    33 	}
       
    34 
       
    35 // ---------------------------------------------------------------------------------------------
       
    36 // Opens parser
       
    37 // ---------------------------------------------------------------------------------------------
       
    38 //
       
    39 EXPORT_C TInt RXmlEngDOMParser::Open(RXmlEngDOMImplementation& aDOMImpl)
       
    40     {
       
    41     iImpl = &aDOMImpl;
       
    42     return KErrNone;
       
    43     };
       
    44 
       
    45 // ---------------------------------------------------------------------------------------------
       
    46 // Frees all allocated by parser resources.
       
    47 // ---------------------------------------------------------------------------------------------
       
    48 //
       
    49 EXPORT_C void RXmlEngDOMParser::Close()
       
    50     {
       
    51     Cleanup();
       
    52     iImpl = NULL;
       
    53     }
       
    54 // ---------------------------------------------------------------------------------------------
       
    55 // Builds DOM document from file. File is read by blocks of specified size, thus,
       
    56 // avoiding keeping in memory both file and DOM tree for it.
       
    57 //
       
    58 // @note Use RDOMPushParser for parsing large files.
       
    59 // @param aRFs File server session
       
    60 // @param aFileName File name
       
    61 // @return The created document
       
    62 // @see GetLastParsingError()
       
    63 // @leave KXmlEngErrParsing Parsing error
       
    64 // @leave KXmlEngErrWrongUseOfAPI OpenL() not previously called
       
    65 // @leave - One of the system-wide error codes
       
    66 // ---------------------------------------------------------------------------------------------
       
    67 //
       
    68 EXPORT_C RXmlEngDocument RXmlEngDOMParser::ParseFileL(
       
    69     RFs &aRFs,
       
    70     const TDesC& aFileName,
       
    71     TUint aChunkSize )
       
    72     {
       
    73     if  ( aChunkSize == 0 )
       
    74     	{
       
    75     	return ParseFileWithoutChunksL( aRFs, aFileName );
       
    76     	}
       
    77     
       
    78     RFile xmlFile;
       
    79     TInt res;
       
    80     
       
    81     User::LeaveIfError(xmlFile.Open(aRFs, aFileName, EFileRead | EFileShareReadersOnly));
       
    82     CleanupClosePushL(xmlFile);
       
    83     
       
    84     RBuf8 buffer;
       
    85     if (aChunkSize < (KMaxTInt/2))
       
    86         {
       
    87         buffer.CreateL(aChunkSize);
       
    88         }
       
    89     else
       
    90         {
       
    91         User::Leave(KErrArgument);
       
    92         }
       
    93     CleanupClosePushL(buffer);
       
    94     
       
    95    	User::LeaveIfError(xmlFile.Read(buffer,aChunkSize));
       
    96 	TUint length;
       
    97 	
       
    98 	do
       
    99 		{
       
   100 		ParseChunkL(buffer);
       
   101 		res = xmlFile.Read(buffer, aChunkSize);
       
   102 		if(res)
       
   103 		    {
       
   104 		    Close();
       
   105 		    User::Leave(res);
       
   106 		    }
       
   107 		length = buffer.Length();
       
   108 		} while (length);
       
   109 		
       
   110 	CleanupStack::PopAndDestroy(&buffer);
       
   111     CleanupStack::PopAndDestroy(&xmlFile);
       
   112     return FinishL();
       
   113     }
       
   114 // ---------------------------------------------------------------------------------------------
       
   115 // Builds DOM document from file.
       
   116 // @see ParseFileL(RFs,TDesC&,TUint)
       
   117 // ---------------------------------------------------------------------------------------------
       
   118 //
       
   119 EXPORT_C RXmlEngDocument RXmlEngDOMParser::ParseFileL(
       
   120     const TDesC& aFileName,
       
   121     TUint aChunkSize )
       
   122     {
       
   123     RFs aRFs;
       
   124     User::LeaveIfError(aRFs.Connect());
       
   125     CleanupClosePushL(aRFs);
       
   126     RXmlEngDocument doc = ParseFileL(aRFs, aFileName, aChunkSize);
       
   127     CleanupStack::PopAndDestroy(); // aRFs
       
   128     return doc;
       
   129     }
       
   130 // ---------------------------------------------------------------------------------------------
       
   131 // Pushes new data from buffer to DOM parser.
       
   132 // Parsing is performed synchronously; method returns as soon as block is parsed.
       
   133 //
       
   134 // Buffer contents is not needed for further parsing after this method.
       
   135 // Method may leave with KErrXMLSyntax code or one of general codes (e.g. KErrNoMemory)
       
   136 // ---------------------------------------------------------------------------------------------
       
   137 //
       
   138 EXPORT_C void RXmlEngDOMParser::ParseChunkL(
       
   139     const TDesC8& aBuffer )
       
   140     {
       
   141     if(!iImpl)
       
   142         {
       
   143         User::Leave(KXmlEngErrWrongUseOfAPI);
       
   144         }
       
   145     
       
   146     xmlParserCtxtPtr ctxt = PARSER_CTXT;
       
   147     if(!ctxt)
       
   148         {
       
   149         iError = KErrNone;
       
   150         // First call after reset or parser creation
       
   151         ctxt = xmlCreatePushParserCtxt(
       
   152                             NULL , /* default set of callbacks is used (for building tree) */
       
   153                             NULL , /* save as userData */
       
   154                             (const char*)aBuffer.Ptr(),
       
   155                             aBuffer.Size(),
       
   156                             NULL /* filename or URI */);
       
   157         if(!ctxt)
       
   158             {
       
   159             XmlEngOOMTestL();
       
   160             };
       
   161         iInternal = ctxt;    
       
   162         xmlCtxtUseOptions(ctxt, XML_PARSE_DTDLOAD | XML_PARSE_NOENT | XML_PARSE_NODICT);
       
   163         iError = xmlParseChunk(ctxt,
       
   164                       ""   , /* char* data */
       
   165                       0    , /* int size */
       
   166                       0);    /* flag: 0 - not the last chunk */
       
   167         }
       
   168     else
       
   169         {
       
   170         iError = xmlParseChunk(ctxt,
       
   171                       (char*)aBuffer.Ptr(), /* char* data */
       
   172                       (TInt)aBuffer.Size(), /* int size */
       
   173                       0);                   /* flag: 0 - not the last chunk */
       
   174         }
       
   175     if(iError != XML_ERR_OK && ctxt->lastError.level == XML_ERR_FATAL)
       
   176         {
       
   177         Cleanup();        
       
   178         XmlEngOOMTestL();
       
   179         User::Leave(KXmlEngErrParsing);
       
   180         }
       
   181     }
       
   182 
       
   183 // ---------------------------------------------------------------------------------------------
       
   184 // Returns constructed document after the last block of XML document is parsed.
       
   185 // Ownership over returned RXmlEngDocument object is transferred to the caller of the method.
       
   186 // ---------------------------------------------------------------------------------------------
       
   187 //
       
   188 EXPORT_C RXmlEngDocument RXmlEngDOMParser::FinishL()
       
   189     {
       
   190     if(!iImpl)
       
   191         {
       
   192         User::Leave(KXmlEngErrWrongUseOfAPI);
       
   193         }
       
   194     
       
   195     xmlDocPtr doc;
       
   196     xmlParserCtxtPtr ctxt = PARSER_CTXT;
       
   197     
       
   198     if(!ctxt)
       
   199         {
       
   200         User::Leave(KXmlEngErrWrongUseOfAPI);
       
   201         }
       
   202     
       
   203     iError = xmlParseChunk(ctxt,
       
   204                         NULL /* char* data */,
       
   205                         0    /* int size */,
       
   206                         1    /* flag: 1 - the last chunk */);
       
   207     
       
   208     if(iError != XML_ERR_OK  && ctxt->lastError.level == XML_ERR_FATAL)
       
   209         {
       
   210         Cleanup();
       
   211         XmlEngOOMTestL();        
       
   212         User::Leave(KXmlEngErrParsing);
       
   213         }
       
   214         
       
   215     doc = ctxt->myDoc;
       
   216     ctxt->myDoc = NULL;
       
   217     xmlFreeParserCtxt(ctxt);
       
   218     iInternal = NULL;
       
   219     RXmlEngDocument rdoc;
       
   220     rdoc.OpenL(*iImpl,doc);
       
   221     return rdoc;
       
   222     }
       
   223 
       
   224 // ---------------------------------------------------------------------------------------------
       
   225 // Parses XML data from memory buffer and builds DOM RXmlEngDocument
       
   226 //
       
   227 // May leave with KXmlEngErrParsing code
       
   228 // ---------------------------------------------------------------------------------------------
       
   229 //
       
   230 EXPORT_C RXmlEngDocument RXmlEngDOMParser::ParseL(
       
   231     const TDesC8& aBuffer )
       
   232     {
       
   233     if(!iImpl)
       
   234         {
       
   235         User::Leave(KXmlEngErrWrongUseOfAPI);
       
   236         }
       
   237     
       
   238     TInt code = 0;
       
   239     xmlDocPtr tree = xmlSAXParseDoc(
       
   240                         NULL, 
       
   241                         (xmlChar*) aBuffer.Ptr(), 
       
   242                         aBuffer.Size(), 
       
   243                         0, 
       
   244                         &code /* errorCode */);
       
   245     TEST_OOM_FLAG;
       
   246     iError = code;
       
   247     if(!tree)
       
   248         XmlEngLeaveL(KXmlEngErrParsing);
       
   249     RXmlEngDocument doc;
       
   250     doc.OpenL(*iImpl,tree);
       
   251     return doc;
       
   252     }
       
   253 // ---------------------------------------------------------------------------------------------
       
   254 // Return last parsing error
       
   255 // ---------------------------------------------------------------------------------------------
       
   256 //
       
   257 EXPORT_C TInt RXmlEngDOMParser::GetLastParsingError()
       
   258     {
       
   259     return iError;
       
   260     }
       
   261 // ---------------------------------------------------------------------------------------------
       
   262 // Parses XML file and builds DOM RXmlEngDocument without usage of chunks
       
   263 //
       
   264 // May leave with KXmlEngErrParsing code (besides system I/O error codes)
       
   265 // ---------------------------------------------------------------------------------------------
       
   266 //
       
   267 RXmlEngDocument RXmlEngDOMParser::ParseFileWithoutChunksL(
       
   268     RFs &aRFs, 
       
   269     const TDesC& aFileName )
       
   270     {
       
   271     TInt size;
       
   272     RFile xmlFile;
       
   273         
       
   274     // Read file
       
   275     User::LeaveIfError(xmlFile.Open(aRFs, aFileName, EFileRead | EFileShareReadersOnly));
       
   276     CleanupClosePushL(xmlFile);
       
   277     User::LeaveIfError(xmlFile.Size(size));
       
   278     HBufC8* buffer = HBufC8::NewLC(size);
       
   279     TPtr8 bufferPtr = buffer->Des();
       
   280     User::LeaveIfError(xmlFile.Read(bufferPtr, size));
       
   281 
       
   282     RXmlEngDocument doc = ParseL(bufferPtr);
       
   283 
       
   284     CleanupStack::PopAndDestroy(buffer);
       
   285     CleanupStack::PopAndDestroy(&xmlFile);
       
   286     return doc;
       
   287     }
       
   288 
       
   289 // ---------------------------------------------------------------------------------------------
       
   290 // Cleanup internal data
       
   291 // ---------------------------------------------------------------------------------------------
       
   292 //
       
   293 void RXmlEngDOMParser::Cleanup()
       
   294     {
       
   295     xmlParserCtxtPtr ctxt = PARSER_CTXT;
       
   296     // free all allocated resources
       
   297     if(ctxt)
       
   298         {
       
   299         if(ctxt->myDoc)
       
   300             xmlFreeDoc(ctxt->myDoc);
       
   301         xmlFreeParserCtxt(ctxt);
       
   302         iInternal = NULL;
       
   303         }
       
   304     }
       
   305