xml/xmldomandxpath/src/xmlenginedom/xmlengnode.cpp
changeset 0 e35f40988205
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xml/xmldomandxpath/src/xmlenginedom/xmlengnode.cpp	Thu Dec 17 09:29:21 2009 +0200
@@ -0,0 +1,1170 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Node functions implementation
+//
+
+#include <stdlib.h>
+
+#include <xml/dom/xmlengelement.h>
+#include <xml/dom/xmlengdocument.h>
+#include <xml/dom/xmlengnamespace.h>
+#include <xml/dom/xmlengtext.h>
+#include <xml/dom/xmlenguserdata.h>
+#include <xml/dom/xmlengnodelist.h>
+#include <stdapis/libxml2/libxml2_parser.h>
+#include <stdapis/libxml2/libxml2_globals.h>
+#include <stdapis/libxml2/libxml2_xmlio.h>
+#include "libxml2_xmlsave_private.h"
+#include "libxml2_tree_private.h"
+#include "xmlengdomdefs.h"
+#include <xml/dom/xmlengerrors.h>
+#include <xml/utils/xmlengmem.h>
+#include <xml/utils/xmlengxestrings.h>
+
+// ---------------------------------------------------------------------------------------------
+// Unlinks the internal libxml2's node from double-linked list.
+// Relinks neighbour nodes.The node stays virtually linked to its old neighbours! Use with care!!
+//
+// No checks are made; nor parent's, nor node's properties updated
+// ---------------------------------------------------------------------------------------------
+//
+void TXmlEngNode::DoUnlinkNode()
+    {
+    xmlNodePtr& next = LIBXML_NODE->next;
+    xmlNodePtr& prev = LIBXML_NODE->prev;
+    // Unlink this node; relink neighbors
+    if (prev)
+        {
+        prev->next = next;
+        }
+    else
+        {
+        // Unlinked node is the first in the list
+        // 'children' or 'properties' property of the parent node
+        // must be updated (depending on the type of the node: content node or attribute) 
+        xmlNodePtr& parent = LIBXML_NODE->parent;
+        // Ugly, but works :)
+        xmlNodePtr* first = ((LIBXML_NODE->type ==  XML_ATTRIBUTE_NODE) 
+                              ? reinterpret_cast<xmlNodePtr*>(&(parent->properties)) 
+                              : &(parent->children));
+        *first = next;
+        }
+    if (next)
+        {
+        next->prev = prev;
+        }
+    else
+        {
+        // Unlinked node is the last in the list (of elements or attributes) 
+        // 'last' property of the parent element must be updated  (for content nodes only)
+        if(LIBXML_NODE->type != XML_ATTRIBUTE_NODE)
+            {
+            LIBXML_NODE->parent->last = prev;
+            }
+        }
+    }
+
+
+// ---------------------------------------------------------------------------------------------
+// Inserts the node in a double-linked list of nodes before specified node.
+//
+// No checks are made; nor parent's, nor node's properties updated (except prev/next)
+// ---------------------------------------------------------------------------------------------
+//
+void TXmlEngNode::LinkBefore(TXmlEngNode aTargetNode)
+    {
+    xmlNodePtr node = INTERNAL_NODEPTR(aTargetNode);
+    xmlNodePtr& prev = node->prev;
+    LIBXML_NODE->next = node;
+    LIBXML_NODE->prev = prev;
+    prev->next = LIBXML_NODE;
+    node->prev = LIBXML_NODE;
+    }
+
+// ---------------------------------------------------------------------------------------------
+// Get innerXML string. This method return all content of the node.
+// Output text does not include node markup.
+//
+// @note Returned TString should be freed
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C TInt TXmlEngNode::InnerXmlL(RBuf8& aBuffer)
+    {
+    if(aBuffer.Length())
+        {
+        aBuffer.Close();
+        }
+    if(IsNull())
+    	{
+    	User::Leave(KXmlEngErrWrongUseOfAPI);
+    	} 
+    	
+    if(NodeType() == TXmlEngNode::EDocument)
+        {
+        return OwnerDocument().SaveL(aBuffer, OwnerDocument(), NULL);
+        }
+    aBuffer.FillZ();
+    RXmlEngNodeList<TXmlEngNode> nodeList;
+    RBuf8 tmpStr;
+    GetChildNodes(nodeList);
+    TXmlEngNode tmpNode;
+    while(nodeList.HasNext())
+        {
+        tmpNode = nodeList.Next();
+        tmpNode.OuterXmlL(tmpStr);
+        CleanupClosePushL(tmpStr);
+        if((aBuffer.MaxSize() - aBuffer.Size()) < tmpStr.Size()) 
+            {
+            aBuffer.ReAllocL(aBuffer.MaxSize() + tmpStr.Size() + 1);
+            }
+        aBuffer.Append(tmpStr);
+        CleanupStack::PopAndDestroy();
+        }
+    tmpStr.Close();
+    
+    return aBuffer.Size();
+    }
+    
+// ---------------------------------------------------------------------------------------------
+// Get outerXML string. This method return all content of the node.
+// Output text includes node markup.
+//
+// @note Returned TString should be freed
+//
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C TInt TXmlEngNode::OuterXmlL(RBuf8& aBuffer)
+    {
+    TInt size = -1;
+    if(aBuffer.Length())
+        {
+        aBuffer.Close();
+        }
+    if(IsNull())
+    	{
+    	User::Leave(KXmlEngErrWrongUseOfAPI);
+    	} 
+        
+    if(NodeType() == TXmlEngNode::EDocument)
+        {
+        return OwnerDocument().SaveL(aBuffer, OwnerDocument(), NULL);
+        }
+    
+    xmlSaveCtxt ctxt;
+    xmlOutputBufferPtr buf;
+    
+    /* 
+     * save the content to a temp buffer.
+     */
+    buf = xmlAllocOutputBuffer(NULL);
+    OOM_IF_NULL(buf);
+
+    memset(&ctxt, 0, sizeof(ctxt));
+    ctxt.doc = LIBXML_NODE->doc;
+    ctxt.buf = buf;
+    ctxt.level = 0;
+    ctxt.format = 0; 
+   
+    xmlSaveCtxtInit(&ctxt);
+
+    xmlNodeDumpOutputInternal(&ctxt, LIBXML_NODE);
+    if(xmlOOMFlag())
+        {
+        xmlOutputBufferClose(buf);
+        OOM_HAPPENED;
+        }
+        
+    size = buf->buffer->use;
+    if(size > 0)
+        {
+        // frees any previous contents of aBuffer argument
+        aBuffer.Assign(buf->buffer->content,size,size);
+        // To prevent it from freeing
+        buf->buffer->content = NULL; 
+        }
+    xmlOutputBufferClose(buf);
+    
+    // Leaves with KErrNoMemory
+    TEST_OOM_FLAG; 
+    if (size < 0)
+        {
+        XmlEngLeaveL(KXmlEngErrNegativeOutputSize);
+        }        
+        
+    return size;
+    }
+
+// ---------------------------------------------------------------------------------------------
+// Moves the node to become the first in the list of its siblings
+// Node is expected to have a parent.
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C void TXmlEngNode::SetAsFirstSibling()
+    {
+    if (LIBXML_NODE->type == XML_NAMESPACE_DECL)
+        {
+        return;
+        }
+    xmlNodePtr& prev = LIBXML_NODE->prev;
+    if (prev)
+        {
+        DoUnlinkNode();
+        // Insert as first
+        prev = NULL;
+        xmlNodePtr& parent = LIBXML_NODE->parent;
+        // Ugly, but works :)
+        xmlNodePtr* first = ((LIBXML_NODE->type == XML_ATTRIBUTE_NODE)
+                              ? reinterpret_cast<xmlNodePtr*>(&(parent->properties))
+                              : &(parent->children));
+        
+        (*first)->prev = LIBXML_NODE;
+        LIBXML_NODE->next = *first;
+        *first = LIBXML_NODE;
+        // NOTE: it is possible to cope without having parent defined,
+        //       it will need to iterate through sibling list to find the first one
+        }
+    }
+
+
+// ---------------------------------------------------------------------------------------------
+// Moves the node to become the last in the list of its siblings
+// Node is expected to have a parent.
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C void TXmlEngNode::SetAsLastSibling()
+    {
+    if (LIBXML_NODE->type == XML_NAMESPACE_DECL)
+        {
+        return;
+        }
+    xmlNodePtr& next = LIBXML_NODE->next;
+    if (next)
+        {
+        DoUnlinkNode(); 
+        xmlNodePtr& parent = LIBXML_NODE->parent;
+        xmlNodePtr& prev = LIBXML_NODE->prev;
+        if (LIBXML_NODE->type != XML_ATTRIBUTE_NODE)
+            {
+            if (!prev)
+                parent->children = next;
+            prev = parent->last;
+            parent->last->next = LIBXML_NODE;
+            parent->last = LIBXML_NODE;
+            }
+        else
+            {
+            if (!prev)
+                parent->properties = (xmlAttrPtr)next;
+            prev = next; // NOTE: 'next' is always different than NULL
+            while (prev->next)
+                prev = prev->next;
+            prev->next = LIBXML_NODE;
+            }
+        next = NULL;
+        }
+    }
+
+// ---------------------------------------------------------------------------------------------
+// Moves the node in the list of sibling nodes before another node
+// Node is expected to have a parent.
+// Do nothing if aSiblingNode is not one of node's siblings
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C void TXmlEngNode::MoveBeforeSibling(
+    TXmlEngNode aSiblingNode )
+    {
+    if (LIBXML_NODE->type == XML_NAMESPACE_DECL)
+        {
+        return;
+        }
+    xmlNodePtr node = INTERNAL_NODEPTR(aSiblingNode);
+    if (!node->prev)
+        {
+        SetAsFirstSibling();
+        }
+    else
+        {
+        DoUnlinkNode();
+        LinkBefore(aSiblingNode);
+        }
+    }
+
+// ---------------------------------------------------------------------------------------------
+// Moves the node in the list of sibling nodes after another node
+// Node is expected to have a parent.
+// Do nothing if aSiblingNode is not one of the node's siblings
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C void TXmlEngNode::MoveAfterSibling(
+    TXmlEngNode aSiblingNode)
+    {
+    if (LIBXML_NODE->type == XML_NAMESPACE_DECL)
+        {
+        return;
+        }
+    xmlNodePtr node = INTERNAL_NODEPTR(aSiblingNode);
+    if (!node->next)
+        {
+        SetAsLastSibling();
+        }
+    else
+        {
+        DoUnlinkNode();
+        LinkBefore(aSiblingNode.NextSibling());
+        }   
+    }
+
+// ---------------------------------------------------------------------------------------------
+// Retrieves a "handle" for namespace declaration that applies to the node's namespace
+// Note: DOM specs do not consider namespace declarations as a kind of nodes
+// This API adds TXmlEngNamespace type of nodes, which is derived from TXmlEngNode.
+//
+// @return    Object that represents namespace declaration and prefix binding that
+//            act on the node; returns NULL object (check using TXmlEngNamespace.IsNull()
+//            or TXmlEngNamespace.NotNull()) if no namespace associated
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C TXmlEngNamespace TXmlEngNode::NamespaceDeclaration() const
+    {
+    //
+    switch(LIBXML_NODE->type)
+        {
+        case XML_ELEMENT_NODE:
+        case XML_ATTRIBUTE_NODE:
+            return TXmlEngNamespace(LIBXML_NODE->ns);
+        default:
+            return NULL;
+        }
+    }
+
+// ---------------------------------------------------------------------------------------------
+// Clones the node completely: all attributes and namespace declarations (for TXmlEngElement nodes),
+// values and children nodes are copied as well.
+// 
+// Document nodes cannot be copied with this method: RXmlEngDocument::CloneDocumentL() must be used.
+//
+// @return Complete copy of a node or leaves.
+// @note    The node should not be NULL!
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C TXmlEngNode TXmlEngNode::CopyL() const
+    {
+    if ( !LIBXML_NODE )
+    	{
+    	User::Leave(KXmlEngErrNullNode);
+    	}
+    // Copying of RXmlEngDocument should be made with RXmlEngDocument::CloneDocumentL()
+    if(NodeType() == TXmlEngNode::EDocument)
+        return NULL;
+    //
+    xmlNodePtr copy = xmlStaticCopyNode(
+                            LIBXML_NODE, 
+                            NULL /* doc */, 
+                            NULL /* parent */, 
+                            1);
+    //
+    if (xmlOOMFlag())
+        {
+        if(copy)
+            xmlFreeNode(copy); // it may be a partial copy
+        OOM_HAPPENED;
+        }
+    TXmlEngNode ncopy(copy);
+    OwnerDocument().TakeOwnership(ncopy);
+    return ncopy;
+    }
+
+// ---------------------------------------------------------------------------------------------
+// Creates a deep copy of the node and appends the subtree as a new child
+// to the provided parent node.
+//
+// @return Created copy of the node after linking it into the target document tree.
+// @note Document nodes cannot be copied with this method; use RXmlEngDocument::CloneDocumentL()
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C TXmlEngNode TXmlEngNode::CopyToL(
+    TXmlEngNode aParent ) const
+    {
+    if ( !LIBXML_NODE )
+    	{
+    	User::Leave(KXmlEngErrNullNode);
+    	}
+    if ( LIBXML_NODE->type == XML_DOCUMENT_NODE )
+    	{
+    	User::Leave(KXmlEngErrWrongUseOfAPI);
+    	}
+   if ( aParent.IsNull() )
+    	{
+    	User::Leave(KXmlEngErrNullNode);
+    	}
+    //
+    TXmlEngNode ncopy = CopyL();
+    return aParent.AppendChildL(ncopy);
+    }
+
+// ---------------------------------------------------------------------------------------------
+// Detaches a node from document tree
+//
+// @return This node, which is already not a part of any document
+// @note    Remember to use ReconcileNamespacesL() later, if extracted node (subtree)
+//         contains references to namespace declarations outside of the subtree.
+// @see     ReconcileNamespacesL()
+// @note    The document, from which the node is being unlinked, becomes an owner of the node
+//         until it is linked elsewhere.
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C TXmlEngNode TXmlEngNode::Unlink()
+    {   
+    //
+    if(LIBXML_NODE && ParentNode().NotNull())
+        {
+        RXmlEngDocument tmpDoc = OwnerDocument();
+        xmlUnlinkNode(LIBXML_NODE);
+        tmpDoc.TakeOwnership(*this);
+        }
+    return *this;
+    }
+
+// ---------------------------------------------------------------------------------------------
+// Unlinks the node and destroys it; all child nodes are destroyed as well and all memory is freed
+//
+// @note  Document nodes cannot be "removed" with this method, uses RXmlEngDocument-specific methods.
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C void TXmlEngNode::Remove()
+    {
+    //
+    if (!LIBXML_NODE || LIBXML_NODE->type == XML_DOCUMENT_NODE)
+        {
+        return;
+        }
+    if(ParentNode().NotNull())
+        {
+        xmlUnlinkNode(LIBXML_NODE);
+        }
+    else
+        {
+        OwnerDocument().RemoveOwnership(*this);
+        }
+    if (LIBXML_NODE->type != XML_ATTRIBUTE_NODE)
+        {
+     xmlFreeNode(LIBXML_NODE);
+        }
+	else
+		{
+		xmlFreeProp(INTERNAL_ATTRPTR(iInternal));
+		}
+
+    iInternal = 0;
+    }
+
+// ---------------------------------------------------------------------------------------------
+// Ensures that namespaces referred to in the node and its descendants are
+// in the scope the node.
+//
+// * This method checks that all the namespaces declared within the given
+// * tree are properly declared. This is needed for example after Copy or Unlink
+// * and then Append operations. The subtree may still hold pointers to
+// * namespace declarations outside the subtree or they may be invalid/masked. As much
+// * as possible the function try to reuse the existing namespaces found in
+// * the new environment. If not possible, the new namespaces are redeclared
+// * on the top of the subtree.
+//
+// This method should be used after unlinking nodes and inserting to another
+// document tree or to a another part of the original tree, if some nodes of the subtree
+// are remove from the scope of a namespace declaration they refer to.
+//
+// When node is unlinked, it may still refer to namespace declarations from the previous location.
+// It is important to reconcile subtree's namespaces if previous parent tree is to be destroyed.
+// On the other hand, if the parent tree is not changed before pasting its unlinked part into another
+// tree, then reconciliation is needed only after paste operation.
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C void TXmlEngNode::ReconcileNamespacesL()
+    {
+    xmlReconciliateNs(LIBXML_NODE->doc, LIBXML_NODE);
+    TEST_OOM_FLAG;
+    }
+
+// ---------------------------------------------------------------------------------------------
+// Current node is replaced with another node (subtree).
+//
+// The replacement node is linked into document tree instead of this node.
+// The replaced node is destroyed.
+//
+// @see SubstituteForL(TXmlEngNode)
+//
+// In both cases the argument node is unlinked from its previous location
+// (which can be NONE, i.e. not linked; SAME or ANOTHER document tree).
+//
+// @note Replacement of a node with NULL TXmlEngNode is legal and equivalent to removing the node.
+// @note Not applicable to document nodes
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C void TXmlEngNode::ReplaceWithL(TXmlEngNode aNode)
+    {
+    if ( !LIBXML_NODE )
+    	{
+    	User::Leave(KXmlEngErrNullNode);
+    	}
+    if ( LIBXML_NODE->type == XML_DOCUMENT_NODE )
+    	{
+    	User::Leave(KXmlEngErrWrongUseOfAPI);
+    	}
+
+    if(aNode.ParentNode().IsNull())
+        {
+    	// new node is unlinked, so owned by some (maybe other than this) document
+	    // previous ownership must be withdrawn
+        aNode.OwnerDocument().RemoveOwnership(aNode);
+        }
+    if(ParentNode().IsNull())
+        {
+    	// This node is unlinked, thus owned by its document
+	    // Ownership must be withdrawn before removing the node
+	    RXmlEngDocument doc = OwnerDocument();
+	    doc.RemoveOwnership(*this);
+	    // Also, there is no place to link the new node! 
+	    // So it will be unlinked, but owned by this node's document 
+        doc.TakeOwnership(aNode);
+        }
+    // put new node instead of 'this' node: it works with all combinations of linked/unlinked states of the nodes
+    xmlFreeNode(xmlReplaceNode(LIBXML_NODE, INTERNAL_NODEPTR(aNode)));
+    }
+
+EXPORT_C void TXmlEngNode::ReplaceWith(TXmlEngNode aNode)
+    {
+    if(!LIBXML_NODE || LIBXML_NODE->type == XML_DOCUMENT_NODE)
+        return;
+    if(aNode.ParentNode().IsNull())
+        {
+    	// new node is unlinked, so owned by some (maybe other than this) document
+	    // previous ownership must be withdrawn
+        aNode.OwnerDocument().RemoveOwnership(aNode);
+        }
+    if(ParentNode().IsNull())
+        {
+    	// This node is unlinked, thus owned by its document
+	    // Ownership must be withdrawn before removing the node
+	    RXmlEngDocument doc = OwnerDocument();
+	    doc.RemoveOwnership(*this);
+	    // Also, there is no place to link the new node! 
+	    // So it will be unlinked, but owned by this node's document 
+        doc.TakeOwnership(aNode);
+        }
+    // put new node instead of 'this' node: it works with all combinations of linked/unlinked states of the nodes
+    xmlFreeNode(xmlReplaceNode(LIBXML_NODE, INTERNAL_NODEPTR(aNode)));
+    }
+
+// ---------------------------------------------------------------------------------------------
+// Another node is put instead of the current node.
+//
+// Does the same as ReplaceWith(TXmlEngNode) but does not free node and just returns it.
+//
+// @return Current node after unlinking it from document tree
+// @see ReplaceWith(TXmlEngNode)
+//
+// In both cases the argument node is unlinked from its previous location
+// (which can be NONE, i.e. not linked; SAME or ANOTHER document tree)
+//
+// It is possible to use NULL TXmlEngNode object as an argument. In such case
+// no new node will be put instead of unlinked one.
+//
+// @note Not applicable to document nodes
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C TXmlEngNode TXmlEngNode::SubstituteForL(TXmlEngNode aNode)
+    {
+    if ( !LIBXML_NODE )
+    	{
+    	User::Leave(KXmlEngErrNullNode);
+    	}
+    if ( LIBXML_NODE->type == XML_DOCUMENT_NODE )
+    	{
+    	User::Leave(KXmlEngErrWrongUseOfAPI);
+    	}
+    //
+    if(aNode.ParentNode().IsNull())
+        {
+      	// new node is unlinked, so owned by other document
+    	// it must not be owned to be linked
+        aNode.OwnerDocument().RemoveOwnership(aNode);
+        }
+    if(ParentNode().IsNull())
+        {
+    	// this node is unlinked - nowhere to link new node: this node's document will own it
+        OwnerDocument().TakeOwnership(aNode);
+	    // this node will stay as it is
+	    // new node will be unlinked by call to xmlReplaceNode
+        }        
+    TXmlEngNode tmpNode = TXmlEngNode(xmlReplaceNode(LIBXML_NODE, INTERNAL_NODEPTR(aNode)));
+    aNode.OwnerDocument().TakeOwnership(tmpNode);
+    return tmpNode;
+    }
+
+// ---------------------------------------------------------------------------------------------
+// DOM Level 3 Core
+// ---------------------------------------------------------------------------------------------
+
+// ---------------------------------------------------------------------------------------------
+//Initializes a node list with all children of the node
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C void TXmlEngNode::GetChildNodes(RXmlEngNodeList<TXmlEngNode>& aList) const
+    {
+    aList.Open(LIBXML_NODE->children, TDOMNODETYPENONE);
+    }
+
+// ---------------------------------------------------------------------------------------------
+// @return Parent node of the node or NULL if no parent
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C TXmlEngNode TXmlEngNode::ParentNode() const
+    {
+    //
+    return TXmlEngNode(LIBXML_NODE->parent);
+    }
+
+// ---------------------------------------------------------------------------------------------
+// @return The first child node or NULL if no children
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C TXmlEngNode TXmlEngNode::FirstChild() const
+    {
+    //
+    return TXmlEngNode(LIBXML_NODE->children);
+    }
+
+// ---------------------------------------------------------------------------------------------
+// @return The last child node or NULL if no children
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C TXmlEngNode TXmlEngNode::LastChild() const
+    {
+    //
+    return TXmlEngNode(LIBXML_NODE->last);
+    }
+
+// ---------------------------------------------------------------------------------------------
+// @return Previous node in a child list or NULL if no sibling before
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C TXmlEngNode TXmlEngNode::PreviousSibling() const
+    {
+    if(!LIBXML_NODE->parent)
+        {
+        return NULL;
+        }
+    return TXmlEngNode(LIBXML_NODE->prev);
+    }
+
+// ---------------------------------------------------------------------------------------------
+// @return Following node in a child list or NULL if no sibling after
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C TXmlEngNode TXmlEngNode::NextSibling() const
+    {
+    if(!LIBXML_NODE->parent)
+        {
+        return NULL;
+        }
+    return TXmlEngNode(LIBXML_NODE->next);
+    }
+
+// ---------------------------------------------------------------------------------------------
+// @return A document node of the DOM tree this node belongs to
+// @note    An instance of RXmlEngDocument class returns itself
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C RXmlEngDocument TXmlEngNode::OwnerDocument() const
+    {
+    //
+    return RXmlEngDocument(LIBXML_NODE->doc);
+    }
+
+// ---------------------------------------------------------------------------------------------
+// Append a child node.
+//
+// This is universal operation for any types of nodes.
+// Note, that some types of nodes cannot have children and
+// some types of nodes are not allowed to be children of some other types.
+//
+// @return Appended node, which could changed as a result of adding it to
+// list of child nodes (e.g. text nodes can coalesce together)
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C TXmlEngNode TXmlEngNode::AppendChildL(
+    TXmlEngNode aNewChild)
+    {
+    if ( !LIBXML_NODE || aNewChild.IsNull() )
+    	{
+    	User::Leave(KXmlEngErrNullNode);
+    	}
+    //
+    if(aNewChild.ParentNode().IsNull())
+    {
+        aNewChild.OwnerDocument().RemoveOwnership(aNewChild);
+    }
+    else
+    {
+         xmlUnlinkNode(INTERNAL_NODEPTR(aNewChild));
+    }
+   xmlNodePtr   child  =  xmlAddChild(LIBXML_NODE, INTERNAL_NODEPTR(aNewChild));
+
+    TEST_OOM_FLAG;
+    return child;
+}
+
+// ---------------------------------------------------------------------------------------------
+// @return Type of the node
+//
+// Use NodeType() to find out the type of the node prior to casting object
+// of TXmlEngNode class to one of its derived subclasses (TXmlEngElement, TXmlEngAttr, TXmlEngTextNode, etc.)
+//
+// @see TXmlEngDOMNodeType
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C TXmlEngNode::TXmlEngDOMNodeType TXmlEngNode::NodeType() const
+    {
+    //
+    if((TXmlEngDOMNodeType)LIBXML_NODE->type == EText && TEXT_NODE_DATA_TYPE)
+    	{
+		return (TXmlEngDOMNodeType)(TUint)TEXT_NODE_DATA_TYPE;
+    	}
+	return (TXmlEngDOMNodeType)LIBXML_NODE->type;
+    }
+
+// Note: "" is used for undefined name;  0 means "to use libxml node's name field"
+static const char* const KNodeNames[]={
+    0,
+    0,                  // EElement                 =       1,
+    0,                  // EAttribute               =       2,
+    "#text",            // EText                    =       3,
+    "#cdata-section",   // ECDATASection            =       4,
+    0,                  // EEntityReference         =       5,
+    "",                 // EEntity                  =       6,
+    0,                  // EProcessingInstruction   =       7,
+    "#comment",         // EComment                 =       8,
+    0,                  // EDocument                =       9,
+    0,                  // EDocumentType            =       10,
+    "#document-fragment", // EDocumentFragment      =       11,
+    "",                 // ENotation                =       12,
+    0,                  // ENamespaceDeclaration    =       18  // not in use
+	"",					// EBinaryContainer 		= 		 30,
+	"",					// EChunkContainer	 		= 		 31,
+	""					// EFileContainer 			= 		 32    
+};
+
+const TInt KNodeNamesSize = sizeof(KNodeNames);
+
+// ---------------------------------------------------------------------------------------------
+// @return Name of the node
+//
+// This method generally follows DOM spec :
+// \verbatim
+// -------------------------------------------------------------------------------
+// The values of nodeName, nodeValue, and attributes vary according to the node
+// type as follows:
+//
+// interface              nodeName                nodeValue            attributes
+// -------------------------------------------------------------------------------
+// Attr                   = Attr.name              = Attr.value             = null
+// CDATASection           = "#cdata-section"       = CharacterData.data     = null
+// Comment                = "#comment"             = CharacterData.data     = null
+// Document               = "#document"            = null                   = null
+// DocumentFragment       = "#document-fragment"   = null                   = null
+// DocumentType           = DocumentType.name      = null                   = null
+// Element                = Element.tagName        = null           = NamedNodeMap
+// Entity                 = entity name            = null                   = null
+// EntityReference        = name of entity referenced  = null               = null
+// Notation               = notation name          = null                   = null
+// ProcessingInstruction  = target                 = data                   = null
+// Text                   = "#text"                = CharacterData.data     = null
+// -------------------------------------------------------------------------------
+// \endverbatim
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C TPtrC8 TXmlEngNode::Name() const
+    {
+    // DONE: OPTIMIZE: Create static array of names with nodetype as index
+    //                 Use NULL if name is not constant and then use such switch..
+    //
+    TUint type = (TUint) LIBXML_NODE->type;
+    if (type < KNodeNamesSize /sizeof(char*))
+        {
+        const char* KName = KNodeNames[type];
+        if(KName)
+            {
+            return TXmlEngConstString(KName).PtrC8();
+            }
+        return TXmlEngConstString((char*)LIBXML_NODE->name).PtrC8();
+        }
+    return KNullDesC8();
+    }
+
+
+// ---------------------------------------------------------------------------------------------
+// Fetches value of this node, depending on its type.
+//
+// @note It is better to always cast nodes to specific type and then use specific
+//      method for getting "node value"
+//
+// @return Node value
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C TPtrC8 TXmlEngNode::Value() const
+    {
+    if (iInternal)
+        {
+        switch(LIBXML_NODE->type)
+            {
+            // The content of first Text child is returned
+            case XML_ATTRIBUTE_NODE:
+                return AsAttr().Value();
+            // Note: in DOM spec element's value is Null, but we can
+            //       access it: the content of first TXmlEngTextNode child node is returned
+            case XML_ELEMENT_NODE:
+                return AsElement().Text();
+            // TXmlEngTextNode, TXmlEngCDATASection, TXmlEngProcessingInstruction and Comments store
+            // content in the same way.
+            case XML_TEXT_NODE:
+            case XML_CDATA_SECTION_NODE:
+            case XML_COMMENT_NODE:      
+            case XML_PI_NODE:           
+                return ((TXmlEngConstString)CAST_XMLCHAR_TO_DOMSTRING(LIBXML_NODE->content)).PtrC8();
+
+            default:
+                ;
+            }
+        }
+    return NULL;
+}
+// ---------------------------------------------------------------------------------------------
+// Sets value of this node.
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C void TXmlEngNode::SetValueL(
+    const TDesC8& aValue )
+    {
+    if (iInternal)
+        {
+        switch(LIBXML_NODE->type)
+            {
+            // The content of first TXmlEngTextNode child is returned
+            case XML_ATTRIBUTE_NODE:
+            case XML_ELEMENT_NODE:
+                // Note: in DOM spec element's value is Null, but we can
+                //       access it: the content of first TXmlEngTextNode child node is returned
+                AsAttr().SetValueL(aValue); //  same as TXmlEngElement::SetTextL(aValue);
+                return;
+            // TXmlEngTextNode, TXmlEngCDATASection, TXmlEngProcessingInstruction and Comments store
+            // content in the same way.
+            case XML_TEXT_NODE:
+            case XML_CDATA_SECTION_NODE:
+            case XML_COMMENT_NODE:      
+            case XML_PI_NODE:       
+                AsText().SetContentsL(aValue);
+                return;
+            default:
+                ;
+            }
+        }
+    }
+
+
+// ---------------------------------------------------------------------------------------------
+// @return Whether the value of the node is presented by only one TXmlEngTextNode node
+//
+// If the value is <i>"simple text"</i> then it is possible to access it as TDOMString
+// without making copy, which combines values of all text nodes and entity reference nodes.
+//
+// @see TXmlEngNode::Value(), TXmlEngAttr::Value(), TXmlEngElement::Text()
+//
+// This method is applicable to TXmlEngElement and TXmlEngAttr nodes. On other nodes FALSE is returned.
+//
+// @note
+// Values (contents) of TXmlEngComment, TXmlEngCDATASection, TXmlEngTextNode, ProcessingInstuction data are
+// always "simple".
+//
+// When the returned result is FALSE, getting value of the node would not returned
+// whole contents because of either entity references present in the contents or
+// the contents is mixed (for TXmlEngElement node). In this case WholeTextContentsCopyL()
+// should be used.
+//
+// @see TXmlEngNode::WholeTextContentsCopyL()
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C TBool TXmlEngNode::IsSimpleTextContents() const
+    {
+    if (!LIBXML_NODE)
+        return false;
+    xmlElementType type = LIBXML_NODE->type;
+    if (type == XML_ELEMENT_NODE ||
+        type == XML_ATTRIBUTE_NODE)
+        {
+        xmlNodePtr children = LIBXML_NODE->children;
+
+        return children  &&  children->type == XML_TEXT_NODE &&
+               !(children->next);
+        }
+    return false; // incorrect type node
+}
+
+// ---------------------------------------------------------------------------------------------
+// @return   the content of the node
+//
+// What is returned depends on the node type.
+// Method caller is responsible for freeing returned string.
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C void TXmlEngNode::WholeTextContentsCopyL(RBuf8& aOutput) const
+    {
+    XE_ASSERT_DEBUG(LIBXML_NODE);
+    //
+    xmlChar* text = xmlNodeGetContent(LIBXML_NODE);
+    if (xmlOOMFlag())
+        { 
+        if(text) 
+            xmlFree(text);
+        OOM_HAPPENED;
+        }
+    xmlCharAssignToRbuf8L(aOutput,text);
+    }
+// -----------------------------------------------------------------------------
+
+EXPORT_C TBool TXmlEngNode::HasChildNodes() const
+    {
+    //
+    return (TBool)LIBXML_NODE->children;
+    }
+
+// ---------------------------------------------------------------------------------------------
+// @return  Namespace URI of a node
+//           - NULL is returned for elements and attributes that do not
+//             belong to any namespace.
+//           - bound namespace URI is returned for namespace declaration nodes (instances of TXmlEngNamespace).
+//           - NULL is returned to all other types of node.
+// @note use IsNull() and NotNull() for testing returned result on the subject
+//      of having some URI
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C TPtrC8 TXmlEngNode::NamespaceUri() const
+    {
+    //
+    switch(LIBXML_NODE->type)
+        {
+        case XML_ELEMENT_NODE:
+        case XML_ATTRIBUTE_NODE:
+            return TXmlEngNamespace(LIBXML_NODE->ns).Uri();
+        case XML_NAMESPACE_DECL:
+            return AsNamespace().Uri();
+        default:
+            return NULL;
+        }
+    }
+
+// ---------------------------------------------------------------------------------------------
+// @return  Prefix of a node
+//           
+// Returns NULL for elements and attributes that do not have prefix
+// (node belongs to the default namespace or does not belong to any namespace)
+// NULL is also returned for all types of node other than TXmlEngElement or TXmlEngAttr
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C TPtrC8 TXmlEngNode::Prefix() const
+    {
+    if (LIBXML_NODE->type < XML_TEXT_NODE) // NOTE: XML_ELEMENT_NODE = 1 and XML_ATTRIBUTE_NODE = 2
+        {
+        xmlNs* ns = LIBXML_NODE->ns;
+        if (ns)
+            return ((TXmlEngConstString)CAST_XMLCHAR_TO_DOMSTRING(ns->prefix)).PtrC8();
+        }
+    return KNullDesC8();
+    }
+
+
+// ---------------------------------------------------------------------------------------------
+// @return    True if the node is TXmlEngElement and has at least one attribute
+//
+// @note Namespace-to-prefix bindings are not attributes.
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C TBool TXmlEngNode::HasAttributes() const
+    {
+    return iInternal &&
+           LIBXML_NODE->type == XML_ELEMENT_NODE &&
+           LIBXML_NODE->properties;
+    }
+
+// ---------------------------------------------------------------------------------------------
+// Evaluates active base URI for the node by processing xml:base attributes of parents
+//
+// @return A copy of effective base URI for the node
+// @note It's up to the caller to free the string with TDOMString::Free()
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C void TXmlEngNode::BaseUriL(RBuf8& aBaseUri) const
+    {
+    //
+    xmlChar* uri = xmlNodeGetBase(LIBXML_NODE->doc, LIBXML_NODE);
+    if (xmlOOMFlag())
+        {
+        if(uri)
+            xmlFree(uri); // partial construction is possible
+        OOM_HAPPENED;
+        }
+    xmlCharAssignToRbuf8L(aBaseUri,uri);
+    }
+
+// ---------------------------------------------------------------------------------------------
+// Searches the prefix that is bound to the given aNamespaceUri and
+// applicable in the scope of this TXmlEngNode.
+//
+// @return    A sought prefix or NULL if not found or aNamespaceUri is the default namespace
+// @see TXmlEngElement::LookupNamespaceByUri(TXmlEngNode,TDOMString)
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C TPtrC8 TXmlEngNode::LookupPrefixL(
+    const TDesC8& aNamespaceUri ) const
+    {
+    if ( !LIBXML_NODE )
+    	{
+    	User::Leave(KXmlEngErrNullNode);
+    	}
+    //
+    if (LIBXML_NODE->type == XML_ATTRIBUTE_NODE ||
+        LIBXML_NODE->type == XML_ELEMENT_NODE)
+        {
+        return AsElement().LookupNamespaceByUriL(aNamespaceUri).Prefix();
+        }
+	if(!ParentNode().IsNull())        
+		{
+		return ParentNode().AsElement().LookupNamespaceByUriL(aNamespaceUri).Prefix();
+		}
+    return KNullDesC8();
+    }
+
+// ---------------------------------------------------------------------------------------------
+// @return True if given namespace URI is a default one for the node (applicable to elements only)
+//
+// @note "" or NULL can be used to denote undefined namespace
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C TBool TXmlEngNode::IsDefaultNamespaceL(
+    const TDesC8& aNamespaceUri ) const
+    {
+    if (LIBXML_NODE->type == XML_ELEMENT_NODE) // No default namespaces for attributes
+        {
+        return !AsElement().DefaultNamespaceL().Uri().Compare(aNamespaceUri);
+        }
+    return false;
+    }
+
+// ---------------------------------------------------------------------------------------------
+// Searches the namespace URI that is bound to the given prefix.
+//
+// @return    - a sought URI or NULL if the prefix is not bound
+// @see TXmlEngElement::LookupNamespaceByPrefix(TXmlEngNode,TDOMString)
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C TPtrC8 TXmlEngNode::LookupNamespaceUriL(
+    const TDesC8& aPrefix ) const
+    {
+    if ( !LIBXML_NODE )
+    	{
+    	User::Leave(KXmlEngErrNullNode);
+    	}
+    //
+    if (LIBXML_NODE->type == XML_ATTRIBUTE_NODE ||
+        LIBXML_NODE->type == XML_ELEMENT_NODE)
+        {
+        return AsElement().LookupNamespaceByPrefixL(aPrefix).Uri();
+        }
+	if(!ParentNode().IsNull())        
+		{
+		return ParentNode().AsElement().LookupNamespaceByPrefixL(aPrefix).Uri();
+		}
+    return KNullDesC8();
+    }
+
+// ---------------------------------------------------------------------------------------------
+// Returns the user data object attached to this node. Ownership is not transferred.
+//
+// @return Pointer to data object or NULL if it doesn't exist.
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C MXmlEngUserData* TXmlEngNode::UserData() const
+    {
+    return
+        (LIBXML_NODE &&
+            (LIBXML_NODE->type == XML_ATTRIBUTE_NODE ||
+             LIBXML_NODE->type == XML_ELEMENT_NODE))
+        ?
+        static_cast<MXmlEngUserData*>(LIBXML_NODE->_private)
+        :
+        NULL;
+    }
+
+// ---------------------------------------------------------------------------------------------
+// Removes the user data onject attached to this node. Ownership is transferred
+// (the object is not deleted).
+//
+// @return Pointer to data object or NULL if it doesn't exist.
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C MXmlEngUserData* TXmlEngNode::RemoveUserData()
+    {
+    MXmlEngUserData* data = UserData();
+    if (data)
+        {
+        // node type has been checked by UserData()
+        LIBXML_NODE->_private = NULL;
+        }
+    return data;
+    }
+
+// ---------------------------------------------------------------------------------------------
+// Attaches a user data object to this node. The ownership of the object is transferred.
+// When the (underlying) node is deleted the Destroy method of the MXmlEngUserData class will be
+// called. If there already is a user data object associated with this node, it will be
+// deleted before attaching the new object. Notet that only TXmlEngElement and Attribute nodes
+// currently support this feature.
+//
+// @param[in] aData Pointer to the data object.
+// @return true if successful, false if for example underlying node type doesn't support
+// attaching user data.
+// ---------------------------------------------------------------------------------------------
+//
+EXPORT_C TBool TXmlEngNode::AddUserData(
+    MXmlEngUserData* aData )
+    {
+    TBool ret = false;
+    if (iInternal)
+        {
+        if (LIBXML_NODE->type == XML_ATTRIBUTE_NODE ||
+            LIBXML_NODE->type == XML_ELEMENT_NODE)
+            {
+            // release previous data
+            if (LIBXML_NODE->_private)
+                {
+                MXmlEngUserData* oldData = RemoveUserData();
+                oldData->Destroy();
+                }
+            LIBXML_NODE->_private = aData;
+            ret = true;
+            }
+        }
+    return ret;
+    }
+