xml/xmldomandxpath/src/xmlenginedom/xmlengdocument.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 // Document node functions
       
    15 //
       
    16 
       
    17 #include <stdlib.h>
       
    18 #include <bafl/sysutil.h>
       
    19 
       
    20 #include <xml/utils/xmlengmem.h>
       
    21 #include <xml/dom/xmlengdocument.h>
       
    22 #include "xmlengfileoutputstream.h"
       
    23 #include <xml/dom/xmlengerrors.h>
       
    24 #include "xmlengownednodescontainer.h"
       
    25 #include "xmlengdomdefs.h"
       
    26 #include <xml/dom/xmlengdatacontainer.h>
       
    27 #include <xml/dom/xmlengbinarycontainer.h>
       
    28 #include <xml/dom/xmlengchunkcontainer.h>
       
    29 #include <xml/dom/xmlengfilecontainer.h>
       
    30 #include <xml/dom/xmlengdataserializer.h>
       
    31 #include <xml/dom/xmlengelement.h>
       
    32 #include <xml/dom/xmlengcdatasection.h>
       
    33 #include <xml/dom/xmlengprocessinginstruction.h>
       
    34 #include <xml/dom/xmlengcomment.h>
       
    35 #include <xml/dom/xmlengdocumentfragment.h>
       
    36 #include <xml/dom/xmlengentityreference.h>
       
    37 #include <xml/dom/xmlengoutputstream.h>
       
    38 #include <xml/dom/xmlengdomimplementation.h>
       
    39 
       
    40 #include <xml/utils/xmlengxestrings.h>
       
    41 #include <stdapis/libxml2/libxml2_parser.h>
       
    42 #include <stdapis/libxml2/libxml2_xmlio.h>
       
    43 #include "libxml2_xmlsave_private.h"
       
    44 #include "libxml2_tree_private.h"
       
    45 #include "libxml2_globals_private.h"
       
    46 #include <stdapis/libxml2/libxml2_parserinternals.h>
       
    47 #include "libxml2_valid_private.h"
       
    48 
       
    49 int XMLCALL NodeFilterCallback(void* aFilter, xmlNodePtr aNode);
       
    50 void LibxmlDocumentCleanup(TAny* aAttrPtr);
       
    51 void LibxmlNodeCleanup(TAny* aNodePtr);
       
    52 
       
    53 // -----------------------------------------------------------------------------------------------
       
    54 // "Write" callback registered in libxml2 for using with custom output stream
       
    55 // during serializing XML. 
       
    56 // 
       
    57 // This callback is invoked repeatedly during serialization; 
       
    58 // when whole data is serialized the "Close" callback is called for a output stream.
       
    59 //
       
    60 // @param aContext  User data that was used during callback registration 
       
    61 //                  XML Engine uses here a pointer to MXmlEngOutputStream provided by client app
       
    62 // @param aBuffer   Buffer where the next part of serialized XML has just been written
       
    63 // @param aLen      Number of bytes written to the buffer
       
    64 // 
       
    65 // The callback is prototyped by libxml2's type declaration:
       
    66 // @code
       
    67 //     typedef int (*xmlOutputWriteCallback) (void* context, const char* buffer, int len);
       
    68 // @endcode
       
    69 // -----------------------------------------------------------------------------------------------
       
    70 //
       
    71 int XmlEngineIOWriteCallback(void* aContext, const char* aBuffer, int aLen)
       
    72     {
       
    73     MXmlEngOutputStream* stream = reinterpret_cast<MXmlEngOutputStream*>(aContext);
       
    74     return stream->Write(TPtrC8(reinterpret_cast<TUint8*>(const_cast<char*>(aBuffer)), aLen));
       
    75     }
       
    76 
       
    77 // -----------------------------------------------------------------------------------------------
       
    78 // "Close" callback registered in libxml2 for using with custom output stream
       
    79 // during serializing XML. 
       
    80 // 
       
    81 // This callback is invoked after the last "Write" callback.
       
    82 // 
       
    83 // @param aContext  User data that was used during callback registration 
       
    84 //                  XML Engine uses here a pointer to MXmlEngOutputStream provided by client app
       
    85 // 
       
    86 // The callback is prototyped by libxml2's type declaration:
       
    87 // @code
       
    88 //     typedef int (*xmlOutputCloseCallback) (void* context);
       
    89 // @endcode
       
    90 // -----------------------------------------------------------------------------------------------
       
    91 //
       
    92 int XmlEngineIOCloseCallback(void* aContext)
       
    93     {
       
    94     MXmlEngOutputStream* stream = reinterpret_cast<MXmlEngOutputStream*>(aContext);
       
    95     return stream->Close();
       
    96     }
       
    97 
       
    98 // -----------------------------------------------------------------------------------------------
       
    99 // Data serialization callback registered in libxml2 for custom node data serialization.
       
   100 // 
       
   101 // This callback is invoked whenever EText node contains data of given length, for example
       
   102 // binary data or data stored in a memory chunk.
       
   103 // 
       
   104 // @param aContext  Data serializer provided by client app
       
   105 // @param aNode  Node that contains data to be serialized 
       
   106 // -----------------------------------------------------------------------------------------------
       
   107 //
       
   108 unsigned char* DataSerializationCallback(void* aContext, xmlNodePtr aNode, int* aWritten)
       
   109   	{
       
   110   	TPtrC8 ptr(KNullDesC8());
       
   111 	MXmlEngDataSerializer* dataSerializer = reinterpret_cast<MXmlEngDataSerializer*>(aContext);	
       
   112 	TRAPD(err, ptr.Set(dataSerializer->SerializeDataL(TXmlEngNode(aNode))));
       
   113 	if(err)
       
   114 	    {
       
   115 	    *aWritten = err;
       
   116 	    return NULL;
       
   117 	    }
       
   118 	    
       
   119     *aWritten = ptr.Size();
       
   120     return (unsigned char*)ptr.Ptr();
       
   121 	}
       
   122 
       
   123 #define LIBXML_DOC (static_cast<xmlDocPtr>(iInternal))
       
   124 
       
   125 // -------------------------------------------------------------------------------------------------------
       
   126 // Closes the RXmlEngDocument object: the whole document tree is destroyed and all memory is released.
       
   127 // 
       
   128 // All owned by the document nodes (created by it or unlinked from the document and not linked elsewhere)
       
   129 // are destroyed too.
       
   130 // -------------------------------------------------------------------------------------------------------
       
   131 //
       
   132 EXPORT_C void RXmlEngDocument::Close()
       
   133     {
       
   134     if(LIBXML_DOC)
       
   135         {
       
   136         LibxmlDocumentCleanup(LIBXML_DOC);
       
   137         iInternal = NULL;
       
   138         }
       
   139     }
       
   140 
       
   141 EXPORT_C void RXmlEngDocument::OpenL(RXmlEngDOMImplementation& aDOMImpl)
       
   142     {
       
   143     iImpl = &aDOMImpl;
       
   144     xmlDocPtr doc = xmlNewDoc(NULL);
       
   145     OOM_IF_NULL(doc);
       
   146     iInternal = doc;
       
   147     CleanupClosePushL(*this);
       
   148     InitOwnedNodeListL();
       
   149     CleanupStack::Pop();
       
   150     };
       
   151 	
       
   152 EXPORT_C void RXmlEngDocument::OpenL(RXmlEngDOMImplementation& aDOMImpl, void* aInternal)
       
   153     {
       
   154     iImpl = &aDOMImpl;
       
   155     iInternal = aInternal;
       
   156     CleanupStack::PushL(TCleanupItem(LibxmlDocumentCleanup,(TAny*)LIBXML_DOC));
       
   157     InitOwnedNodeListL();
       
   158     CleanupStack::Pop();
       
   159     };
       
   160 
       
   161 EXPORT_C void RXmlEngDocument::OpenL(RXmlEngDOMImplementation& aDOMImpl, TXmlEngElement aRoot)
       
   162     {
       
   163     OpenL(aDOMImpl);
       
   164     xmlUnlinkNode(INTERNAL_NODEPTR(aRoot));
       
   165     xmlNodePtr node = xmlAddChild(LIBXML_NODE, INTERNAL_NODEPTR(aRoot));
       
   166     if(!node)
       
   167         {
       
   168         Close();
       
   169         OOM_HAPPENED;
       
   170         }
       
   171     };
       
   172 
       
   173 EXPORT_C TXmlEngDocumentFragment RXmlEngDocument::CreateDocumentFragmentL()
       
   174     {
       
   175     xmlNodePtr dfNode = xmlNewDocFragment(LIBXML_DOC);
       
   176     OOM_IF_NULL(dfNode);
       
   177     TXmlEngNode df(dfNode);
       
   178     TakeOwnership(df);
       
   179     return df.AsDocumentFragment();
       
   180     }
       
   181     
       
   182 // -----------------------------------------------------------------------------------------------
       
   183 // Serializes document tree into a file
       
   184 //
       
   185 // @param aFileName    A file name (with path)
       
   186 // @return            Number of byte written
       
   187 // @note
       
   188 // Method may leave with KErrNoMemory or KErrGeneral codes.
       
   189 // -----------------------------------------------------------------------------------------------
       
   190 //
       
   191 EXPORT_C TInt RXmlEngDocument::SaveL( const TDesC& aFileName, 
       
   192 							    TXmlEngNode aRoot,
       
   193 							    const TXmlEngSerializationOptions& aSaveOptions ) const
       
   194     {
       
   195     if(IsNull())
       
   196     	{
       
   197     	User::Leave(KXmlEngErrWrongUseOfAPI);
       
   198     	}
       
   199     if (!aFileName.Length())
       
   200         {
       
   201         WRONG_USE_OF_API;
       
   202         }    
       
   203     RFs fs;
       
   204     User::LeaveIfError(fs.Connect());
       
   205     CleanupClosePushL(fs);
       
   206     TInt size = SaveL(fs, aFileName, aRoot, aSaveOptions);
       
   207     CleanupStack::PopAndDestroy(&fs);
       
   208     return size;
       
   209     }
       
   210 
       
   211 // -----------------------------------------------------------------------------------------------
       
   212 // Serializes node to a file
       
   213 // -----------------------------------------------------------------------------------------------
       
   214 //
       
   215 EXPORT_C TInt RXmlEngDocument::SaveL( RFs& aRFs,
       
   216     							const TDesC& aFileName, 
       
   217     							TXmlEngNode aRoot,
       
   218     							const TXmlEngSerializationOptions& aSaveOptions ) const
       
   219     {
       
   220     if(IsNull())
       
   221     	{
       
   222     	User::Leave(KXmlEngErrWrongUseOfAPI);
       
   223     	}    
       
   224     if (!aFileName.Length())
       
   225         {
       
   226         WRONG_USE_OF_API;
       
   227         }  
       
   228     TInt size = -1;        
       
   229     RFile outputFile;
       
   230     
       
   231     User::LeaveIfError(outputFile.Replace(aRFs,aFileName,EFileShareAny|EFileWrite));
       
   232     CleanupClosePushL(outputFile);
       
   233         
       
   234     TXmlEngFileOutputStream outputStream(outputFile,aRFs);
       
   235     RBuf8 buffer;
       
   236     // TString is null so it does not need to be closed
       
   237     size = SaveNodeL( INTERNAL_NODEPTR(aRoot), buffer, &outputStream, aSaveOptions);
       
   238     User::LeaveIfError(outputStream.CheckError());
       
   239     CleanupStack::PopAndDestroy(&outputFile);
       
   240     
       
   241     return size;   
       
   242     }
       
   243 
       
   244 // -----------------------------------------------------------------------------------------------
       
   245 // Serializes a document tree into provided output stream, which supports
       
   246 // progressive writing of data.
       
   247 //
       
   248 // @param aStream  An output stream to write serialized DOM tree
       
   249 // @param aRoot Root node to be serialized
       
   250 // @param aSaveOptions Options that control how serialization is performed
       
   251 // @see MXmlEngOutputStream
       
   252 // -----------------------------------------------------------------------------------------------
       
   253 //
       
   254 EXPORT_C TInt RXmlEngDocument::SaveL( MXmlEngOutputStream& aStream,
       
   255 								TXmlEngNode aRoot,
       
   256 								const TXmlEngSerializationOptions& aSaveOptions ) const
       
   257     {
       
   258 	RBuf8 placeHolder;
       
   259     if(IsNull())
       
   260     	{
       
   261     	User::Leave(KXmlEngErrWrongUseOfAPI);
       
   262     	}
       
   263 	if(!&aStream)
       
   264 		{
       
   265 		User::Leave(KXmlEngErrWrongUseOfAPI);
       
   266 		}
       
   267 	
       
   268 	return SaveNodeL( aRoot, placeHolder, &aStream, aSaveOptions );   
       
   269     }
       
   270 
       
   271 
       
   272 // -----------------------------------------------------------------------------------------------
       
   273 // Serializes DOM subtree into memory buffer
       
   274 // 
       
   275 // @param  aBuffer  A buffer to write output data.
       
   276 // @param  aRoot    Root note to serialize.
       
   277 // @param  aSaveOptions Various options that control how serialization is performed
       
   278 //
       
   279 // @return Number of bytes in updated buffer
       
   280 //
       
   281 // Buffer contents is freed prior serialization
       
   282 // -----------------------------------------------------------------------------------------------
       
   283 //
       
   284 EXPORT_C TInt RXmlEngDocument::SaveL( RBuf8& aBuffer, 
       
   285     							TXmlEngNode aRoot, 
       
   286     							const TXmlEngSerializationOptions& aSaveOptions ) const
       
   287     {
       
   288     if(IsNull())
       
   289     	{
       
   290     	User::Leave(KXmlEngErrWrongUseOfAPI);
       
   291     	}  
       
   292     return SaveNodeL(aRoot, aBuffer, NULL, aSaveOptions);
       
   293     }
       
   294    
       
   295 // -----------------------------------------------------------------------------------------------
       
   296 // Creates complete copy of the document
       
   297 //
       
   298 // @return Complete copy of the document tree
       
   299 // -----------------------------------------------------------------------------------------------
       
   300 //
       
   301 EXPORT_C RXmlEngDocument RXmlEngDocument::CloneDocumentL() const
       
   302     {
       
   303     xmlDocPtr doc = NULL;
       
   304     if (iInternal)
       
   305         {
       
   306         doc = xmlCopyDoc(LIBXML_DOC, 1);
       
   307         OOM_IF_NULL(doc); 
       
   308         }
       
   309     RXmlEngDocument retDoc(doc);
       
   310     CleanupStack::PushL(TCleanupItem(LibxmlDocumentCleanup,(TAny*)doc));
       
   311     retDoc.InitOwnedNodeListL();
       
   312     CleanupStack::Pop();
       
   313     return retDoc;
       
   314     }
       
   315 
       
   316 // -----------------------------------------------------------------------------------------------
       
   317 // Creates new element from specific namespace to be a root of the document tree.
       
   318 //
       
   319 // Any existing document element of the document is destroyed
       
   320 //@return A new root element
       
   321 // -----------------------------------------------------------------------------------------------
       
   322 //
       
   323 EXPORT_C TXmlEngElement RXmlEngDocument::CreateDocumentElementL( const TDesC8& aName, 
       
   324 												     const TDesC8& aNamespaceUri, 
       
   325 												     const TDesC8& aPrefix )
       
   326     {
       
   327     TXmlEngElement newE = CreateElementL(aName, aNamespaceUri, aPrefix);
       
   328     SetDocumentElement(newE);
       
   329     return newE;
       
   330     }
       
   331 
       
   332 // -----------------------------------------------------------------------------------------------
       
   333 // Replaces (and closes) document element with another one
       
   334 //
       
   335 // New document element is added as the last child to the document node
       
   336 // @param aNewDocElement New document tree
       
   337 // @note Use TXmlEngElement::ReconcileNamespacesL() on the new document element
       
   338 //      if it or its descendants can contain references to namespace declarations
       
   339 //      out of the element
       
   340 // -----------------------------------------------------------------------------------------------
       
   341 //
       
   342 EXPORT_C void RXmlEngDocument::SetDocumentElement( TXmlEngElement aNewDocElement )
       
   343     {
       
   344     TXmlEngElement oldE = DocumentElement();
       
   345     if (oldE.NotNull())
       
   346         {
       
   347         oldE.Remove();
       
   348         }
       
   349     if(aNewDocElement.ParentNode().IsNull())
       
   350         aNewDocElement.OwnerDocument().RemoveOwnership(aNewDocElement);
       
   351     //
       
   352     xmlNodePtr child =  xmlAddChild(LIBXML_NODE, INTERNAL_NODEPTR(aNewDocElement));
       
   353     }
       
   354 
       
   355 
       
   356 // -----------------------------------------------------------------------------------------------
       
   357 // @return A document element - the top-most element in the document tree
       
   358 // -----------------------------------------------------------------------------------------------
       
   359 //
       
   360 EXPORT_C TXmlEngElement RXmlEngDocument::DocumentElement() const
       
   361     {
       
   362     return TXmlEngElement(xmlDocGetRootElement(LIBXML_DOC));
       
   363     }
       
   364 
       
   365 // -----------------------------------------------------------------------------------------------
       
   366 // @return Encoding of the source XML data.
       
   367 // -----------------------------------------------------------------------------------------------
       
   368 //
       
   369 EXPORT_C TPtrC8 RXmlEngDocument::XmlEncoding() const
       
   370     {
       
   371     return ((TXmlEngConstString)CAST_XMLCHAR_TO_DOMSTRING(LIBXML_DOC->encoding)).PtrC8();
       
   372     }
       
   373 
       
   374 // -----------------------------------------------------------------------------------------------
       
   375 // @return Whether standalone="true" was specified in XML declaration in the source XML file.
       
   376 // -----------------------------------------------------------------------------------------------
       
   377 //
       
   378 EXPORT_C TBool RXmlEngDocument::IsStandalone() const
       
   379     {
       
   380     return LIBXML_DOC->standalone != 0;
       
   381     }
       
   382 
       
   383 // -----------------------------------------------------------------------------------------------
       
   384 // Sets 'standalone' attribute of XML declaration for a document
       
   385 // -----------------------------------------------------------------------------------------------
       
   386 //
       
   387 EXPORT_C void RXmlEngDocument::SetStandalone( TBool aStandalone )
       
   388     {
       
   389     LIBXML_DOC->standalone = aStandalone;
       
   390     }
       
   391 
       
   392 // -----------------------------------------------------------------------------------------------
       
   393 // @return Version number of XML taken from XML declaration
       
   394 // -----------------------------------------------------------------------------------------------
       
   395 //
       
   396 EXPORT_C TPtrC8 RXmlEngDocument::XmlVersion() const
       
   397     {
       
   398     return ((TXmlEngConstString)CAST_XMLCHAR_TO_DOMSTRING(LIBXML_DOC->version)).PtrC8();
       
   399     }
       
   400 
       
   401 // -----------------------------------------------------------------------------------------------
       
   402 // Sets XML version number to be shown in XML declaration when document is serialized.
       
   403 // -----------------------------------------------------------------------------------------------
       
   404 //
       
   405 EXPORT_C void RXmlEngDocument::SetXmlVersionL( const TDesC8& aVersion )
       
   406     {
       
   407     if(aVersion.Length())
       
   408         {
       
   409         xmlChar* ver = xmlCharFromDesC8L(aVersion);
       
   410         xmlFree((void*)LIBXML_DOC->version);
       
   411         LIBXML_DOC->version = ver;
       
   412         }
       
   413     }
       
   414 
       
   415 // -----------------------------------------------------------------------------------------------
       
   416 // Retrieves base URI (if defined) of the document or NULL
       
   417 // -----------------------------------------------------------------------------------------------
       
   418 //
       
   419 EXPORT_C TPtrC8 RXmlEngDocument::DocumentUri() const
       
   420     {
       
   421     return ((TXmlEngConstString)CAST_XMLCHAR_TO_DOMSTRING(LIBXML_DOC->URL)).PtrC8();
       
   422     }
       
   423 
       
   424 // -----------------------------------------------------------------------------------------------
       
   425 // Sets location of the document.
       
   426 //
       
   427 // Document's URI is used as top-level base URI definition.
       
   428 // -----------------------------------------------------------------------------------------------
       
   429 //
       
   430 EXPORT_C void RXmlEngDocument::SetDocumentUriL( const TDesC8& aUri )
       
   431     {
       
   432     xmlChar* uri = xmlCharFromDesC8L(aUri);
       
   433     if(LIBXML_DOC->URL)
       
   434         xmlFree((void*)LIBXML_DOC->URL);
       
   435     LIBXML_DOC->URL = uri;
       
   436     }
       
   437 
       
   438 // -----------------------------------------------------------------------------------------------
       
   439 // @return Object that represents current DOM implementation
       
   440 // @note There is no practical use of implementation object in this version
       
   441 //      of API other than for creating new RXmlEngDocument instances, but
       
   442 //      it will change in the future, when an implementation object 
       
   443 //      is used for changing configuration settings at run-time.
       
   444 // -----------------------------------------------------------------------------------------------
       
   445 //
       
   446 EXPORT_C RXmlEngDOMImplementation RXmlEngDocument::Implementation() const
       
   447     {
       
   448     return *iImpl;
       
   449     }
       
   450 
       
   451 // -----------------------------------------------------------------------------------------------
       
   452 // Creates new text node and copies the content string into it.
       
   453 // -----------------------------------------------------------------------------------------------
       
   454 //
       
   455 EXPORT_C TXmlEngTextNode RXmlEngDocument::CreateTextNodeL( const TDesC8& aCharacters )
       
   456     {
       
   457     xmlChar* con = xmlCharFromDesC8L(aCharacters);
       
   458     xmlNodePtr textNode = xmlNewText(NULL);
       
   459     if(!textNode)
       
   460         {
       
   461         delete con;
       
   462         OOM_HAPPENED;
       
   463         }
       
   464     textNode->doc = LIBXML_DOC;
       
   465     textNode->content = con;
       
   466     TXmlEngNode text(textNode);
       
   467     TakeOwnership(text);
       
   468     return text.AsText();
       
   469     }
       
   470 
       
   471 // -----------------------------------------------------------------------------------------------
       
   472 // Creates new binary container and copies the content string into it.
       
   473 // -----------------------------------------------------------------------------------------------
       
   474 //
       
   475 EXPORT_C TXmlEngBinaryContainer RXmlEngDocument::CreateBinaryContainerL( const TDesC8& aCid,
       
   476                                                              const TDesC8& aData )
       
   477     {
       
   478     // Note: TXmlEngBinaryContainer is treated internally by Libxml2 as text node.
       
   479 
       
   480     TUint len = aCid.Size();
       
   481     unsigned char* cid = new(ELeave) unsigned char[len + 1];
       
   482     memcpy(cid, aCid.Ptr(), len);
       
   483     cid[len] = 0;
       
   484     len = aData.Size();
       
   485     
       
   486     CleanupStack::PushL(cid);
       
   487     unsigned char* str = new(ELeave) unsigned char[len + 1];
       
   488     CleanupStack::Pop(cid);
       
   489     
       
   490     memcpy(str, aData.Ptr(), len);
       
   491     str[len] = 0;
       
   492     
       
   493     xmlNodePtr contNode = xmlNewText(NULL);
       
   494     if(!contNode)
       
   495         {
       
   496         delete cid;
       
   497         delete str;
       
   498         OOM_HAPPENED;
       
   499         }
       
   500         
       
   501     contNode->ns = (xmlNs*) cid;    
       
   502     contNode->content = (xmlChar*) str;
       
   503     contNode->properties = (xmlAttr*) len;
       
   504 	contNode->psvi = (void*) EBinaryContainer;
       
   505     contNode->doc = LIBXML_DOC;
       
   506     contNode->name = xmlStringTextNoenc;
       
   507     xmlAppendDataList(contNode, LIBXML_DOC);
       
   508     if(OOM_FLAG)
       
   509     	{
       
   510         xmlFreeNode(contNode);
       
   511         OOM_HAPPENED;    	
       
   512     	}    
       
   513     TXmlEngNode container(contNode);
       
   514     TakeOwnership(container);
       
   515     return container.AsBinaryContainer();
       
   516     }
       
   517 
       
   518 // -----------------------------------------------------------------------------------------------
       
   519 // Creates new binary container that stores reference to memory chunk mapped with descriptor
       
   520 // -----------------------------------------------------------------------------------------------
       
   521 //
       
   522 EXPORT_C TXmlEngChunkContainer RXmlEngDocument::CreateChunkContainerL( const TDesC8& aCid, 
       
   523 	    												   const RChunk& aChunk,
       
   524 						                                   const TInt aChunkOffset,
       
   525 						                                   const TInt aDataSize )
       
   526     {
       
   527     // Note: TXmlEngChunkContainer is treated internally by Libxml2 as text node.
       
   528     TUint len = aCid.Size();
       
   529     unsigned char* cid = new(ELeave) unsigned char[len + 1];
       
   530     memcpy(cid, aCid.Ptr(), len);
       
   531     cid[len] = 0;
       
   532     
       
   533     xmlNodePtr contNode = xmlNewText(NULL);
       
   534     if(!contNode)
       
   535         {
       
   536         delete cid;
       
   537         OOM_HAPPENED;
       
   538         }
       
   539     contNode->ns = (xmlNs*) cid;
       
   540     contNode->content = (xmlChar*) &aChunk;    
       
   541     contNode->properties = (xmlAttr*) aDataSize;
       
   542     contNode->nsDef = (xmlNs*) aChunkOffset;    
       
   543     contNode->psvi = (void*) EChunkContainer;
       
   544     contNode->doc = LIBXML_DOC;
       
   545     contNode->name = xmlStringTextNoenc;
       
   546     xmlAppendDataList(contNode, LIBXML_DOC);
       
   547     if(OOM_FLAG)
       
   548     	{
       
   549         xmlFreeNode(contNode);
       
   550         OOM_HAPPENED;    	
       
   551     	}
       
   552     TXmlEngNode container(contNode);
       
   553     TakeOwnership(container);
       
   554     return container.AsChunkContainer();
       
   555     }
       
   556 
       
   557 // -----------------------------------------------------------------------------------------------
       
   558 // Creates new binary container that stores reference to memory chunk mapped with descriptor
       
   559 // -----------------------------------------------------------------------------------------------
       
   560 //
       
   561 EXPORT_C TXmlEngFileContainer RXmlEngDocument::CreateFileContainerL( const TDesC8& aCid, 
       
   562 	    												 const RFile& aFile )
       
   563 						                                 
       
   564     {
       
   565     // Note: TXmlEngChunkContainer is treated internally by Libxml2 as text node.
       
   566     TUint len = aCid.Size();
       
   567     unsigned char* cid = new(ELeave) unsigned char[len + 1];
       
   568     memcpy(cid, aCid.Ptr(), len);
       
   569     cid[len] = 0;
       
   570     
       
   571     xmlNodePtr contNode = xmlNewText(NULL);
       
   572     if(!contNode)
       
   573         {
       
   574         delete cid;
       
   575         OOM_HAPPENED;
       
   576         }
       
   577     contNode->ns = (xmlNs*) cid;
       
   578     contNode->content = (xmlChar*) &aFile;    
       
   579     TInt fileSize;
       
   580     aFile.Size(fileSize);
       
   581     contNode->properties = (xmlAttr*) fileSize;
       
   582     contNode->psvi = (void*) EFileContainer;
       
   583     contNode->doc = LIBXML_DOC;
       
   584     contNode->name = xmlStringTextNoenc;
       
   585     xmlAppendDataList(contNode, LIBXML_DOC);
       
   586     if(OOM_FLAG)
       
   587     	{
       
   588         xmlFreeNode(contNode);
       
   589         OOM_HAPPENED;    	
       
   590     	}
       
   591     TXmlEngNode container(contNode);
       
   592     TakeOwnership(container);
       
   593     return container.AsFileContainer();
       
   594     }
       
   595 // -----------------------------------------------------------------------------------------------
       
   596 // Creates new comment node and copies the content string into it.
       
   597 // -----------------------------------------------------------------------------------------------
       
   598 //
       
   599 EXPORT_C TXmlEngComment RXmlEngDocument::CreateCommentL( const TDesC8& aText )
       
   600     {
       
   601     xmlChar* con = xmlCharFromDesC8L(aText);
       
   602     xmlNodePtr commentNode = xmlNewComment(NULL);
       
   603     if(!commentNode)
       
   604         {
       
   605         delete con;
       
   606         OOM_HAPPENED;
       
   607         } 
       
   608     commentNode->doc = LIBXML_DOC;
       
   609     commentNode->content = con;
       
   610     TXmlEngNode comment(commentNode);
       
   611     TakeOwnership(comment);
       
   612     return comment.AsComment();
       
   613     }
       
   614 
       
   615 // -----------------------------------------------------------------------------------------------
       
   616 // Creates new processing instruction node and set its "target" and "data" values
       
   617 // -----------------------------------------------------------------------------------------------
       
   618 //
       
   619 EXPORT_C TXmlEngProcessingInstruction RXmlEngDocument::CreateProcessingInstructionL( const TDesC8& aTarget, 
       
   620     																	 const TDesC8& aData )
       
   621     {
       
   622     if ( aTarget.Length( ) <= 0 ) 
       
   623     	{
       
   624     	User::Leave( KXmlEngErrWrongUseOfAPI );
       
   625     	}
       
   626     
       
   627     xmlChar* target = xmlCharFromDesC8L(aTarget);
       
   628     CleanupStack::PushL(target);
       
   629     xmlChar* data = xmlCharFromDesC8L(aData);
       
   630     
       
   631     xmlNodePtr piNode = xmlNewPI( target,
       
   632                             	  NULL );
       
   633     OOM_IF_NULL(piNode);
       
   634     CleanupStack::PopAndDestroy(target);
       
   635     piNode->content = data;
       
   636     TXmlEngNode pi(piNode);
       
   637     TakeOwnership(pi);
       
   638     return pi.AsProcessingInstruction();
       
   639     }
       
   640 
       
   641 // -----------------------------------------------------------------------------------------------
       
   642 // Creates new CDATA section node and copies the content into it.
       
   643 // -----------------------------------------------------------------------------------------------
       
   644 //
       
   645 EXPORT_C TXmlEngCDATASection RXmlEngDocument::CreateCDATASectionL( const TDesC8& aContents )
       
   646     {
       
   647     xmlChar* con = xmlCharFromDesC8L(aContents);
       
   648     xmlNodePtr cdNode = xmlNewCDataBlock( LIBXML_DOC,
       
   649 			                              NULL,
       
   650 			                              0);
       
   651 	if(!cdNode)
       
   652         {
       
   653         delete con;
       
   654         OOM_HAPPENED;
       
   655         } 
       
   656     cdNode->content = con;
       
   657     TXmlEngNode cd(cdNode);
       
   658     TakeOwnership(cd);
       
   659     return cd.AsCDATASection();
       
   660     }
       
   661 
       
   662 // -----------------------------------------------------------------------------------------------
       
   663 // Creates new entity reference node for aEntityName entity
       
   664 //
       
   665 // aEntityName is a string in one of the forms:
       
   666 //    -  <i>name</i>
       
   667 //    -  <b>&</b><i>name</i>
       
   668 //    -  <b>&</b><i>name</i><b>;</b>
       
   669 //
       
   670 // where <i>name</i> is the name of the entity
       
   671 //
       
   672 // @note &lt; , &gt; , &apos; , &quot; and other <b>predefined</b> entity references
       
   673 //      should not be created with this method. These entity refs are rather 
       
   674 //      "character references" and encoded/decoded automatically.
       
   675 // -----------------------------------------------------------------------------------------------
       
   676 //
       
   677 EXPORT_C TXmlEngEntityReference RXmlEngDocument::CreateEntityReferenceL( const TDesC8& aEntityRef )
       
   678     {
       
   679     if ( aEntityRef.Length( ) <= 0 ) 
       
   680     	{
       
   681     	User::Leave( KXmlEngErrWrongUseOfAPI );
       
   682     	}    
       
   683     
       
   684     xmlChar* er = xmlCharFromDesC8L(aEntityRef);
       
   685     xmlNodePtr erNode = xmlNewReference( LIBXML_DOC,
       
   686                         				 er);
       
   687     delete er;
       
   688     OOM_IF_NULL(erNode);
       
   689     TXmlEngNode eref(erNode);
       
   690     TakeOwnership(eref);
       
   691     return eref.AsEntityReference();
       
   692     }
       
   693 
       
   694 // -----------------------------------------------------------------------------------------------
       
   695 // Creates new element node that belongs to specific namespace.
       
   696 // A namespace declaration node is created on the element.
       
   697 //
       
   698 // @param aNamespaceUri Namespace of new element
       
   699 // @param aPrefix       Prefix to use for namespace binding and QName of the element
       
   700 // @param aLocalName    Local name of the element 
       
   701 //
       
   702 // @note If null namespace uri is provided element will be created without namespace.
       
   703 // -----------------------------------------------------------------------------------------------
       
   704 
       
   705 EXPORT_C TXmlEngElement RXmlEngDocument::CreateElementL( const TDesC8& aLocalName, 
       
   706 										     const TDesC8& aNamespaceUri, 
       
   707 										     const TDesC8& aPrefix )
       
   708     {        
       
   709     if ( aLocalName.Length( ) <= 0 ) 
       
   710     	{
       
   711     	User::Leave( KXmlEngErrWrongUseOfAPI );
       
   712     	}
       
   713     //
       
   714     xmlChar* name = xmlCharFromDesC8L(aLocalName);
       
   715     xmlNodePtr nodeEl = xmlNewNode( NULL, 
       
   716                             		name);
       
   717     delete name;
       
   718     OOM_IF_NULL(nodeEl);
       
   719     //
       
   720 //    if(aNamespaceUri.Length() || aPrefix.Length())
       
   721 	  if(aNamespaceUri.Length())
       
   722         {
       
   723         CleanupStack::PushL(TCleanupItem(LibxmlNodeCleanup,(TAny*)nodeEl));
       
   724         xmlChar* nsU = xmlCharFromDesC8L(aNamespaceUri);
       
   725         CleanupStack::PushL(nsU);
       
   726         xmlChar* nsP = NULL;
       
   727         if(aPrefix.Length())
       
   728             {
       
   729             nsP = xmlCharFromDesC8L(aPrefix);
       
   730             }
       
   731         CleanupStack::Pop(nsU);
       
   732         xmlNsPtr ns = xmlNewNs( NULL,
       
   733                     		    NULL,
       
   734                     		    NULL);
       
   735         
       
   736         if (!ns)
       
   737             {
       
   738             delete nsP;
       
   739             delete nsU;
       
   740             OOM_HAPPENED;
       
   741             }
       
   742         ns->href   = nsU;
       
   743         ns->prefix = nsP;
       
   744         nodeEl->nsDef = ns;
       
   745         nodeEl->ns = ns;
       
   746         CleanupStack::Pop(); // nodeEl
       
   747         }
       
   748     nodeEl->doc = LIBXML_DOC;
       
   749 
       
   750     TXmlEngElement el(nodeEl);
       
   751     TakeOwnership(el);
       
   752     return el;
       
   753     }
       
   754 
       
   755 // -----------------------------------------------------------------------------------------------
       
   756 // Creates new attribute,
       
   757 //
       
   758 // @param  aName   Name of the atribute; no prefix allowed
       
   759 // @param  aValue  Value of the attribute (optional)
       
   760 // @return Handler to the newly created attribute 
       
   761 //
       
   762 // @note 
       
   763 // aValue should represent a correct value of an attribute if it is put as is into XML file
       
   764 // (with all characters correctly escaped with entity references when XML spec requires)
       
   765 //
       
   766 // TXmlEngElement class provides a rich set of attribute creation methods, which not
       
   767 // just create attribute nut also link it into element.
       
   768 //
       
   769 // There is no way to create attributes with namespace (despite the DOM spec); 
       
   770 // you have to use one of the TXmlEngElement::AddNewAttributeL(..) methods instead
       
   771 //
       
   772 // Returned handler is the only reference to the allocated memory
       
   773 // until you have attached the attribute to some element node
       
   774 // -----------------------------------------------------------------------------------------------
       
   775 //
       
   776 EXPORT_C TXmlEngAttr RXmlEngDocument::CreateAttributeL( const TDesC8& aName, 
       
   777     										const TDesC8& aValue )
       
   778     {
       
   779     if ( aName.Length( ) <= 0 ) 
       
   780     	{
       
   781     	User::Leave( KXmlEngErrWrongUseOfAPI );
       
   782     	}
       
   783     xmlChar* name = xmlCharFromDesC8L(aName);
       
   784     CleanupStack::PushL(name);
       
   785     xmlChar* value = xmlCharFromDesC8L(aValue);
       
   786     
       
   787     xmlAttrPtr attrNode = xmlNewDocProp( LIBXML_DOC,
       
   788                             			 name,
       
   789                             	 		 value );
       
   790     delete value;
       
   791     CleanupStack::PopAndDestroy(name);
       
   792     OOM_IF_NULL(attrNode);
       
   793     TXmlEngNode attr(attrNode);
       
   794     TakeOwnership(attr);
       
   795     return attr.AsAttr();
       
   796     }
       
   797 
       
   798 // -----------------------------------------------------------------------------------------------
       
   799 // Sets "document" property on the node and all its descendants to be this RXmlEngDocument node 
       
   800 // -----------------------------------------------------------------------------------------------
       
   801 //
       
   802 EXPORT_C TXmlEngNode RXmlEngDocument::AdoptNodeL(TXmlEngNode aSource)
       
   803     {
       
   804     if ( aSource.ParentNode().NotNull() || aSource.OwnerDocument().IsSameNode( *this )
       
   805     		|| aSource.NodeType() == TXmlEngNode::EDocument ) 
       
   806     	{
       
   807     	User::Leave( KXmlEngErrWrongUseOfAPI );
       
   808     	}
       
   809     
       
   810     aSource.OwnerDocument().RemoveOwnership(aSource);
       
   811     xmlSetTreeDoc(INTERNAL_NODEPTR(aSource), LIBXML_DOC);
       
   812     TakeOwnership(aSource);
       
   813     return aSource;
       
   814     }
       
   815 
       
   816 // -----------------------------------------------------------------------------------------------
       
   817 // Main implementation of SaveL() functions that puts together all common code
       
   818 // and serializes to buffer or output stream.
       
   819 //	@param aNode Root node to be serialized     
       
   820 //	@param aBuffer buffer with serialized data.
       
   821 //	@param aOutputStream stream that should be used during serialization
       
   822 //	@param aOpt Options that control how serialization is performed
       
   823 //  @return Number of bytes written
       
   824 //	@leave KXmlEngErrWrongEncoding The encoding is not understood
       
   825 //  @leave KXmlEngErrNegativeOutputSize The data to be serialized has a negative size
       
   826 //	@leave - One of the system-wide error codes
       
   827 // -----------------------------------------------------------------------------------------------
       
   828 //
       
   829 TInt RXmlEngDocument::SaveNodeL( TXmlEngNode aRoot,
       
   830 					   	   RBuf8& aBuffer,
       
   831 						   MXmlEngOutputStream* aOutputStream,
       
   832 						   TXmlEngSerializationOptions aOpt) const				
       
   833     {
       
   834     TInt size = -1;
       
   835     const unsigned char* encoding;
       
   836     xmlCharEncodingHandlerPtr encoder = NULL;
       
   837     xmlSaveCtxt ctxt;
       
   838     xmlOutputBufferPtr buf = NULL;
       
   839     if (aBuffer.Length())
       
   840         {
       
   841         aBuffer.Close();    
       
   842         }
       
   843     xmlNodePtr node = INTERNAL_NODEPTR(aRoot);
       
   844     if(!node)
       
   845     	{
       
   846     	node = LIBXML_NODE;
       
   847     	}
       
   848     xmlChar* enc =NULL;
       
   849     if(aOpt.iEncoding.Length())
       
   850         enc =  xmlCharFromDesC8L(aOpt.iEncoding);
       
   851     CleanupStack::PushL(enc);
       
   852     
       
   853     encoding = enc;	        
       
   854     if (!encoding)
       
   855         {
       
   856         encoding = node->doc->encoding; 
       
   857         } 
       
   858     if (encoding) 
       
   859         {
       
   860         encoder = xmlFindCharEncodingHandler((char*)encoding);
       
   861         if (encoder == NULL)
       
   862             {
       
   863             TEST_OOM_FLAG;
       
   864             XmlEngLeaveL(KXmlEngErrWrongEncoding);
       
   865             }
       
   866         }
       
   867     
       
   868     if(aOutputStream)
       
   869        		{
       
   870 		    buf = xmlOutputBufferCreateIO( XmlEngineIOWriteCallback,
       
   871 		            					   XmlEngineIOCloseCallback,
       
   872 		            					   aOutputStream, // a "context" know by the library 
       
   873 		            					   encoder );       		
       
   874        		}
       
   875        	else
       
   876        		{
       
   877        		buf = xmlAllocOutputBuffer(encoder); 
       
   878        		}
       
   879     OOM_IF_NULL(buf);
       
   880     
       
   881     memset(&ctxt, 0, sizeof(ctxt));
       
   882     ctxt.doc = node->doc;
       
   883     ctxt.encoding = encoding;
       
   884     ctxt.buf = buf;
       
   885     ctxt.level = 0;
       
   886     ctxt.format = (aOpt.iOptions & TXmlEngSerializationOptions::KOptionIndent) ? 1 : 0; 
       
   887     if(aOpt.iDataSerializer)
       
   888     	{
       
   889     	ctxt.textNodeCallback = (xmlSaveTextNodeCallback) DataSerializationCallback;	
       
   890     	ctxt.context = aOpt.iDataSerializer;
       
   891     	}
       
   892     xmlSaveCtxtInit(&ctxt);
       
   893     
       
   894 	xmlNodeFilterData filterData = {0,0}; // Fix to DEF133066.
       
   895     // The scope of 'afilterData' (now 'filterData') has been increased so that it is valid when 
       
   896 	// passed to 'xmlNodeDumpOutputInternal(&ctxt, node)' as a member of 'ctxt'
       
   897     if (aOpt.iNodeFilter)
       
   898         {
       
   899 		filterData.fn = aOpt.iNodeFilter;
       
   900 		filterData.proxyFn = NodeFilterCallback;
       
   901         ctxt.nodeFilter = &filterData;
       
   902         }
       
   903 
       
   904     if(!(aOpt.iOptions & TXmlEngSerializationOptions::KOptionOmitXMLDeclaration))
       
   905         {
       
   906         const TInt KXmlOpenTagLength = 14;
       
   907         const TInt KXmlOpenTagEncLength = 10;
       
   908         const TInt KXmlOpenTagStdLength1 = 16;
       
   909         const TInt KXmlOpenTagStdLength2 = 17;
       
   910         const TInt KXmlCloseTagEncLength = 1;
       
   911         const TInt KXmlCloseTagLength = 2;
       
   912         
       
   913         xmlOutputBufferWrite(buf,KXmlOpenTagLength,"<?xml version=");
       
   914         if (node->doc->version != NULL)
       
   915             xmlBufferWriteQuotedString(buf->buffer, node->doc->version);
       
   916         else
       
   917             xmlOutputBufferWrite(buf, 5, "\"1.0\"");
       
   918 
       
   919         if (encoding && (aOpt.iOptions & TXmlEngSerializationOptions::KOptionEncoding))
       
   920             {
       
   921             xmlOutputBufferWrite(buf,KXmlOpenTagEncLength," encoding="); 
       
   922             xmlBufferWriteQuotedString(buf->buffer,encoding);
       
   923             }
       
   924             
       
   925         if (aOpt.iOptions & TXmlEngSerializationOptions::KOptionStandalone)
       
   926             {
       
   927             switch (node->doc->standalone) 
       
   928                 {
       
   929                 case 0:
       
   930                     xmlOutputBufferWrite(buf, KXmlOpenTagStdLength1, " standalone=\"no\"");
       
   931                     break;
       
   932                 case 1:
       
   933                     xmlOutputBufferWrite(buf, KXmlOpenTagStdLength2, " standalone=\"yes\"");
       
   934                     break;
       
   935                 }    
       
   936             }
       
   937         xmlOutputBufferWrite(buf,KXmlCloseTagLength,"?>");
       
   938         if(ctxt.format)
       
   939             {
       
   940             xmlOutputBufferWrite(buf,KXmlCloseTagEncLength,"\n");
       
   941             }
       
   942         }
       
   943     xmlNodeDumpOutputInternal(&ctxt, node);
       
   944     
       
   945     if(xmlOOMFlag())
       
   946         {
       
   947         xmlOutputBufferClose(buf);
       
   948         OOM_HAPPENED;
       
   949         }
       
   950     
       
   951     if(!aOutputStream)
       
   952         {
       
   953         if(buf->encoder)
       
   954             {
       
   955             xmlCharEncOutFunc(buf->encoder, buf->conv, buf->buffer);
       
   956             size = buf->conv->use;
       
   957             aBuffer.Assign(buf->conv->content,size,size); // frees any previous contents of aBuffer argument
       
   958             buf->conv->content = NULL; // To prevent it from freeing
       
   959             }
       
   960         else
       
   961             {
       
   962             size = buf->buffer->use;
       
   963             aBuffer.Assign(buf->buffer->content,size,size); // frees any previous contents of aBuffer argument       
       
   964             buf->buffer->content = NULL; // To prevent it from freeing
       
   965             }
       
   966         }
       
   967     else
       
   968         {
       
   969         size = buf->buffer->use;
       
   970         }
       
   971     TInt res = xmlOutputBufferClose(buf);
       
   972     
       
   973     if ((size < 0) || (res == -1))
       
   974         {
       
   975         XmlEngLeaveL(KXmlEngErrNegativeOutputSize);
       
   976         }
       
   977     CleanupStack::PopAndDestroy(enc);
       
   978     if(!aOutputStream)
       
   979         {    
       
   980     	return size;   
       
   981         }
       
   982     else
       
   983     	{
       
   984     	return res;
       
   985     	}
       
   986     }
       
   987 
       
   988 // -----------------------------------------------------------------------------------------------
       
   989 // "Secondary" constructor that should be called on every newly created document node.
       
   990 // Initializes container for nodes owned by the document.
       
   991 // 
       
   992 // The need for such secondary constructor is in the fact that underlying libxml2
       
   993 // library knows nothing about ownership of unlinked nodes -- this feature is
       
   994 // implemented in C++ DOM wrapper.
       
   995 // -----------------------------------------------------------------------------------------------
       
   996 //
       
   997 void RXmlEngDocument::InitOwnedNodeListL()
       
   998     {
       
   999     if(!LIBXML_DOC->ownedNodes)
       
  1000         LIBXML_DOC->ownedNodes = CXmlEngOwnedNodesContainer::NewL();
       
  1001     }
       
  1002 
       
  1003 // -----------------------------------------------------------------------------------------------
       
  1004 // Adds aNode to the list of owned nodes - the nodes that are not linked yet into a 
       
  1005 // document tree, but still destroyed with the document that owns them.
       
  1006 //
       
  1007 // In case of OOM (during growing node list container) the argument node is freed with
       
  1008 // xmlFreeNode()
       
  1009 // -----------------------------------------------------------------------------------------------
       
  1010 //
       
  1011 void RXmlEngDocument::TakeOwnership(TXmlEngNode aNode)
       
  1012     {
       
  1013     CXmlEngOwnedNodesContainer* nc = (CXmlEngOwnedNodesContainer*) LIBXML_DOC->ownedNodes;
       
  1014     if(aNode.ParentNode().NotNull())
       
  1015         return;
       
  1016     RXmlEngDocument owner = aNode.OwnerDocument();
       
  1017     if(owner.NotNull() && !owner.IsSameNode(*this))
       
  1018         {
       
  1019         owner.RemoveOwnership(aNode);
       
  1020         }
       
  1021 
       
  1022     nc->Add(INTERNAL_NODEPTR(aNode));
       
  1023     INTERNAL_NODEPTR(aNode)->doc = LIBXML_DOC;
       
  1024     }
       
  1025 
       
  1026 void RXmlEngDocument::RemoveOwnership(TXmlEngNode aNode)
       
  1027     {
       
  1028     if(LIBXML_DOC)
       
  1029         ((CXmlEngOwnedNodesContainer*)(LIBXML_DOC->ownedNodes))->Remove(INTERNAL_NODEPTR(aNode));
       
  1030     }
       
  1031 
       
  1032 // -----------------------------------------------------------------------------------------------
       
  1033 // Registers specified attribute as xml:id.
       
  1034 // First parametr allows user, to specify sub-tree, not to search whole document.
       
  1035 // To search whole tree see @see RegisterXmlId(const TDesC8&,const TDesC8&)
       
  1036 // -----------------------------------------------------------------------------------------------
       
  1037 //
       
  1038 EXPORT_C void RXmlEngDocument::RegisterXmlIdL(TXmlEngElement aStartElement,     
       
  1039                                         const TDesC8& aLocalName, 
       
  1040 										const TDesC8& aNamespaceUri)
       
  1041     {
       
  1042     if ( !aLocalName.Compare(KNullDesC8) || aStartElement.IsNull()
       
  1043          || !aStartElement.OwnerDocument().IsSameNode(*this) || aStartElement.OwnerDocument().IsNull())
       
  1044         {
       
  1045         User::Leave(KXmlEngErrWrongUseOfAPI);   
       
  1046         }        
       
  1047     
       
  1048     xmlChar* name = xmlCharFromDesC8L(aLocalName);
       
  1049     CleanupStack::PushL(name);
       
  1050     xmlChar* nsU = NULL;
       
  1051     if(aNamespaceUri.Length())
       
  1052         nsU=xmlCharFromDesC8L(aNamespaceUri);
       
  1053     
       
  1054     const xmlChar* ids[3];
       
  1055     ids[0] = name;
       
  1056     ids[1] = nsU;
       
  1057     ids[2] = NULL;
       
  1058     
       
  1059     TInt error = xmlAddIDs(INTERNAL_NODEPTR(aStartElement), ids);
       
  1060     
       
  1061     delete nsU;
       
  1062     CleanupStack::PopAndDestroy(name);
       
  1063     
       
  1064     switch (error) 
       
  1065         {
       
  1066         case 0:            
       
  1067         break;
       
  1068         case -1:
       
  1069             User::Leave(KErrAlreadyExists);
       
  1070         break;
       
  1071         case -2:
       
  1072             User::Leave(KErrNoMemory);
       
  1073         break;
       
  1074         case -3:
       
  1075             User::Leave(KErrArgument);
       
  1076         break;
       
  1077         default:
       
  1078             //User::Panic(); ?
       
  1079         break;            
       
  1080         }
       
  1081 
       
  1082     }
       
  1083 
       
  1084 // -----------------------------------------------------------------------------------------------
       
  1085 // Registers specified attribute as xml:id.
       
  1086 // Not to search whole tree see @see RegisterXmlId(TXmlEngElement,const TDesC8&,const TDesC8&)
       
  1087 // -----------------------------------------------------------------------------------------------
       
  1088 //
       
  1089 EXPORT_C void RXmlEngDocument::RegisterXmlIdL(const TDesC8& aLocalName, 
       
  1090 										const TDesC8& aNamespaceUri)
       
  1091     {
       
  1092     if (IsNull())
       
  1093         {
       
  1094         User::Leave(KXmlEngErrWrongUseOfAPI);   
       
  1095         }        
       
  1096     RegisterXmlIdL(DocumentElement(),aLocalName, aNamespaceUri);
       
  1097     }
       
  1098 
       
  1099 // ---------------------------------------------------------------------------------------------
       
  1100 // Looks for element with specified value of xmlId
       
  1101 // ---------------------------------------------------------------------------------------------
       
  1102 //
       
  1103 EXPORT_C TXmlEngElement RXmlEngDocument::FindElementByXmlIdL( const TDesC8& aValue ) const
       
  1104     {
       
  1105     xmlChar* value = xmlCharFromDesC8L(aValue);
       
  1106     xmlAttrPtr attr = xmlGetID( LIBXML_DOC, value );
       
  1107     delete value;
       
  1108     if (attr==NULL)
       
  1109         {
       
  1110         return TXmlEngElement(NULL);
       
  1111         }
       
  1112     return TXmlEngElement(attr->parent);
       
  1113     }
       
  1114     
       
  1115 // ---------------------------------------------------------------------------------------------
       
  1116 // Retrieves an array of chunk containers
       
  1117 // ---------------------------------------------------------------------------------------------
       
  1118 //
       
  1119 EXPORT_C TInt RXmlEngDocument::GetDataContainerList( RArray<TXmlEngDataContainer>& aList )
       
  1120 	{
       
  1121 	TInt i = 0;
       
  1122 	TInt error = 0;
       
  1123 	while( LIBXML_DOC->dataNodeList[i] )
       
  1124 		{
       
  1125 		TXmlEngNode node(LIBXML_DOC->dataNodeList[i]);
       
  1126 		error = aList.Append( node.AsDataContainer() );
       
  1127 		if (error) break;
       
  1128 		++i;		
       
  1129 	    }
       
  1130 	return error;
       
  1131 	}
       
  1132  
       
  1133 // -----------------------------------------------------------------------------
       
  1134 // Default constructor
       
  1135 // -----------------------------------------------------------------------------
       
  1136 //
       
  1137 EXPORT_C RXmlEngDocument::RXmlEngDocument():TXmlEngNode(NULL), iImpl(NULL)
       
  1138     {
       
  1139     }