xml/xmldomandxpath/src/xmlenginedom/xmlengnode.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 // Node functions implementation
       
    15 //
       
    16 
       
    17 #include <stdlib.h>
       
    18 
       
    19 #include <xml/dom/xmlengelement.h>
       
    20 #include <xml/dom/xmlengdocument.h>
       
    21 #include <xml/dom/xmlengnamespace.h>
       
    22 #include <xml/dom/xmlengtext.h>
       
    23 #include <xml/dom/xmlenguserdata.h>
       
    24 #include <xml/dom/xmlengnodelist.h>
       
    25 #include <stdapis/libxml2/libxml2_parser.h>
       
    26 #include <stdapis/libxml2/libxml2_globals.h>
       
    27 #include <stdapis/libxml2/libxml2_xmlio.h>
       
    28 #include "libxml2_xmlsave_private.h"
       
    29 #include "libxml2_tree_private.h"
       
    30 #include "xmlengdomdefs.h"
       
    31 #include <xml/dom/xmlengerrors.h>
       
    32 #include <xml/utils/xmlengmem.h>
       
    33 #include <xml/utils/xmlengxestrings.h>
       
    34 
       
    35 // ---------------------------------------------------------------------------------------------
       
    36 // Unlinks the internal libxml2's node from double-linked list.
       
    37 // Relinks neighbour nodes.The node stays virtually linked to its old neighbours! Use with care!!
       
    38 //
       
    39 // No checks are made; nor parent's, nor node's properties updated
       
    40 // ---------------------------------------------------------------------------------------------
       
    41 //
       
    42 void TXmlEngNode::DoUnlinkNode()
       
    43     {
       
    44     xmlNodePtr& next = LIBXML_NODE->next;
       
    45     xmlNodePtr& prev = LIBXML_NODE->prev;
       
    46     // Unlink this node; relink neighbors
       
    47     if (prev)
       
    48         {
       
    49         prev->next = next;
       
    50         }
       
    51     else
       
    52         {
       
    53         // Unlinked node is the first in the list
       
    54         // 'children' or 'properties' property of the parent node
       
    55         // must be updated (depending on the type of the node: content node or attribute) 
       
    56         xmlNodePtr& parent = LIBXML_NODE->parent;
       
    57         // Ugly, but works :)
       
    58         xmlNodePtr* first = ((LIBXML_NODE->type ==  XML_ATTRIBUTE_NODE) 
       
    59                               ? reinterpret_cast<xmlNodePtr*>(&(parent->properties)) 
       
    60                               : &(parent->children));
       
    61         *first = next;
       
    62         }
       
    63     if (next)
       
    64         {
       
    65         next->prev = prev;
       
    66         }
       
    67     else
       
    68         {
       
    69         // Unlinked node is the last in the list (of elements or attributes) 
       
    70         // 'last' property of the parent element must be updated  (for content nodes only)
       
    71         if(LIBXML_NODE->type != XML_ATTRIBUTE_NODE)
       
    72             {
       
    73             LIBXML_NODE->parent->last = prev;
       
    74             }
       
    75         }
       
    76     }
       
    77 
       
    78 
       
    79 // ---------------------------------------------------------------------------------------------
       
    80 // Inserts the node in a double-linked list of nodes before specified node.
       
    81 //
       
    82 // No checks are made; nor parent's, nor node's properties updated (except prev/next)
       
    83 // ---------------------------------------------------------------------------------------------
       
    84 //
       
    85 void TXmlEngNode::LinkBefore(TXmlEngNode aTargetNode)
       
    86     {
       
    87     xmlNodePtr node = INTERNAL_NODEPTR(aTargetNode);
       
    88     xmlNodePtr& prev = node->prev;
       
    89     LIBXML_NODE->next = node;
       
    90     LIBXML_NODE->prev = prev;
       
    91     prev->next = LIBXML_NODE;
       
    92     node->prev = LIBXML_NODE;
       
    93     }
       
    94 
       
    95 // ---------------------------------------------------------------------------------------------
       
    96 // Get innerXML string. This method return all content of the node.
       
    97 // Output text does not include node markup.
       
    98 //
       
    99 // @note Returned TString should be freed
       
   100 // ---------------------------------------------------------------------------------------------
       
   101 //
       
   102 EXPORT_C TInt TXmlEngNode::InnerXmlL(RBuf8& aBuffer)
       
   103     {
       
   104     if(aBuffer.Length())
       
   105         {
       
   106         aBuffer.Close();
       
   107         }
       
   108     if(IsNull())
       
   109     	{
       
   110     	User::Leave(KXmlEngErrWrongUseOfAPI);
       
   111     	} 
       
   112     	
       
   113     if(NodeType() == TXmlEngNode::EDocument)
       
   114         {
       
   115         return OwnerDocument().SaveL(aBuffer, OwnerDocument(), NULL);
       
   116         }
       
   117     aBuffer.FillZ();
       
   118     RXmlEngNodeList<TXmlEngNode> nodeList;
       
   119     RBuf8 tmpStr;
       
   120     GetChildNodes(nodeList);
       
   121     TXmlEngNode tmpNode;
       
   122     while(nodeList.HasNext())
       
   123         {
       
   124         tmpNode = nodeList.Next();
       
   125         tmpNode.OuterXmlL(tmpStr);
       
   126         CleanupClosePushL(tmpStr);
       
   127         if((aBuffer.MaxSize() - aBuffer.Size()) < tmpStr.Size()) 
       
   128             {
       
   129             aBuffer.ReAllocL(aBuffer.MaxSize() + tmpStr.Size() + 1);
       
   130             }
       
   131         aBuffer.Append(tmpStr);
       
   132         CleanupStack::PopAndDestroy();
       
   133         }
       
   134     tmpStr.Close();
       
   135     
       
   136     return aBuffer.Size();
       
   137     }
       
   138     
       
   139 // ---------------------------------------------------------------------------------------------
       
   140 // Get outerXML string. This method return all content of the node.
       
   141 // Output text includes node markup.
       
   142 //
       
   143 // @note Returned TString should be freed
       
   144 //
       
   145 // ---------------------------------------------------------------------------------------------
       
   146 //
       
   147 EXPORT_C TInt TXmlEngNode::OuterXmlL(RBuf8& aBuffer)
       
   148     {
       
   149     TInt size = -1;
       
   150     if(aBuffer.Length())
       
   151         {
       
   152         aBuffer.Close();
       
   153         }
       
   154     if(IsNull())
       
   155     	{
       
   156     	User::Leave(KXmlEngErrWrongUseOfAPI);
       
   157     	} 
       
   158         
       
   159     if(NodeType() == TXmlEngNode::EDocument)
       
   160         {
       
   161         return OwnerDocument().SaveL(aBuffer, OwnerDocument(), NULL);
       
   162         }
       
   163     
       
   164     xmlSaveCtxt ctxt;
       
   165     xmlOutputBufferPtr buf;
       
   166     
       
   167     /* 
       
   168      * save the content to a temp buffer.
       
   169      */
       
   170     buf = xmlAllocOutputBuffer(NULL);
       
   171     OOM_IF_NULL(buf);
       
   172 
       
   173     memset(&ctxt, 0, sizeof(ctxt));
       
   174     ctxt.doc = LIBXML_NODE->doc;
       
   175     ctxt.buf = buf;
       
   176     ctxt.level = 0;
       
   177     ctxt.format = 0; 
       
   178    
       
   179     xmlSaveCtxtInit(&ctxt);
       
   180 
       
   181     xmlNodeDumpOutputInternal(&ctxt, LIBXML_NODE);
       
   182     if(xmlOOMFlag())
       
   183         {
       
   184         xmlOutputBufferClose(buf);
       
   185         OOM_HAPPENED;
       
   186         }
       
   187         
       
   188     size = buf->buffer->use;
       
   189     if(size > 0)
       
   190         {
       
   191         // frees any previous contents of aBuffer argument
       
   192         aBuffer.Assign(buf->buffer->content,size,size);
       
   193         // To prevent it from freeing
       
   194         buf->buffer->content = NULL; 
       
   195         }
       
   196     xmlOutputBufferClose(buf);
       
   197     
       
   198     // Leaves with KErrNoMemory
       
   199     TEST_OOM_FLAG; 
       
   200     if (size < 0)
       
   201         {
       
   202         XmlEngLeaveL(KXmlEngErrNegativeOutputSize);
       
   203         }        
       
   204         
       
   205     return size;
       
   206     }
       
   207 
       
   208 // ---------------------------------------------------------------------------------------------
       
   209 // Moves the node to become the first in the list of its siblings
       
   210 // Node is expected to have a parent.
       
   211 // ---------------------------------------------------------------------------------------------
       
   212 //
       
   213 EXPORT_C void TXmlEngNode::SetAsFirstSibling()
       
   214     {
       
   215     if (LIBXML_NODE->type == XML_NAMESPACE_DECL)
       
   216         {
       
   217         return;
       
   218         }
       
   219     xmlNodePtr& prev = LIBXML_NODE->prev;
       
   220     if (prev)
       
   221         {
       
   222         DoUnlinkNode();
       
   223         // Insert as first
       
   224         prev = NULL;
       
   225         xmlNodePtr& parent = LIBXML_NODE->parent;
       
   226         // Ugly, but works :)
       
   227         xmlNodePtr* first = ((LIBXML_NODE->type == XML_ATTRIBUTE_NODE)
       
   228                               ? reinterpret_cast<xmlNodePtr*>(&(parent->properties))
       
   229                               : &(parent->children));
       
   230         
       
   231         (*first)->prev = LIBXML_NODE;
       
   232         LIBXML_NODE->next = *first;
       
   233         *first = LIBXML_NODE;
       
   234         // NOTE: it is possible to cope without having parent defined,
       
   235         //       it will need to iterate through sibling list to find the first one
       
   236         }
       
   237     }
       
   238 
       
   239 
       
   240 // ---------------------------------------------------------------------------------------------
       
   241 // Moves the node to become the last in the list of its siblings
       
   242 // Node is expected to have a parent.
       
   243 // ---------------------------------------------------------------------------------------------
       
   244 //
       
   245 EXPORT_C void TXmlEngNode::SetAsLastSibling()
       
   246     {
       
   247     if (LIBXML_NODE->type == XML_NAMESPACE_DECL)
       
   248         {
       
   249         return;
       
   250         }
       
   251     xmlNodePtr& next = LIBXML_NODE->next;
       
   252     if (next)
       
   253         {
       
   254         DoUnlinkNode(); 
       
   255         xmlNodePtr& parent = LIBXML_NODE->parent;
       
   256         xmlNodePtr& prev = LIBXML_NODE->prev;
       
   257         if (LIBXML_NODE->type != XML_ATTRIBUTE_NODE)
       
   258             {
       
   259             if (!prev)
       
   260                 parent->children = next;
       
   261             prev = parent->last;
       
   262             parent->last->next = LIBXML_NODE;
       
   263             parent->last = LIBXML_NODE;
       
   264             }
       
   265         else
       
   266             {
       
   267             if (!prev)
       
   268                 parent->properties = (xmlAttrPtr)next;
       
   269             prev = next; // NOTE: 'next' is always different than NULL
       
   270             while (prev->next)
       
   271                 prev = prev->next;
       
   272             prev->next = LIBXML_NODE;
       
   273             }
       
   274         next = NULL;
       
   275         }
       
   276     }
       
   277 
       
   278 // ---------------------------------------------------------------------------------------------
       
   279 // Moves the node in the list of sibling nodes before another node
       
   280 // Node is expected to have a parent.
       
   281 // Do nothing if aSiblingNode is not one of node's siblings
       
   282 // ---------------------------------------------------------------------------------------------
       
   283 //
       
   284 EXPORT_C void TXmlEngNode::MoveBeforeSibling(
       
   285     TXmlEngNode aSiblingNode )
       
   286     {
       
   287     if (LIBXML_NODE->type == XML_NAMESPACE_DECL)
       
   288         {
       
   289         return;
       
   290         }
       
   291     xmlNodePtr node = INTERNAL_NODEPTR(aSiblingNode);
       
   292     if (!node->prev)
       
   293         {
       
   294         SetAsFirstSibling();
       
   295         }
       
   296     else
       
   297         {
       
   298         DoUnlinkNode();
       
   299         LinkBefore(aSiblingNode);
       
   300         }
       
   301     }
       
   302 
       
   303 // ---------------------------------------------------------------------------------------------
       
   304 // Moves the node in the list of sibling nodes after another node
       
   305 // Node is expected to have a parent.
       
   306 // Do nothing if aSiblingNode is not one of the node's siblings
       
   307 // ---------------------------------------------------------------------------------------------
       
   308 //
       
   309 EXPORT_C void TXmlEngNode::MoveAfterSibling(
       
   310     TXmlEngNode aSiblingNode)
       
   311     {
       
   312     if (LIBXML_NODE->type == XML_NAMESPACE_DECL)
       
   313         {
       
   314         return;
       
   315         }
       
   316     xmlNodePtr node = INTERNAL_NODEPTR(aSiblingNode);
       
   317     if (!node->next)
       
   318         {
       
   319         SetAsLastSibling();
       
   320         }
       
   321     else
       
   322         {
       
   323         DoUnlinkNode();
       
   324         LinkBefore(aSiblingNode.NextSibling());
       
   325         }   
       
   326     }
       
   327 
       
   328 // ---------------------------------------------------------------------------------------------
       
   329 // Retrieves a "handle" for namespace declaration that applies to the node's namespace
       
   330 // Note: DOM specs do not consider namespace declarations as a kind of nodes
       
   331 // This API adds TXmlEngNamespace type of nodes, which is derived from TXmlEngNode.
       
   332 //
       
   333 // @return    Object that represents namespace declaration and prefix binding that
       
   334 //            act on the node; returns NULL object (check using TXmlEngNamespace.IsNull()
       
   335 //            or TXmlEngNamespace.NotNull()) if no namespace associated
       
   336 // ---------------------------------------------------------------------------------------------
       
   337 //
       
   338 EXPORT_C TXmlEngNamespace TXmlEngNode::NamespaceDeclaration() const
       
   339     {
       
   340     //
       
   341     switch(LIBXML_NODE->type)
       
   342         {
       
   343         case XML_ELEMENT_NODE:
       
   344         case XML_ATTRIBUTE_NODE:
       
   345             return TXmlEngNamespace(LIBXML_NODE->ns);
       
   346         default:
       
   347             return NULL;
       
   348         }
       
   349     }
       
   350 
       
   351 // ---------------------------------------------------------------------------------------------
       
   352 // Clones the node completely: all attributes and namespace declarations (for TXmlEngElement nodes),
       
   353 // values and children nodes are copied as well.
       
   354 // 
       
   355 // Document nodes cannot be copied with this method: RXmlEngDocument::CloneDocumentL() must be used.
       
   356 //
       
   357 // @return Complete copy of a node or leaves.
       
   358 // @note    The node should not be NULL!
       
   359 // ---------------------------------------------------------------------------------------------
       
   360 //
       
   361 EXPORT_C TXmlEngNode TXmlEngNode::CopyL() const
       
   362     {
       
   363     if ( !LIBXML_NODE )
       
   364     	{
       
   365     	User::Leave(KXmlEngErrNullNode);
       
   366     	}
       
   367     // Copying of RXmlEngDocument should be made with RXmlEngDocument::CloneDocumentL()
       
   368     if(NodeType() == TXmlEngNode::EDocument)
       
   369         return NULL;
       
   370     //
       
   371     xmlNodePtr copy = xmlStaticCopyNode(
       
   372                             LIBXML_NODE, 
       
   373                             NULL /* doc */, 
       
   374                             NULL /* parent */, 
       
   375                             1);
       
   376     //
       
   377     if (xmlOOMFlag())
       
   378         {
       
   379         if(copy)
       
   380             xmlFreeNode(copy); // it may be a partial copy
       
   381         OOM_HAPPENED;
       
   382         }
       
   383     TXmlEngNode ncopy(copy);
       
   384     OwnerDocument().TakeOwnership(ncopy);
       
   385     return ncopy;
       
   386     }
       
   387 
       
   388 // ---------------------------------------------------------------------------------------------
       
   389 // Creates a deep copy of the node and appends the subtree as a new child
       
   390 // to the provided parent node.
       
   391 //
       
   392 // @return Created copy of the node after linking it into the target document tree.
       
   393 // @note Document nodes cannot be copied with this method; use RXmlEngDocument::CloneDocumentL()
       
   394 // ---------------------------------------------------------------------------------------------
       
   395 //
       
   396 EXPORT_C TXmlEngNode TXmlEngNode::CopyToL(
       
   397     TXmlEngNode aParent ) const
       
   398     {
       
   399     if ( !LIBXML_NODE )
       
   400     	{
       
   401     	User::Leave(KXmlEngErrNullNode);
       
   402     	}
       
   403     if ( LIBXML_NODE->type == XML_DOCUMENT_NODE )
       
   404     	{
       
   405     	User::Leave(KXmlEngErrWrongUseOfAPI);
       
   406     	}
       
   407    if ( aParent.IsNull() )
       
   408     	{
       
   409     	User::Leave(KXmlEngErrNullNode);
       
   410     	}
       
   411     //
       
   412     TXmlEngNode ncopy = CopyL();
       
   413     return aParent.AppendChildL(ncopy);
       
   414     }
       
   415 
       
   416 // ---------------------------------------------------------------------------------------------
       
   417 // Detaches a node from document tree
       
   418 //
       
   419 // @return This node, which is already not a part of any document
       
   420 // @note    Remember to use ReconcileNamespacesL() later, if extracted node (subtree)
       
   421 //         contains references to namespace declarations outside of the subtree.
       
   422 // @see     ReconcileNamespacesL()
       
   423 // @note    The document, from which the node is being unlinked, becomes an owner of the node
       
   424 //         until it is linked elsewhere.
       
   425 // ---------------------------------------------------------------------------------------------
       
   426 //
       
   427 EXPORT_C TXmlEngNode TXmlEngNode::Unlink()
       
   428     {   
       
   429     //
       
   430     if(LIBXML_NODE && ParentNode().NotNull())
       
   431         {
       
   432         RXmlEngDocument tmpDoc = OwnerDocument();
       
   433         xmlUnlinkNode(LIBXML_NODE);
       
   434         tmpDoc.TakeOwnership(*this);
       
   435         }
       
   436     return *this;
       
   437     }
       
   438 
       
   439 // ---------------------------------------------------------------------------------------------
       
   440 // Unlinks the node and destroys it; all child nodes are destroyed as well and all memory is freed
       
   441 //
       
   442 // @note  Document nodes cannot be "removed" with this method, uses RXmlEngDocument-specific methods.
       
   443 // ---------------------------------------------------------------------------------------------
       
   444 //
       
   445 EXPORT_C void TXmlEngNode::Remove()
       
   446     {
       
   447     //
       
   448     if (!LIBXML_NODE || LIBXML_NODE->type == XML_DOCUMENT_NODE)
       
   449         {
       
   450         return;
       
   451         }
       
   452     if(ParentNode().NotNull())
       
   453         {
       
   454         xmlUnlinkNode(LIBXML_NODE);
       
   455         }
       
   456     else
       
   457         {
       
   458         OwnerDocument().RemoveOwnership(*this);
       
   459         }
       
   460     if (LIBXML_NODE->type != XML_ATTRIBUTE_NODE)
       
   461         {
       
   462      xmlFreeNode(LIBXML_NODE);
       
   463         }
       
   464 	else
       
   465 		{
       
   466 		xmlFreeProp(INTERNAL_ATTRPTR(iInternal));
       
   467 		}
       
   468 
       
   469     iInternal = 0;
       
   470     }
       
   471 
       
   472 // ---------------------------------------------------------------------------------------------
       
   473 // Ensures that namespaces referred to in the node and its descendants are
       
   474 // in the scope the node.
       
   475 //
       
   476 // * This method checks that all the namespaces declared within the given
       
   477 // * tree are properly declared. This is needed for example after Copy or Unlink
       
   478 // * and then Append operations. The subtree may still hold pointers to
       
   479 // * namespace declarations outside the subtree or they may be invalid/masked. As much
       
   480 // * as possible the function try to reuse the existing namespaces found in
       
   481 // * the new environment. If not possible, the new namespaces are redeclared
       
   482 // * on the top of the subtree.
       
   483 //
       
   484 // This method should be used after unlinking nodes and inserting to another
       
   485 // document tree or to a another part of the original tree, if some nodes of the subtree
       
   486 // are remove from the scope of a namespace declaration they refer to.
       
   487 //
       
   488 // When node is unlinked, it may still refer to namespace declarations from the previous location.
       
   489 // It is important to reconcile subtree's namespaces if previous parent tree is to be destroyed.
       
   490 // On the other hand, if the parent tree is not changed before pasting its unlinked part into another
       
   491 // tree, then reconciliation is needed only after paste operation.
       
   492 // ---------------------------------------------------------------------------------------------
       
   493 //
       
   494 EXPORT_C void TXmlEngNode::ReconcileNamespacesL()
       
   495     {
       
   496     xmlReconciliateNs(LIBXML_NODE->doc, LIBXML_NODE);
       
   497     TEST_OOM_FLAG;
       
   498     }
       
   499 
       
   500 // ---------------------------------------------------------------------------------------------
       
   501 // Current node is replaced with another node (subtree).
       
   502 //
       
   503 // The replacement node is linked into document tree instead of this node.
       
   504 // The replaced node is destroyed.
       
   505 //
       
   506 // @see SubstituteForL(TXmlEngNode)
       
   507 //
       
   508 // In both cases the argument node is unlinked from its previous location
       
   509 // (which can be NONE, i.e. not linked; SAME or ANOTHER document tree).
       
   510 //
       
   511 // @note Replacement of a node with NULL TXmlEngNode is legal and equivalent to removing the node.
       
   512 // @note Not applicable to document nodes
       
   513 // ---------------------------------------------------------------------------------------------
       
   514 //
       
   515 EXPORT_C void TXmlEngNode::ReplaceWithL(TXmlEngNode aNode)
       
   516     {
       
   517     if ( !LIBXML_NODE )
       
   518     	{
       
   519     	User::Leave(KXmlEngErrNullNode);
       
   520     	}
       
   521     if ( LIBXML_NODE->type == XML_DOCUMENT_NODE )
       
   522     	{
       
   523     	User::Leave(KXmlEngErrWrongUseOfAPI);
       
   524     	}
       
   525 
       
   526     if(aNode.ParentNode().IsNull())
       
   527         {
       
   528     	// new node is unlinked, so owned by some (maybe other than this) document
       
   529 	    // previous ownership must be withdrawn
       
   530         aNode.OwnerDocument().RemoveOwnership(aNode);
       
   531         }
       
   532     if(ParentNode().IsNull())
       
   533         {
       
   534     	// This node is unlinked, thus owned by its document
       
   535 	    // Ownership must be withdrawn before removing the node
       
   536 	    RXmlEngDocument doc = OwnerDocument();
       
   537 	    doc.RemoveOwnership(*this);
       
   538 	    // Also, there is no place to link the new node! 
       
   539 	    // So it will be unlinked, but owned by this node's document 
       
   540         doc.TakeOwnership(aNode);
       
   541         }
       
   542     // put new node instead of 'this' node: it works with all combinations of linked/unlinked states of the nodes
       
   543     xmlFreeNode(xmlReplaceNode(LIBXML_NODE, INTERNAL_NODEPTR(aNode)));
       
   544     }
       
   545 
       
   546 EXPORT_C void TXmlEngNode::ReplaceWith(TXmlEngNode aNode)
       
   547     {
       
   548     if(!LIBXML_NODE || LIBXML_NODE->type == XML_DOCUMENT_NODE)
       
   549         return;
       
   550     if(aNode.ParentNode().IsNull())
       
   551         {
       
   552     	// new node is unlinked, so owned by some (maybe other than this) document
       
   553 	    // previous ownership must be withdrawn
       
   554         aNode.OwnerDocument().RemoveOwnership(aNode);
       
   555         }
       
   556     if(ParentNode().IsNull())
       
   557         {
       
   558     	// This node is unlinked, thus owned by its document
       
   559 	    // Ownership must be withdrawn before removing the node
       
   560 	    RXmlEngDocument doc = OwnerDocument();
       
   561 	    doc.RemoveOwnership(*this);
       
   562 	    // Also, there is no place to link the new node! 
       
   563 	    // So it will be unlinked, but owned by this node's document 
       
   564         doc.TakeOwnership(aNode);
       
   565         }
       
   566     // put new node instead of 'this' node: it works with all combinations of linked/unlinked states of the nodes
       
   567     xmlFreeNode(xmlReplaceNode(LIBXML_NODE, INTERNAL_NODEPTR(aNode)));
       
   568     }
       
   569 
       
   570 // ---------------------------------------------------------------------------------------------
       
   571 // Another node is put instead of the current node.
       
   572 //
       
   573 // Does the same as ReplaceWith(TXmlEngNode) but does not free node and just returns it.
       
   574 //
       
   575 // @return Current node after unlinking it from document tree
       
   576 // @see ReplaceWith(TXmlEngNode)
       
   577 //
       
   578 // In both cases the argument node is unlinked from its previous location
       
   579 // (which can be NONE, i.e. not linked; SAME or ANOTHER document tree)
       
   580 //
       
   581 // It is possible to use NULL TXmlEngNode object as an argument. In such case
       
   582 // no new node will be put instead of unlinked one.
       
   583 //
       
   584 // @note Not applicable to document nodes
       
   585 // ---------------------------------------------------------------------------------------------
       
   586 //
       
   587 EXPORT_C TXmlEngNode TXmlEngNode::SubstituteForL(TXmlEngNode aNode)
       
   588     {
       
   589     if ( !LIBXML_NODE )
       
   590     	{
       
   591     	User::Leave(KXmlEngErrNullNode);
       
   592     	}
       
   593     if ( LIBXML_NODE->type == XML_DOCUMENT_NODE )
       
   594     	{
       
   595     	User::Leave(KXmlEngErrWrongUseOfAPI);
       
   596     	}
       
   597     //
       
   598     if(aNode.ParentNode().IsNull())
       
   599         {
       
   600       	// new node is unlinked, so owned by other document
       
   601     	// it must not be owned to be linked
       
   602         aNode.OwnerDocument().RemoveOwnership(aNode);
       
   603         }
       
   604     if(ParentNode().IsNull())
       
   605         {
       
   606     	// this node is unlinked - nowhere to link new node: this node's document will own it
       
   607         OwnerDocument().TakeOwnership(aNode);
       
   608 	    // this node will stay as it is
       
   609 	    // new node will be unlinked by call to xmlReplaceNode
       
   610         }        
       
   611     TXmlEngNode tmpNode = TXmlEngNode(xmlReplaceNode(LIBXML_NODE, INTERNAL_NODEPTR(aNode)));
       
   612     aNode.OwnerDocument().TakeOwnership(tmpNode);
       
   613     return tmpNode;
       
   614     }
       
   615 
       
   616 // ---------------------------------------------------------------------------------------------
       
   617 // DOM Level 3 Core
       
   618 // ---------------------------------------------------------------------------------------------
       
   619 
       
   620 // ---------------------------------------------------------------------------------------------
       
   621 //Initializes a node list with all children of the node
       
   622 // ---------------------------------------------------------------------------------------------
       
   623 //
       
   624 EXPORT_C void TXmlEngNode::GetChildNodes(RXmlEngNodeList<TXmlEngNode>& aList) const
       
   625     {
       
   626     aList.Open(LIBXML_NODE->children, TDOMNODETYPENONE);
       
   627     }
       
   628 
       
   629 // ---------------------------------------------------------------------------------------------
       
   630 // @return Parent node of the node or NULL if no parent
       
   631 // ---------------------------------------------------------------------------------------------
       
   632 //
       
   633 EXPORT_C TXmlEngNode TXmlEngNode::ParentNode() const
       
   634     {
       
   635     //
       
   636     return TXmlEngNode(LIBXML_NODE->parent);
       
   637     }
       
   638 
       
   639 // ---------------------------------------------------------------------------------------------
       
   640 // @return The first child node or NULL if no children
       
   641 // ---------------------------------------------------------------------------------------------
       
   642 //
       
   643 EXPORT_C TXmlEngNode TXmlEngNode::FirstChild() const
       
   644     {
       
   645     //
       
   646     return TXmlEngNode(LIBXML_NODE->children);
       
   647     }
       
   648 
       
   649 // ---------------------------------------------------------------------------------------------
       
   650 // @return The last child node or NULL if no children
       
   651 // ---------------------------------------------------------------------------------------------
       
   652 //
       
   653 EXPORT_C TXmlEngNode TXmlEngNode::LastChild() const
       
   654     {
       
   655     //
       
   656     return TXmlEngNode(LIBXML_NODE->last);
       
   657     }
       
   658 
       
   659 // ---------------------------------------------------------------------------------------------
       
   660 // @return Previous node in a child list or NULL if no sibling before
       
   661 // ---------------------------------------------------------------------------------------------
       
   662 //
       
   663 EXPORT_C TXmlEngNode TXmlEngNode::PreviousSibling() const
       
   664     {
       
   665     if(!LIBXML_NODE->parent)
       
   666         {
       
   667         return NULL;
       
   668         }
       
   669     return TXmlEngNode(LIBXML_NODE->prev);
       
   670     }
       
   671 
       
   672 // ---------------------------------------------------------------------------------------------
       
   673 // @return Following node in a child list or NULL if no sibling after
       
   674 // ---------------------------------------------------------------------------------------------
       
   675 //
       
   676 EXPORT_C TXmlEngNode TXmlEngNode::NextSibling() const
       
   677     {
       
   678     if(!LIBXML_NODE->parent)
       
   679         {
       
   680         return NULL;
       
   681         }
       
   682     return TXmlEngNode(LIBXML_NODE->next);
       
   683     }
       
   684 
       
   685 // ---------------------------------------------------------------------------------------------
       
   686 // @return A document node of the DOM tree this node belongs to
       
   687 // @note    An instance of RXmlEngDocument class returns itself
       
   688 // ---------------------------------------------------------------------------------------------
       
   689 //
       
   690 EXPORT_C RXmlEngDocument TXmlEngNode::OwnerDocument() const
       
   691     {
       
   692     //
       
   693     return RXmlEngDocument(LIBXML_NODE->doc);
       
   694     }
       
   695 
       
   696 // ---------------------------------------------------------------------------------------------
       
   697 // Append a child node.
       
   698 //
       
   699 // This is universal operation for any types of nodes.
       
   700 // Note, that some types of nodes cannot have children and
       
   701 // some types of nodes are not allowed to be children of some other types.
       
   702 //
       
   703 // @return Appended node, which could changed as a result of adding it to
       
   704 // list of child nodes (e.g. text nodes can coalesce together)
       
   705 // ---------------------------------------------------------------------------------------------
       
   706 //
       
   707 EXPORT_C TXmlEngNode TXmlEngNode::AppendChildL(
       
   708     TXmlEngNode aNewChild)
       
   709     {
       
   710     if ( !LIBXML_NODE || aNewChild.IsNull() )
       
   711     	{
       
   712     	User::Leave(KXmlEngErrNullNode);
       
   713     	}
       
   714     //
       
   715     if(aNewChild.ParentNode().IsNull())
       
   716     {
       
   717         aNewChild.OwnerDocument().RemoveOwnership(aNewChild);
       
   718     }
       
   719     else
       
   720     {
       
   721          xmlUnlinkNode(INTERNAL_NODEPTR(aNewChild));
       
   722     }
       
   723    xmlNodePtr   child  =  xmlAddChild(LIBXML_NODE, INTERNAL_NODEPTR(aNewChild));
       
   724 
       
   725     TEST_OOM_FLAG;
       
   726     return child;
       
   727 }
       
   728 
       
   729 // ---------------------------------------------------------------------------------------------
       
   730 // @return Type of the node
       
   731 //
       
   732 // Use NodeType() to find out the type of the node prior to casting object
       
   733 // of TXmlEngNode class to one of its derived subclasses (TXmlEngElement, TXmlEngAttr, TXmlEngTextNode, etc.)
       
   734 //
       
   735 // @see TXmlEngDOMNodeType
       
   736 // ---------------------------------------------------------------------------------------------
       
   737 //
       
   738 EXPORT_C TXmlEngNode::TXmlEngDOMNodeType TXmlEngNode::NodeType() const
       
   739     {
       
   740     //
       
   741     if((TXmlEngDOMNodeType)LIBXML_NODE->type == EText && TEXT_NODE_DATA_TYPE)
       
   742     	{
       
   743 		return (TXmlEngDOMNodeType)(TUint)TEXT_NODE_DATA_TYPE;
       
   744     	}
       
   745 	return (TXmlEngDOMNodeType)LIBXML_NODE->type;
       
   746     }
       
   747 
       
   748 // Note: "" is used for undefined name;  0 means "to use libxml node's name field"
       
   749 static const char* const KNodeNames[]={
       
   750     0,
       
   751     0,                  // EElement                 =       1,
       
   752     0,                  // EAttribute               =       2,
       
   753     "#text",            // EText                    =       3,
       
   754     "#cdata-section",   // ECDATASection            =       4,
       
   755     0,                  // EEntityReference         =       5,
       
   756     "",                 // EEntity                  =       6,
       
   757     0,                  // EProcessingInstruction   =       7,
       
   758     "#comment",         // EComment                 =       8,
       
   759     0,                  // EDocument                =       9,
       
   760     0,                  // EDocumentType            =       10,
       
   761     "#document-fragment", // EDocumentFragment      =       11,
       
   762     "",                 // ENotation                =       12,
       
   763     0,                  // ENamespaceDeclaration    =       18  // not in use
       
   764 	"",					// EBinaryContainer 		= 		 30,
       
   765 	"",					// EChunkContainer	 		= 		 31,
       
   766 	""					// EFileContainer 			= 		 32    
       
   767 };
       
   768 
       
   769 const TInt KNodeNamesSize = sizeof(KNodeNames);
       
   770 
       
   771 // ---------------------------------------------------------------------------------------------
       
   772 // @return Name of the node
       
   773 //
       
   774 // This method generally follows DOM spec :
       
   775 // \verbatim
       
   776 // -------------------------------------------------------------------------------
       
   777 // The values of nodeName, nodeValue, and attributes vary according to the node
       
   778 // type as follows:
       
   779 //
       
   780 // interface              nodeName                nodeValue            attributes
       
   781 // -------------------------------------------------------------------------------
       
   782 // Attr                   = Attr.name              = Attr.value             = null
       
   783 // CDATASection           = "#cdata-section"       = CharacterData.data     = null
       
   784 // Comment                = "#comment"             = CharacterData.data     = null
       
   785 // Document               = "#document"            = null                   = null
       
   786 // DocumentFragment       = "#document-fragment"   = null                   = null
       
   787 // DocumentType           = DocumentType.name      = null                   = null
       
   788 // Element                = Element.tagName        = null           = NamedNodeMap
       
   789 // Entity                 = entity name            = null                   = null
       
   790 // EntityReference        = name of entity referenced  = null               = null
       
   791 // Notation               = notation name          = null                   = null
       
   792 // ProcessingInstruction  = target                 = data                   = null
       
   793 // Text                   = "#text"                = CharacterData.data     = null
       
   794 // -------------------------------------------------------------------------------
       
   795 // \endverbatim
       
   796 // ---------------------------------------------------------------------------------------------
       
   797 //
       
   798 EXPORT_C TPtrC8 TXmlEngNode::Name() const
       
   799     {
       
   800     // DONE: OPTIMIZE: Create static array of names with nodetype as index
       
   801     //                 Use NULL if name is not constant and then use such switch..
       
   802     //
       
   803     TUint type = (TUint) LIBXML_NODE->type;
       
   804     if (type < KNodeNamesSize /sizeof(char*))
       
   805         {
       
   806         const char* KName = KNodeNames[type];
       
   807         if(KName)
       
   808             {
       
   809             return TXmlEngConstString(KName).PtrC8();
       
   810             }
       
   811         return TXmlEngConstString((char*)LIBXML_NODE->name).PtrC8();
       
   812         }
       
   813     return KNullDesC8();
       
   814     }
       
   815 
       
   816 
       
   817 // ---------------------------------------------------------------------------------------------
       
   818 // Fetches value of this node, depending on its type.
       
   819 //
       
   820 // @note It is better to always cast nodes to specific type and then use specific
       
   821 //      method for getting "node value"
       
   822 //
       
   823 // @return Node value
       
   824 // ---------------------------------------------------------------------------------------------
       
   825 //
       
   826 EXPORT_C TPtrC8 TXmlEngNode::Value() const
       
   827     {
       
   828     if (iInternal)
       
   829         {
       
   830         switch(LIBXML_NODE->type)
       
   831             {
       
   832             // The content of first Text child is returned
       
   833             case XML_ATTRIBUTE_NODE:
       
   834                 return AsAttr().Value();
       
   835             // Note: in DOM spec element's value is Null, but we can
       
   836             //       access it: the content of first TXmlEngTextNode child node is returned
       
   837             case XML_ELEMENT_NODE:
       
   838                 return AsElement().Text();
       
   839             // TXmlEngTextNode, TXmlEngCDATASection, TXmlEngProcessingInstruction and Comments store
       
   840             // content in the same way.
       
   841             case XML_TEXT_NODE:
       
   842             case XML_CDATA_SECTION_NODE:
       
   843             case XML_COMMENT_NODE:      
       
   844             case XML_PI_NODE:           
       
   845                 return ((TXmlEngConstString)CAST_XMLCHAR_TO_DOMSTRING(LIBXML_NODE->content)).PtrC8();
       
   846 
       
   847             default:
       
   848                 ;
       
   849             }
       
   850         }
       
   851     return NULL;
       
   852 }
       
   853 // ---------------------------------------------------------------------------------------------
       
   854 // Sets value of this node.
       
   855 // ---------------------------------------------------------------------------------------------
       
   856 //
       
   857 EXPORT_C void TXmlEngNode::SetValueL(
       
   858     const TDesC8& aValue )
       
   859     {
       
   860     if (iInternal)
       
   861         {
       
   862         switch(LIBXML_NODE->type)
       
   863             {
       
   864             // The content of first TXmlEngTextNode child is returned
       
   865             case XML_ATTRIBUTE_NODE:
       
   866             case XML_ELEMENT_NODE:
       
   867                 // Note: in DOM spec element's value is Null, but we can
       
   868                 //       access it: the content of first TXmlEngTextNode child node is returned
       
   869                 AsAttr().SetValueL(aValue); //  same as TXmlEngElement::SetTextL(aValue);
       
   870                 return;
       
   871             // TXmlEngTextNode, TXmlEngCDATASection, TXmlEngProcessingInstruction and Comments store
       
   872             // content in the same way.
       
   873             case XML_TEXT_NODE:
       
   874             case XML_CDATA_SECTION_NODE:
       
   875             case XML_COMMENT_NODE:      
       
   876             case XML_PI_NODE:       
       
   877                 AsText().SetContentsL(aValue);
       
   878                 return;
       
   879             default:
       
   880                 ;
       
   881             }
       
   882         }
       
   883     }
       
   884 
       
   885 
       
   886 // ---------------------------------------------------------------------------------------------
       
   887 // @return Whether the value of the node is presented by only one TXmlEngTextNode node
       
   888 //
       
   889 // If the value is <i>"simple text"</i> then it is possible to access it as TDOMString
       
   890 // without making copy, which combines values of all text nodes and entity reference nodes.
       
   891 //
       
   892 // @see TXmlEngNode::Value(), TXmlEngAttr::Value(), TXmlEngElement::Text()
       
   893 //
       
   894 // This method is applicable to TXmlEngElement and TXmlEngAttr nodes. On other nodes FALSE is returned.
       
   895 //
       
   896 // @note
       
   897 // Values (contents) of TXmlEngComment, TXmlEngCDATASection, TXmlEngTextNode, ProcessingInstuction data are
       
   898 // always "simple".
       
   899 //
       
   900 // When the returned result is FALSE, getting value of the node would not returned
       
   901 // whole contents because of either entity references present in the contents or
       
   902 // the contents is mixed (for TXmlEngElement node). In this case WholeTextContentsCopyL()
       
   903 // should be used.
       
   904 //
       
   905 // @see TXmlEngNode::WholeTextContentsCopyL()
       
   906 // ---------------------------------------------------------------------------------------------
       
   907 //
       
   908 EXPORT_C TBool TXmlEngNode::IsSimpleTextContents() const
       
   909     {
       
   910     if (!LIBXML_NODE)
       
   911         return false;
       
   912     xmlElementType type = LIBXML_NODE->type;
       
   913     if (type == XML_ELEMENT_NODE ||
       
   914         type == XML_ATTRIBUTE_NODE)
       
   915         {
       
   916         xmlNodePtr children = LIBXML_NODE->children;
       
   917 
       
   918         return children  &&  children->type == XML_TEXT_NODE &&
       
   919                !(children->next);
       
   920         }
       
   921     return false; // incorrect type node
       
   922 }
       
   923 
       
   924 // ---------------------------------------------------------------------------------------------
       
   925 // @return   the content of the node
       
   926 //
       
   927 // What is returned depends on the node type.
       
   928 // Method caller is responsible for freeing returned string.
       
   929 // ---------------------------------------------------------------------------------------------
       
   930 //
       
   931 EXPORT_C void TXmlEngNode::WholeTextContentsCopyL(RBuf8& aOutput) const
       
   932     {
       
   933     XE_ASSERT_DEBUG(LIBXML_NODE);
       
   934     //
       
   935     xmlChar* text = xmlNodeGetContent(LIBXML_NODE);
       
   936     if (xmlOOMFlag())
       
   937         { 
       
   938         if(text) 
       
   939             xmlFree(text);
       
   940         OOM_HAPPENED;
       
   941         }
       
   942     xmlCharAssignToRbuf8L(aOutput,text);
       
   943     }
       
   944 // -----------------------------------------------------------------------------
       
   945 
       
   946 EXPORT_C TBool TXmlEngNode::HasChildNodes() const
       
   947     {
       
   948     //
       
   949     return (TBool)LIBXML_NODE->children;
       
   950     }
       
   951 
       
   952 // ---------------------------------------------------------------------------------------------
       
   953 // @return  Namespace URI of a node
       
   954 //           - NULL is returned for elements and attributes that do not
       
   955 //             belong to any namespace.
       
   956 //           - bound namespace URI is returned for namespace declaration nodes (instances of TXmlEngNamespace).
       
   957 //           - NULL is returned to all other types of node.
       
   958 // @note use IsNull() and NotNull() for testing returned result on the subject
       
   959 //      of having some URI
       
   960 // ---------------------------------------------------------------------------------------------
       
   961 //
       
   962 EXPORT_C TPtrC8 TXmlEngNode::NamespaceUri() const
       
   963     {
       
   964     //
       
   965     switch(LIBXML_NODE->type)
       
   966         {
       
   967         case XML_ELEMENT_NODE:
       
   968         case XML_ATTRIBUTE_NODE:
       
   969             return TXmlEngNamespace(LIBXML_NODE->ns).Uri();
       
   970         case XML_NAMESPACE_DECL:
       
   971             return AsNamespace().Uri();
       
   972         default:
       
   973             return NULL;
       
   974         }
       
   975     }
       
   976 
       
   977 // ---------------------------------------------------------------------------------------------
       
   978 // @return  Prefix of a node
       
   979 //           
       
   980 // Returns NULL for elements and attributes that do not have prefix
       
   981 // (node belongs to the default namespace or does not belong to any namespace)
       
   982 // NULL is also returned for all types of node other than TXmlEngElement or TXmlEngAttr
       
   983 // ---------------------------------------------------------------------------------------------
       
   984 //
       
   985 EXPORT_C TPtrC8 TXmlEngNode::Prefix() const
       
   986     {
       
   987     if (LIBXML_NODE->type < XML_TEXT_NODE) // NOTE: XML_ELEMENT_NODE = 1 and XML_ATTRIBUTE_NODE = 2
       
   988         {
       
   989         xmlNs* ns = LIBXML_NODE->ns;
       
   990         if (ns)
       
   991             return ((TXmlEngConstString)CAST_XMLCHAR_TO_DOMSTRING(ns->prefix)).PtrC8();
       
   992         }
       
   993     return KNullDesC8();
       
   994     }
       
   995 
       
   996 
       
   997 // ---------------------------------------------------------------------------------------------
       
   998 // @return    True if the node is TXmlEngElement and has at least one attribute
       
   999 //
       
  1000 // @note Namespace-to-prefix bindings are not attributes.
       
  1001 // ---------------------------------------------------------------------------------------------
       
  1002 //
       
  1003 EXPORT_C TBool TXmlEngNode::HasAttributes() const
       
  1004     {
       
  1005     return iInternal &&
       
  1006            LIBXML_NODE->type == XML_ELEMENT_NODE &&
       
  1007            LIBXML_NODE->properties;
       
  1008     }
       
  1009 
       
  1010 // ---------------------------------------------------------------------------------------------
       
  1011 // Evaluates active base URI for the node by processing xml:base attributes of parents
       
  1012 //
       
  1013 // @return A copy of effective base URI for the node
       
  1014 // @note It's up to the caller to free the string with TDOMString::Free()
       
  1015 // ---------------------------------------------------------------------------------------------
       
  1016 //
       
  1017 EXPORT_C void TXmlEngNode::BaseUriL(RBuf8& aBaseUri) const
       
  1018     {
       
  1019     //
       
  1020     xmlChar* uri = xmlNodeGetBase(LIBXML_NODE->doc, LIBXML_NODE);
       
  1021     if (xmlOOMFlag())
       
  1022         {
       
  1023         if(uri)
       
  1024             xmlFree(uri); // partial construction is possible
       
  1025         OOM_HAPPENED;
       
  1026         }
       
  1027     xmlCharAssignToRbuf8L(aBaseUri,uri);
       
  1028     }
       
  1029 
       
  1030 // ---------------------------------------------------------------------------------------------
       
  1031 // Searches the prefix that is bound to the given aNamespaceUri and
       
  1032 // applicable in the scope of this TXmlEngNode.
       
  1033 //
       
  1034 // @return    A sought prefix or NULL if not found or aNamespaceUri is the default namespace
       
  1035 // @see TXmlEngElement::LookupNamespaceByUri(TXmlEngNode,TDOMString)
       
  1036 // ---------------------------------------------------------------------------------------------
       
  1037 //
       
  1038 EXPORT_C TPtrC8 TXmlEngNode::LookupPrefixL(
       
  1039     const TDesC8& aNamespaceUri ) const
       
  1040     {
       
  1041     if ( !LIBXML_NODE )
       
  1042     	{
       
  1043     	User::Leave(KXmlEngErrNullNode);
       
  1044     	}
       
  1045     //
       
  1046     if (LIBXML_NODE->type == XML_ATTRIBUTE_NODE ||
       
  1047         LIBXML_NODE->type == XML_ELEMENT_NODE)
       
  1048         {
       
  1049         return AsElement().LookupNamespaceByUriL(aNamespaceUri).Prefix();
       
  1050         }
       
  1051 	if(!ParentNode().IsNull())        
       
  1052 		{
       
  1053 		return ParentNode().AsElement().LookupNamespaceByUriL(aNamespaceUri).Prefix();
       
  1054 		}
       
  1055     return KNullDesC8();
       
  1056     }
       
  1057 
       
  1058 // ---------------------------------------------------------------------------------------------
       
  1059 // @return True if given namespace URI is a default one for the node (applicable to elements only)
       
  1060 //
       
  1061 // @note "" or NULL can be used to denote undefined namespace
       
  1062 // ---------------------------------------------------------------------------------------------
       
  1063 //
       
  1064 EXPORT_C TBool TXmlEngNode::IsDefaultNamespaceL(
       
  1065     const TDesC8& aNamespaceUri ) const
       
  1066     {
       
  1067     if (LIBXML_NODE->type == XML_ELEMENT_NODE) // No default namespaces for attributes
       
  1068         {
       
  1069         return !AsElement().DefaultNamespaceL().Uri().Compare(aNamespaceUri);
       
  1070         }
       
  1071     return false;
       
  1072     }
       
  1073 
       
  1074 // ---------------------------------------------------------------------------------------------
       
  1075 // Searches the namespace URI that is bound to the given prefix.
       
  1076 //
       
  1077 // @return    - a sought URI or NULL if the prefix is not bound
       
  1078 // @see TXmlEngElement::LookupNamespaceByPrefix(TXmlEngNode,TDOMString)
       
  1079 // ---------------------------------------------------------------------------------------------
       
  1080 //
       
  1081 EXPORT_C TPtrC8 TXmlEngNode::LookupNamespaceUriL(
       
  1082     const TDesC8& aPrefix ) const
       
  1083     {
       
  1084     if ( !LIBXML_NODE )
       
  1085     	{
       
  1086     	User::Leave(KXmlEngErrNullNode);
       
  1087     	}
       
  1088     //
       
  1089     if (LIBXML_NODE->type == XML_ATTRIBUTE_NODE ||
       
  1090         LIBXML_NODE->type == XML_ELEMENT_NODE)
       
  1091         {
       
  1092         return AsElement().LookupNamespaceByPrefixL(aPrefix).Uri();
       
  1093         }
       
  1094 	if(!ParentNode().IsNull())        
       
  1095 		{
       
  1096 		return ParentNode().AsElement().LookupNamespaceByPrefixL(aPrefix).Uri();
       
  1097 		}
       
  1098     return KNullDesC8();
       
  1099     }
       
  1100 
       
  1101 // ---------------------------------------------------------------------------------------------
       
  1102 // Returns the user data object attached to this node. Ownership is not transferred.
       
  1103 //
       
  1104 // @return Pointer to data object or NULL if it doesn't exist.
       
  1105 // ---------------------------------------------------------------------------------------------
       
  1106 //
       
  1107 EXPORT_C MXmlEngUserData* TXmlEngNode::UserData() const
       
  1108     {
       
  1109     return
       
  1110         (LIBXML_NODE &&
       
  1111             (LIBXML_NODE->type == XML_ATTRIBUTE_NODE ||
       
  1112              LIBXML_NODE->type == XML_ELEMENT_NODE))
       
  1113         ?
       
  1114         static_cast<MXmlEngUserData*>(LIBXML_NODE->_private)
       
  1115         :
       
  1116         NULL;
       
  1117     }
       
  1118 
       
  1119 // ---------------------------------------------------------------------------------------------
       
  1120 // Removes the user data onject attached to this node. Ownership is transferred
       
  1121 // (the object is not deleted).
       
  1122 //
       
  1123 // @return Pointer to data object or NULL if it doesn't exist.
       
  1124 // ---------------------------------------------------------------------------------------------
       
  1125 //
       
  1126 EXPORT_C MXmlEngUserData* TXmlEngNode::RemoveUserData()
       
  1127     {
       
  1128     MXmlEngUserData* data = UserData();
       
  1129     if (data)
       
  1130         {
       
  1131         // node type has been checked by UserData()
       
  1132         LIBXML_NODE->_private = NULL;
       
  1133         }
       
  1134     return data;
       
  1135     }
       
  1136 
       
  1137 // ---------------------------------------------------------------------------------------------
       
  1138 // Attaches a user data object to this node. The ownership of the object is transferred.
       
  1139 // When the (underlying) node is deleted the Destroy method of the MXmlEngUserData class will be
       
  1140 // called. If there already is a user data object associated with this node, it will be
       
  1141 // deleted before attaching the new object. Notet that only TXmlEngElement and Attribute nodes
       
  1142 // currently support this feature.
       
  1143 //
       
  1144 // @param[in] aData Pointer to the data object.
       
  1145 // @return true if successful, false if for example underlying node type doesn't support
       
  1146 // attaching user data.
       
  1147 // ---------------------------------------------------------------------------------------------
       
  1148 //
       
  1149 EXPORT_C TBool TXmlEngNode::AddUserData(
       
  1150     MXmlEngUserData* aData )
       
  1151     {
       
  1152     TBool ret = false;
       
  1153     if (iInternal)
       
  1154         {
       
  1155         if (LIBXML_NODE->type == XML_ATTRIBUTE_NODE ||
       
  1156             LIBXML_NODE->type == XML_ELEMENT_NODE)
       
  1157             {
       
  1158             // release previous data
       
  1159             if (LIBXML_NODE->_private)
       
  1160                 {
       
  1161                 MXmlEngUserData* oldData = RemoveUserData();
       
  1162                 oldData->Destroy();
       
  1163                 }
       
  1164             LIBXML_NODE->_private = aData;
       
  1165             ret = true;
       
  1166             }
       
  1167         }
       
  1168     return ret;
       
  1169     }
       
  1170