From 3ea9fec8a54e90afed63d627c010004ccddb3c8d Mon Sep 17 00:00:00 2001
From: Tinny Ng <tng@apache.org>
Date: Wed, 12 Jun 2002 18:29:31 +0000
Subject: [PATCH] DOM L3: Add DOMNode::get/setUserData

git-svn-id: https://svn.apache.org/repos/asf/xerces/c/trunk@173823 13f79535-47bb-0310-9956-ffa450edef68
---
 src/xercesc/dom/DOMCharacterData.hpp          |   1 +
 src/xercesc/dom/DOMNode.hpp                   |  45 ++
 src/xercesc/dom/impl/DOMAttrImpl.cpp          |  65 +--
 src/xercesc/dom/impl/DOMAttrNSImpl.cpp        |   4 +-
 src/xercesc/dom/impl/DOMCDATASectionImpl.cpp  |  81 +--
 src/xercesc/dom/impl/DOMCommentImpl.cpp       |  81 +--
 src/xercesc/dom/impl/DOMDeepNodeListPool.hpp  |   1 -
 .../dom/impl/DOMDocumentFragmentImpl.cpp      |  55 +-
 src/xercesc/dom/impl/DOMDocumentImpl.cpp      | 509 ++++++++++--------
 src/xercesc/dom/impl/DOMDocumentImpl.hpp      | 155 +++---
 src/xercesc/dom/impl/DOMDocumentTypeImpl.cpp  |  67 +--
 src/xercesc/dom/impl/DOMElementImpl.cpp       |  88 +--
 src/xercesc/dom/impl/DOMElementNSImpl.cpp     |   4 +-
 src/xercesc/dom/impl/DOMEntityImpl.cpp        |  71 +--
 .../dom/impl/DOMEntityReferenceImpl.cpp       |  55 +-
 src/xercesc/dom/impl/DOMNamedNodeMapImpl.cpp  |   3 -
 src/xercesc/dom/impl/DOMNodeImpl.cpp          |  73 ++-
 src/xercesc/dom/impl/DOMNodeImpl.hpp          | 171 +++---
 src/xercesc/dom/impl/DOMNotationImpl.cpp      |  55 +-
 .../dom/impl/DOMProcessingInstructionImpl.cpp |  53 +-
 src/xercesc/dom/impl/DOMTextImpl.cpp          |  81 +--
 src/xercesc/dom/impl/XSDElementNSImpl.cpp     |   4 +-
 22 files changed, 961 insertions(+), 761 deletions(-)

diff --git a/src/xercesc/dom/DOMCharacterData.hpp b/src/xercesc/dom/DOMCharacterData.hpp
index a220ed4c3..2ced5588b 100644
--- a/src/xercesc/dom/DOMCharacterData.hpp
+++ b/src/xercesc/dom/DOMCharacterData.hpp
@@ -78,6 +78,7 @@
  * the following, the term 16-bit units is used whenever necessary to
  * indicate that indexing on DOMCharacterData is done in 16-bit units.
  * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>.
+ * @since DOM Level 1
  */
 class CDOM_EXPORT DOMCharacterData: public DOMNode {
 
diff --git a/src/xercesc/dom/DOMNode.hpp b/src/xercesc/dom/DOMNode.hpp
index 95ca71941..eff971815 100644
--- a/src/xercesc/dom/DOMNode.hpp
+++ b/src/xercesc/dom/DOMNode.hpp
@@ -67,6 +67,7 @@
 class DOMDocument;
 class DOMNamedNodeMap;
 class DOMNodeList;
+class DOMUserDataHandler;
 
 /**
  * The <code>DOMNode</code> interface is the primary datatype for the entire
@@ -609,6 +610,50 @@ public:
     virtual bool              hasAttributes() const = 0;
     //@}
 
+    /** @name Functions introduced in DOM Level 3. */
+    //@{
+    /**
+     * Associate an object to a key on this node. The object can later be
+     * retrieved from this node by calling <code>getUserData</code> with the
+     * same key.
+     *
+     * Deletion of the user data remains the responsibility of the
+     * application program; it will not be automatically deleted when
+     * the nodes themselves are reclaimed.
+     *
+     * Both the parameter <code>data</code> and the returned object are
+     * void pointer, it is applications' responsibility to keep track of
+     * their original type.  Casting them to the wrong type may result
+     * unexpected behavior.
+     *
+     * @param key The key to associate the object to.
+     * @param data The object to associate to the given key, or
+     *   <code>null</code> to remove any existing association to that key.
+     * @param handler The handler to associate to that key, or
+     *   <code>null</code>.
+     * @return Returns the void* object previously associated to
+     *   the given key on this node, or <code>null</code> if there was none.
+     * @see getUserData
+     *
+     * @since DOM Level 3
+     */
+    virtual void*             setUserData(const XMLCh* key,
+                                          void* data,
+                                          DOMUserDataHandler* handler) = 0;
+
+    /**
+     * Retrieves the object associated to a key on a this node. The object
+     * must first have been set to this node by calling
+     * <code>setUserData</code> with the same key.
+     * @param key The key the object is associated to.
+     * @return Returns the <code>DOMObject</code> associated to the given key
+     *   on this node, or <code>null</code> if there was none.
+     * @see setUserData
+     * @since DOM Level 3
+     */
+    virtual void*             getUserData(const XMLCh* key) const = 0;
+    //@}
+
 
 };
 
diff --git a/src/xercesc/dom/impl/DOMAttrImpl.cpp b/src/xercesc/dom/impl/DOMAttrImpl.cpp
index 42998d7b2..439884c5a 100644
--- a/src/xercesc/dom/impl/DOMAttrImpl.cpp
+++ b/src/xercesc/dom/impl/DOMAttrImpl.cpp
@@ -80,11 +80,11 @@ DOMAttrImpl::DOMAttrImpl(const DOMAttrImpl &other, bool deep)
     : fNode(other.fNode), fParent (other.fParent)
 {
     fName = other.fName;
-	
-	if (other.fNode.isSpecified())
-		fNode.isSpecified(true);
-	else
-		fNode.isSpecified(false);
+
+    if (other.fNode.isSpecified())
+        fNode.isSpecified(true);
+    else
+        fNode.isSpecified(false);
 
     if (other.fNode.isIdAttr())
     {
@@ -93,7 +93,7 @@ DOMAttrImpl::DOMAttrImpl(const DOMAttrImpl &other, bool deep)
         doc->getNodeIDMap()->add(this);
     }
 
-	fParent.cloneChildren(&other);
+    fParent.cloneChildren(&other);
 };
 
 
@@ -103,7 +103,9 @@ DOMAttrImpl::~DOMAttrImpl() {
 
 DOMNode * DOMAttrImpl::cloneNode(bool deep) const
 {
-    return new (this->getOwnerDocument()) DOMAttrImpl(*this, deep);
+    DOMNode* newNode = new (this->getOwnerDocument()) DOMAttrImpl(*this, deep);
+    fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode);
+    return newNode;
 };
 
 
@@ -240,29 +242,32 @@ void DOMAttrImpl::setOwnerElement(DOMElement *ownerElem)
 
 
 
-           DOMNode          *DOMAttrImpl::appendChild(DOMNode *newChild)        {return fParent.appendChild (newChild); };
-           DOMNamedNodeMap  *DOMAttrImpl::getAttributes() const 			       {return fNode.getAttributes (); };
-           DOMNodeList      *DOMAttrImpl::getChildNodes() const 			       {return fParent.getChildNodes (); };
-           DOMNode          *DOMAttrImpl::getFirstChild() const 			       {return fParent.getFirstChild (); };
-           DOMNode          *DOMAttrImpl::getLastChild() const 		           {return fParent.getLastChild (); };
-     const XMLCh              *DOMAttrImpl::getLocalName() const                    {return fNode.getLocalName (); };
-     const XMLCh              *DOMAttrImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); };
-           DOMNode          *DOMAttrImpl::getNextSibling() const                  {return fNode.getNextSibling (); };
-           DOMDocument      *DOMAttrImpl::getOwnerDocument() const                {return fNode.getOwnerDocument (); };
-     const XMLCh              *DOMAttrImpl::getPrefix() const                       {return fNode.getPrefix (); };
-           DOMNode          *DOMAttrImpl::getParentNode() const                   {return fNode.getParentNode (); };
-           DOMNode          *DOMAttrImpl::getPreviousSibling() const              {return fNode.getPreviousSibling (); };
-           bool                DOMAttrImpl::hasChildNodes() const                   {return fParent.hasChildNodes (); };
-           DOMNode          *DOMAttrImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
-                                                                                   {return fParent.insertBefore (newChild, refChild); };
-           void                DOMAttrImpl::normalize()                             {fParent.normalize (); };
-           DOMNode          *DOMAttrImpl::removeChild(DOMNode *oldChild)        {return fParent.removeChild (oldChild); };
-           DOMNode          *DOMAttrImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
-                                                                                   {return fParent.replaceChild (newChild, oldChild); };
-           bool                DOMAttrImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
-                                                                                   {return fNode.isSupported (feature, version); };
-           void                DOMAttrImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); };
-           bool                DOMAttrImpl::hasAttributes() const                   {return fNode.hasAttributes(); };
+           DOMNode*         DOMAttrImpl::appendChild(DOMNode *newChild)          {return fParent.appendChild (newChild); };
+           DOMNamedNodeMap* DOMAttrImpl::getAttributes() const                   {return fNode.getAttributes (); };
+           DOMNodeList*     DOMAttrImpl::getChildNodes() const                   {return fParent.getChildNodes (); };
+           DOMNode*         DOMAttrImpl::getFirstChild() const                   {return fParent.getFirstChild (); };
+           DOMNode*         DOMAttrImpl::getLastChild() const                    {return fParent.getLastChild (); };
+     const XMLCh*           DOMAttrImpl::getLocalName() const                    {return fNode.getLocalName (); };
+     const XMLCh*           DOMAttrImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); };
+           DOMNode*         DOMAttrImpl::getNextSibling() const                  {return fNode.getNextSibling (); };
+           DOMDocument*     DOMAttrImpl::getOwnerDocument() const                {return fNode.getOwnerDocument (); };
+     const XMLCh*           DOMAttrImpl::getPrefix() const                       {return fNode.getPrefix (); };
+           DOMNode*         DOMAttrImpl::getParentNode() const                   {return fNode.getParentNode (); };
+           DOMNode*         DOMAttrImpl::getPreviousSibling() const              {return fNode.getPreviousSibling (); };
+           bool             DOMAttrImpl::hasChildNodes() const                   {return fParent.hasChildNodes (); };
+           DOMNode*         DOMAttrImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
+                                                                                 {return fParent.insertBefore (newChild, refChild); };
+           void             DOMAttrImpl::normalize()                             {fParent.normalize (); };
+           DOMNode*         DOMAttrImpl::removeChild(DOMNode *oldChild)          {return fParent.removeChild (oldChild); };
+           DOMNode*         DOMAttrImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
+                                                                                 {return fParent.replaceChild (newChild, oldChild); };
+           bool             DOMAttrImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
+                                                                                 {return fNode.isSupported (feature, version); };
+           void             DOMAttrImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); };
+           bool             DOMAttrImpl::hasAttributes() const                   {return fNode.hasAttributes(); };
+           void*            DOMAttrImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler)
+                                                                                 {return fNode.setUserData(key, data, handler); };
+           void*            DOMAttrImpl::getUserData(const XMLCh* key) const     {return fNode.getUserData(key); };
 
 
 
diff --git a/src/xercesc/dom/impl/DOMAttrNSImpl.cpp b/src/xercesc/dom/impl/DOMAttrNSImpl.cpp
index cad20107b..a7e9ed24b 100644
--- a/src/xercesc/dom/impl/DOMAttrNSImpl.cpp
+++ b/src/xercesc/dom/impl/DOMAttrNSImpl.cpp
@@ -129,7 +129,9 @@ DOMAttrImpl(other, deep)
 
 DOMNode * DOMAttrNSImpl::cloneNode(bool deep) const
 {
-    return new (getOwnerDocument()) DOMAttrNSImpl(*this, deep);
+    DOMNode* newNode = new (getOwnerDocument()) DOMAttrNSImpl(*this, deep);
+    fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode);
+    return newNode;
 };
 
 const XMLCh * DOMAttrNSImpl::getNamespaceURI() const
diff --git a/src/xercesc/dom/impl/DOMCDATASectionImpl.cpp b/src/xercesc/dom/impl/DOMCDATASectionImpl.cpp
index 0b3896777..f75984186 100644
--- a/src/xercesc/dom/impl/DOMCDATASectionImpl.cpp
+++ b/src/xercesc/dom/impl/DOMCDATASectionImpl.cpp
@@ -90,7 +90,9 @@ DOMCDATASectionImpl::~DOMCDATASectionImpl()
 
 DOMNode  *DOMCDATASectionImpl::cloneNode(bool deep) const
 {
-    return new (this->getOwnerDocument()) DOMCDATASectionImpl(*this, deep);
+    DOMNode* newNode = new (this->getOwnerDocument()) DOMCDATASectionImpl(*this, deep);
+    fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode);
+    return newNode;
 };
 
 
@@ -162,30 +164,33 @@ DOMText *DOMCDATASectionImpl::splitText(XMLSize_t offset)
 //
 //  Delegation stubs for other DOM_Node inherited functions.
 //
-           DOMNode          *DOMCDATASectionImpl::appendChild(DOMNode *newChild)        {return fParent.appendChild (newChild); };
-           DOMNamedNodeMap  *DOMCDATASectionImpl::getAttributes() const 			        {return fNode.getAttributes (); };
-           DOMNodeList      *DOMCDATASectionImpl::getChildNodes() const 			        {return fParent.getChildNodes (); };
-           DOMNode          *DOMCDATASectionImpl::getFirstChild() const 			        {return fParent.getFirstChild (); };
-           DOMNode          *DOMCDATASectionImpl::getLastChild() const 		            {return fParent.getLastChild (); };
-     const XMLCh              *DOMCDATASectionImpl::getLocalName() const                    {return fNode.getLocalName (); };
-     const XMLCh              *DOMCDATASectionImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); };
-           DOMNode          *DOMCDATASectionImpl::getNextSibling() const                  {return fChild.getNextSibling (); };
-     const XMLCh              *DOMCDATASectionImpl::getNodeValue() const                    {return fCharacterData.getNodeValue (); };
-           DOMDocument      *DOMCDATASectionImpl::getOwnerDocument() const                {return fNode.getOwnerDocument (); };
-     const XMLCh              *DOMCDATASectionImpl::getPrefix() const                       {return fNode.getPrefix (); };
-           DOMNode          *DOMCDATASectionImpl::getParentNode() const                   {return fChild.getParentNode (this); };
-           DOMNode          *DOMCDATASectionImpl::getPreviousSibling() const              {return fChild.getPreviousSibling (this); };
-           bool                DOMCDATASectionImpl::hasChildNodes() const                   {return fParent.hasChildNodes (); };
-           DOMNode          *DOMCDATASectionImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
-                                                                            {return fParent.insertBefore (newChild, refChild); };
-           void                DOMCDATASectionImpl::normalize()                             {fNode.normalize (); };
-           DOMNode          *DOMCDATASectionImpl::removeChild(DOMNode *oldChild)        {return fParent.removeChild (oldChild); };
-           DOMNode          *DOMCDATASectionImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
-                                                                            {return fParent.replaceChild (newChild, oldChild); };
-           bool                DOMCDATASectionImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
-                                                                            {return fNode.isSupported (feature, version); };
-           void                DOMCDATASectionImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); };
-           bool                DOMCDATASectionImpl::hasAttributes() const                   {return fNode.hasAttributes(); };
+           DOMNode*         DOMCDATASectionImpl::appendChild(DOMNode *newChild)          {return fParent.appendChild (newChild); };
+           DOMNamedNodeMap* DOMCDATASectionImpl::getAttributes() const                   {return fNode.getAttributes (); };
+           DOMNodeList*     DOMCDATASectionImpl::getChildNodes() const                   {return fParent.getChildNodes (); };
+           DOMNode*         DOMCDATASectionImpl::getFirstChild() const                   {return fParent.getFirstChild (); };
+           DOMNode*         DOMCDATASectionImpl::getLastChild() const                    {return fParent.getLastChild (); };
+     const XMLCh*           DOMCDATASectionImpl::getLocalName() const                    {return fNode.getLocalName (); };
+     const XMLCh*           DOMCDATASectionImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); };
+           DOMNode*         DOMCDATASectionImpl::getNextSibling() const                  {return fChild.getNextSibling (); };
+     const XMLCh*           DOMCDATASectionImpl::getNodeValue() const                    {return fCharacterData.getNodeValue (); };
+           DOMDocument*     DOMCDATASectionImpl::getOwnerDocument() const                {return fNode.getOwnerDocument (); };
+     const XMLCh*           DOMCDATASectionImpl::getPrefix() const                       {return fNode.getPrefix (); };
+           DOMNode*         DOMCDATASectionImpl::getParentNode() const                   {return fChild.getParentNode (this); };
+           DOMNode*         DOMCDATASectionImpl::getPreviousSibling() const              {return fChild.getPreviousSibling (this); };
+           bool             DOMCDATASectionImpl::hasChildNodes() const                   {return fParent.hasChildNodes (); };
+           DOMNode*         DOMCDATASectionImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
+                                                                                         {return fParent.insertBefore (newChild, refChild); };
+           void             DOMCDATASectionImpl::normalize()                             {fNode.normalize (); };
+           DOMNode*         DOMCDATASectionImpl::removeChild(DOMNode *oldChild)          {return fParent.removeChild (oldChild); };
+           DOMNode*         DOMCDATASectionImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
+                                                                                         {return fParent.replaceChild (newChild, oldChild); };
+           bool             DOMCDATASectionImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
+                                                                                         {return fNode.isSupported (feature, version); };
+           void             DOMCDATASectionImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); };
+           bool             DOMCDATASectionImpl::hasAttributes() const                   {return fNode.hasAttributes(); };
+           void*            DOMCDATASectionImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler)
+                                                                                         {return fNode.setUserData(key, data, handler); };
+           void*            DOMCDATASectionImpl::getUserData(const XMLCh* key) const     {return fNode.getUserData(key); };
 
 
 //
@@ -193,18 +198,18 @@ DOMText *DOMCDATASectionImpl::splitText(XMLSize_t offset)
 //
 
 
-     const XMLCh * DOMCDATASectionImpl::getData() const                  {return fCharacterData.getData();};
-     XMLSize_t  DOMCDATASectionImpl::getLength() const                {return fCharacterData.getLength();};
-     const XMLCh * DOMCDATASectionImpl::substringData(XMLSize_t offset, XMLSize_t count) const
-                                                                {return fCharacterData.substringData(this, offset, count);};
-     void          DOMCDATASectionImpl::appendData(const XMLCh *arg)     {fCharacterData.appendData(this, arg);};
-     void          DOMCDATASectionImpl::insertData(XMLSize_t offset, const  XMLCh *arg)
-                                                                {fCharacterData.insertData(this, offset, arg);};
-     void          DOMCDATASectionImpl::deleteData(XMLSize_t offset, XMLSize_t count)
-                                                                {fCharacterData.deleteData(this, offset, count);};
-     void          DOMCDATASectionImpl::replaceData(XMLSize_t offset, XMLSize_t count, const XMLCh *arg)
-                                                                {fCharacterData.replaceData(this, offset, count, arg);};
-     void          DOMCDATASectionImpl::setData(const XMLCh *data)       {fCharacterData.setData(this, data);};
-     void          DOMCDATASectionImpl::setNodeValue(const XMLCh  *nodeValue)   {fCharacterData.setNodeValue (this, nodeValue); };
+           const XMLCh*     DOMCDATASectionImpl::getData() const                         {return fCharacterData.getData();};
+           XMLSize_t        DOMCDATASectionImpl::getLength() const                       {return fCharacterData.getLength();};
+           const XMLCh*     DOMCDATASectionImpl::substringData(XMLSize_t offset, XMLSize_t count) const
+                                                                                         {return fCharacterData.substringData(this, offset, count);};
+           void             DOMCDATASectionImpl::appendData(const XMLCh *arg)            {fCharacterData.appendData(this, arg);};
+           void             DOMCDATASectionImpl::insertData(XMLSize_t offset, const  XMLCh *arg)
+                                                                                         {fCharacterData.insertData(this, offset, arg);};
+           void             DOMCDATASectionImpl::deleteData(XMLSize_t offset, XMLSize_t count)
+                                                                                         {fCharacterData.deleteData(this, offset, count);};
+           void             DOMCDATASectionImpl::replaceData(XMLSize_t offset, XMLSize_t count, const XMLCh *arg)
+                                                                                         {fCharacterData.replaceData(this, offset, count, arg);};
+           void             DOMCDATASectionImpl::setData(const XMLCh *data)              {fCharacterData.setData(this, data);};
+           void             DOMCDATASectionImpl::setNodeValue(const XMLCh  *nodeValue)   {fCharacterData.setNodeValue (this, nodeValue); };
 
 
diff --git a/src/xercesc/dom/impl/DOMCommentImpl.cpp b/src/xercesc/dom/impl/DOMCommentImpl.cpp
index ecff360ae..51709f211 100644
--- a/src/xercesc/dom/impl/DOMCommentImpl.cpp
+++ b/src/xercesc/dom/impl/DOMCommentImpl.cpp
@@ -89,7 +89,9 @@ DOMCommentImpl::~DOMCommentImpl() {
 
 DOMNode * DOMCommentImpl::cloneNode(bool deep) const
 {
-    return new (getOwnerDocument()) DOMCommentImpl(*this, deep);
+    DOMNode* newNode = new (getOwnerDocument()) DOMCommentImpl(*this, deep);
+    fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode);
+    return newNode;
 };
 
 
@@ -106,30 +108,33 @@ short DOMCommentImpl::getNodeType() const {
 
 
 
-           DOMNode          *DOMCommentImpl::appendChild(DOMNode *newChild)        {return fNode.appendChild (newChild); };
-           DOMNamedNodeMap  *DOMCommentImpl::getAttributes() const 			        {return fNode.getAttributes (); };
-           DOMNodeList      *DOMCommentImpl::getChildNodes() const 			        {return fNode.getChildNodes (); };
-           DOMNode          *DOMCommentImpl::getFirstChild() const 			        {return fNode.getFirstChild (); };
-           DOMNode          *DOMCommentImpl::getLastChild() const 		            {return fNode.getLastChild (); };
-     const XMLCh              *DOMCommentImpl::getLocalName() const                    {return fNode.getLocalName (); };
-     const XMLCh              *DOMCommentImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); };
-           DOMNode          *DOMCommentImpl::getNextSibling() const                  {return fChild.getNextSibling (); };
-     const XMLCh              *DOMCommentImpl::getNodeValue() const                    {return fCharacterData.getNodeValue (); };
-           DOMDocument      *DOMCommentImpl::getOwnerDocument() const                {return fNode.getOwnerDocument (); };
-     const XMLCh              *DOMCommentImpl::getPrefix() const                       {return fNode.getPrefix (); };
-           DOMNode          *DOMCommentImpl::getParentNode() const                   {return fChild.getParentNode (this); };
-           DOMNode          *DOMCommentImpl::getPreviousSibling() const              {return fChild.getPreviousSibling (this); };
-           bool                DOMCommentImpl::hasChildNodes() const                   {return fNode.hasChildNodes (); };
-           DOMNode          *DOMCommentImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
-                                                                            {return fNode.insertBefore (newChild, refChild); };
-           void                DOMCommentImpl::normalize()                             {fNode.normalize (); };
-           DOMNode          *DOMCommentImpl::removeChild(DOMNode *oldChild)        {return fNode.removeChild (oldChild); };
-           DOMNode          *DOMCommentImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
-                                                                            {return fNode.replaceChild (newChild, oldChild); };
-           bool                DOMCommentImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
-                                                                            {return fNode.isSupported (feature, version); };
-           void                DOMCommentImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); };
-           bool                DOMCommentImpl::hasAttributes() const                   {return fNode.hasAttributes(); };
+           DOMNode*         DOMCommentImpl::appendChild(DOMNode *newChild)          {return fNode.appendChild (newChild); };
+           DOMNamedNodeMap* DOMCommentImpl::getAttributes() const                   {return fNode.getAttributes (); };
+           DOMNodeList*     DOMCommentImpl::getChildNodes() const                   {return fNode.getChildNodes (); };
+           DOMNode*         DOMCommentImpl::getFirstChild() const                   {return fNode.getFirstChild (); };
+           DOMNode*         DOMCommentImpl::getLastChild() const                    {return fNode.getLastChild (); };
+     const XMLCh*           DOMCommentImpl::getLocalName() const                    {return fNode.getLocalName (); };
+     const XMLCh*           DOMCommentImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); };
+           DOMNode*         DOMCommentImpl::getNextSibling() const                  {return fChild.getNextSibling (); };
+     const XMLCh*           DOMCommentImpl::getNodeValue() const                    {return fCharacterData.getNodeValue (); };
+           DOMDocument*     DOMCommentImpl::getOwnerDocument() const                {return fNode.getOwnerDocument (); };
+     const XMLCh*           DOMCommentImpl::getPrefix() const                       {return fNode.getPrefix (); };
+           DOMNode*         DOMCommentImpl::getParentNode() const                   {return fChild.getParentNode (this); };
+           DOMNode*         DOMCommentImpl::getPreviousSibling() const              {return fChild.getPreviousSibling (this); };
+           bool             DOMCommentImpl::hasChildNodes() const                   {return fNode.hasChildNodes (); };
+           DOMNode*         DOMCommentImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
+                                                                                    {return fNode.insertBefore (newChild, refChild); };
+           void             DOMCommentImpl::normalize()                             {fNode.normalize (); };
+           DOMNode*         DOMCommentImpl::removeChild(DOMNode *oldChild)          {return fNode.removeChild (oldChild); };
+           DOMNode*         DOMCommentImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
+                                                                                    {return fNode.replaceChild (newChild, oldChild); };
+           bool             DOMCommentImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
+                                                                                    {return fNode.isSupported (feature, version); };
+           void             DOMCommentImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); };
+           bool             DOMCommentImpl::hasAttributes() const                   {return fNode.hasAttributes(); };
+           void*            DOMCommentImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler)
+                                                                                    {return fNode.setUserData(key, data, handler); };
+           void*            DOMCommentImpl::getUserData(const XMLCh* key) const     {return fNode.getUserData(key); };
 
 
 //
@@ -137,17 +142,17 @@ short DOMCommentImpl::getNodeType() const {
 //
 
 
-     const XMLCh * DOMCommentImpl::getData() const                  {return fCharacterData.getData();};
-     XMLSize_t  DOMCommentImpl::getLength() const                {return fCharacterData.getLength();};
-     const XMLCh * DOMCommentImpl::substringData(XMLSize_t offset, XMLSize_t count) const
-                                                                {return fCharacterData.substringData(this, offset, count);};
-     void          DOMCommentImpl::appendData(const XMLCh *arg)     {fCharacterData.appendData(this, arg);};
-     void          DOMCommentImpl::insertData(XMLSize_t offset, const  XMLCh *arg)
-                                                                {fCharacterData.insertData(this, offset, arg);};
-     void          DOMCommentImpl::deleteData(XMLSize_t offset, XMLSize_t count)
-                                                                {fCharacterData.deleteData(this, offset, count);};
-     void          DOMCommentImpl::replaceData(XMLSize_t offset, XMLSize_t count, const XMLCh *arg)
-                                                                {fCharacterData.replaceData(this, offset, count, arg);};
-     void          DOMCommentImpl::setData(const XMLCh *data)       {fCharacterData.setData(this, data);};
-     void          DOMCommentImpl::setNodeValue(const XMLCh  *nodeValue)   {fCharacterData.setNodeValue (this, nodeValue); };
+           const XMLCh*     DOMCommentImpl::getData() const                         {return fCharacterData.getData();};
+           XMLSize_t        DOMCommentImpl::getLength() const                       {return fCharacterData.getLength();};
+           const XMLCh*     DOMCommentImpl::substringData(XMLSize_t offset, XMLSize_t count) const
+                                                                                    {return fCharacterData.substringData(this, offset, count);};
+           void             DOMCommentImpl::appendData(const XMLCh *arg)            {fCharacterData.appendData(this, arg);};
+           void             DOMCommentImpl::insertData(XMLSize_t offset, const  XMLCh *arg)
+                                                                                    {fCharacterData.insertData(this, offset, arg);};
+           void             DOMCommentImpl::deleteData(XMLSize_t offset, XMLSize_t count)
+                                                                                    {fCharacterData.deleteData(this, offset, count);};
+           void             DOMCommentImpl::replaceData(XMLSize_t offset, XMLSize_t count, const XMLCh *arg)
+                                                                                    {fCharacterData.replaceData(this, offset, count, arg);};
+           void             DOMCommentImpl::setData(const XMLCh *data)              {fCharacterData.setData(this, data);};
+           void             DOMCommentImpl::setNodeValue(const XMLCh  *nodeValue)   {fCharacterData.setNodeValue (this, nodeValue); };
 
diff --git a/src/xercesc/dom/impl/DOMDeepNodeListPool.hpp b/src/xercesc/dom/impl/DOMDeepNodeListPool.hpp
index a5c044f6a..368dd1b48 100644
--- a/src/xercesc/dom/impl/DOMDeepNodeListPool.hpp
+++ b/src/xercesc/dom/impl/DOMDeepNodeListPool.hpp
@@ -72,7 +72,6 @@
 
 
 #include <xercesc/util/XercesDefs.hpp>
-#include <xercesc/util/KeyValuePair.hpp>
 #include <xercesc/util/HashBase.hpp>
 #include <xercesc/util/IllegalArgumentException.hpp>
 #include <xercesc/util/NoSuchElementException.hpp>
diff --git a/src/xercesc/dom/impl/DOMDocumentFragmentImpl.cpp b/src/xercesc/dom/impl/DOMDocumentFragmentImpl.cpp
index 84979d914..dafcc3dbd 100644
--- a/src/xercesc/dom/impl/DOMDocumentFragmentImpl.cpp
+++ b/src/xercesc/dom/impl/DOMDocumentFragmentImpl.cpp
@@ -91,7 +91,9 @@ DOMDocumentFragmentImpl::~DOMDocumentFragmentImpl()
 
 DOMNode *DOMDocumentFragmentImpl::cloneNode(bool deep) const
 {
-    return new (castToNodeImpl(this)->getOwnerDocument()) DOMDocumentFragmentImpl(*this, deep);
+    DOMNode* newNode = new (castToNodeImpl(this)->getOwnerDocument()) DOMDocumentFragmentImpl(*this, deep);
+    fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode);
+    return newNode;
 };
 
 
@@ -117,28 +119,31 @@ void DOMDocumentFragmentImpl::setNodeValue(const XMLCh *x)
 //
 //  Delegation stubs for inherited functions.
 //
-           DOMNode          *DOMDocumentFragmentImpl::appendChild(DOMNode *newChild)        {return fParent.appendChild (newChild); };
-           DOMNamedNodeMap  *DOMDocumentFragmentImpl::getAttributes() const 			        {return fNode.getAttributes (); };
-           DOMNodeList      *DOMDocumentFragmentImpl::getChildNodes() const 			        {return fParent.getChildNodes (); };
-           DOMNode          *DOMDocumentFragmentImpl::getFirstChild() const 			        {return fParent.getFirstChild (); };
-           DOMNode          *DOMDocumentFragmentImpl::getLastChild() const 		            {return fParent.getLastChild (); };
-     const XMLCh              *DOMDocumentFragmentImpl::getLocalName() const                    {return fNode.getLocalName (); };
-     const XMLCh              *DOMDocumentFragmentImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); };
-           DOMNode          *DOMDocumentFragmentImpl::getNextSibling() const                  {return fNode.getNextSibling (); };
-     const XMLCh              *DOMDocumentFragmentImpl::getNodeValue() const                    {return fNode.getNodeValue (); };
-           DOMDocument      *DOMDocumentFragmentImpl::getOwnerDocument() const                {return fNode.getOwnerDocument (); };
-     const XMLCh              *DOMDocumentFragmentImpl::getPrefix() const                       {return fNode.getPrefix (); };
-           DOMNode          *DOMDocumentFragmentImpl::getParentNode() const                   {return fNode.getParentNode (); };
-           DOMNode          *DOMDocumentFragmentImpl::getPreviousSibling() const              {return fNode.getPreviousSibling (); };
-           bool                DOMDocumentFragmentImpl::hasChildNodes() const                   {return fParent.hasChildNodes (); };
-           DOMNode          *DOMDocumentFragmentImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
-                                                                            {return fParent.insertBefore (newChild, refChild); };
-           void                DOMDocumentFragmentImpl::normalize()                             {fParent.normalize (); };
-           DOMNode          *DOMDocumentFragmentImpl::removeChild(DOMNode *oldChild)        {return fParent.removeChild (oldChild); };
-           DOMNode          *DOMDocumentFragmentImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
-                                                                            {return fParent.replaceChild (newChild, oldChild); };
-           bool                DOMDocumentFragmentImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
-                                                                            {return fNode.isSupported (feature, version); };
-           void                DOMDocumentFragmentImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); };
-           bool                DOMDocumentFragmentImpl::hasAttributes() const                   {return fNode.hasAttributes(); };
+           DOMNode*         DOMDocumentFragmentImpl::appendChild(DOMNode *newChild)          {return fParent.appendChild (newChild); };
+           DOMNamedNodeMap* DOMDocumentFragmentImpl::getAttributes() const                   {return fNode.getAttributes (); };
+           DOMNodeList*     DOMDocumentFragmentImpl::getChildNodes() const                   {return fParent.getChildNodes (); };
+           DOMNode*         DOMDocumentFragmentImpl::getFirstChild() const                   {return fParent.getFirstChild (); };
+           DOMNode*         DOMDocumentFragmentImpl::getLastChild() const                    {return fParent.getLastChild (); };
+     const XMLCh*           DOMDocumentFragmentImpl::getLocalName() const                    {return fNode.getLocalName (); };
+     const XMLCh*           DOMDocumentFragmentImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); };
+           DOMNode*         DOMDocumentFragmentImpl::getNextSibling() const                  {return fNode.getNextSibling (); };
+     const XMLCh*           DOMDocumentFragmentImpl::getNodeValue() const                    {return fNode.getNodeValue (); };
+           DOMDocument*     DOMDocumentFragmentImpl::getOwnerDocument() const                {return fNode.getOwnerDocument (); };
+     const XMLCh*           DOMDocumentFragmentImpl::getPrefix() const                       {return fNode.getPrefix (); };
+           DOMNode*         DOMDocumentFragmentImpl::getParentNode() const                   {return fNode.getParentNode (); };
+           DOMNode*         DOMDocumentFragmentImpl::getPreviousSibling() const              {return fNode.getPreviousSibling (); };
+           bool             DOMDocumentFragmentImpl::hasChildNodes() const                   {return fParent.hasChildNodes (); };
+           DOMNode*         DOMDocumentFragmentImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
+                                                                                             {return fParent.insertBefore (newChild, refChild); };
+           void             DOMDocumentFragmentImpl::normalize()                             {fParent.normalize (); };
+           DOMNode*         DOMDocumentFragmentImpl::removeChild(DOMNode *oldChild)          {return fParent.removeChild (oldChild); };
+           DOMNode*         DOMDocumentFragmentImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
+                                                                                             {return fParent.replaceChild (newChild, oldChild); };
+           bool             DOMDocumentFragmentImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
+                                                                                             {return fNode.isSupported (feature, version); };
+           void             DOMDocumentFragmentImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); };
+           bool             DOMDocumentFragmentImpl::hasAttributes() const                   {return fNode.hasAttributes(); };
+           void*            DOMDocumentFragmentImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler)
+                                                                                             {return fNode.setUserData(key, data, handler); };
+           void*            DOMDocumentFragmentImpl::getUserData(const XMLCh* key) const     {return fNode.getUserData(key); };
 
diff --git a/src/xercesc/dom/impl/DOMDocumentImpl.cpp b/src/xercesc/dom/impl/DOMDocumentImpl.cpp
index c44a952ce..73317e2cc 100644
--- a/src/xercesc/dom/impl/DOMDocumentImpl.cpp
+++ b/src/xercesc/dom/impl/DOMDocumentImpl.cpp
@@ -122,7 +122,6 @@ DOMDocumentImpl::DOMDocumentImpl()
       fIterators(0L),
       fTreeWalkers(0L),
       fNodeIDMap(0),
-      fUserData(0),
       fRanges(0),
       fChanges(0),
       fNodeListPool(0),
@@ -130,7 +129,8 @@ DOMDocumentImpl::DOMDocumentImpl()
       fEncoding(0),
       fVersion(0),
       fStandalone(false),
-      fDocumentURI(0)
+      fDocumentURI(0),
+      fUserDataTable(0)
 {
     fNamePool    = new (this) DOMStringPool(257, this);
 };
@@ -151,7 +151,6 @@ DOMDocumentImpl::DOMDocumentImpl(const XMLCh *fNamespaceURI,
       fIterators(0L),
       fTreeWalkers(0L),
       fNodeIDMap(0),
-      fUserData(0),
       fRanges(0),
       fChanges(0),
       fNodeListPool(0),
@@ -159,7 +158,8 @@ DOMDocumentImpl::DOMDocumentImpl(const XMLCh *fNamespaceURI,
       fEncoding(0),
       fVersion(0),
       fStandalone(false),
-      fDocumentURI(0)
+      fDocumentURI(0),
+      fUserDataTable(0)
 {
     fNamePool    = new (this) DOMStringPool(257, this);
     try {
@@ -174,14 +174,14 @@ DOMDocumentImpl::DOMDocumentImpl(const XMLCh *fNamespaceURI,
 
 void DOMDocumentImpl::setDocumentType(DOMDocumentType *doctype)
 {
-	if (!doctype)
-		return;
+    if (!doctype)
+        return;
 
     // New doctypes can be created either with the factory methods on DOMImplementation, in
     //   which case ownerDocument will be 0, or with methods on DocumentImpl, in which case
     //   ownerDocument will be set, but the DocType won't yet be a child of the document.
     if (doctype->getOwnerDocument() != 0 && doctype->getOwnerDocument() != this)
-        throw DOMException(	//one doctype can belong to only one DOMDocumentImpl
+        throw DOMException(    //one doctype can belong to only one DOMDocumentImpl
         DOMException::WRONG_DOCUMENT_ERR, 0);
 
     DOMDocumentTypeImpl* doctypeImpl = (DOMDocumentTypeImpl*) doctype;
@@ -189,9 +189,9 @@ void DOMDocumentImpl::setDocumentType(DOMDocumentType *doctype)
 
     // The doctype can not have any Entities or Notations yet, because they can not
     //   be created except through factory methods on a document.
-				
+
     // revisit.  What if this doctype is already a child of the document?
-	appendChild(doctype);
+    appendChild(doctype);
 
 }
 
@@ -211,6 +211,9 @@ DOMDocumentImpl::~DOMDocumentImpl()
     if (fRanges)
         fRanges->cleanup();
 
+    if (fUserDataTable)
+        fUserDataTable->cleanup();
+
     //  Delete the heap for this document.  This uncerimoniously yanks the storage
     //      out from under all of the nodes in the document.  Destructors are NOT called.
     this->deleteHeap();
@@ -219,9 +222,6 @@ DOMDocumentImpl::~DOMDocumentImpl()
 
 DOMNode *DOMDocumentImpl::cloneNode(bool deep) const {
 
-    // clone the node itself
-    // revisit  -- this doesn't look right.  What about entities, doctype?
-
     // Note:  the cloned document node goes on the system heap.  All other
     //   nodes added to the new document will go on that document's heap,
     //   but we need to construct the document first, before its heap exists.
@@ -230,8 +230,10 @@ DOMNode *DOMDocumentImpl::cloneNode(bool deep) const {
     // then the children by _importing_ them
     if (deep)
         for (DOMNode *n = this->getFirstChild(); n != 0; n = n->getNextSibling()) {
-            newdoc->appendChild(newdoc->importNode(n, true));
-	}
+            newdoc->appendChild(newdoc->importNode(n, true, true));
+    }
+
+    fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newdoc);
     return newdoc;
 };
 
@@ -379,10 +381,10 @@ DOMText *DOMDocumentImpl::createTextNode(const XMLCh *data)
 DOMNodeIterator* DOMDocumentImpl::createNodeIterator (
           DOMNode *root, unsigned long whatToShow, DOMNodeFilter* filter, bool entityReferenceExpansion)
 {
-		// Create the node iterator implementation object.
-		//	Add it to the vector of fIterators that must be synchronized when a node is deleted.
-		//	The vector of fIterators is kept in the "owner document" if there is one. If there isn't one, I assume that root is the
-		//	owner document.
+    // Create the node iterator implementation object.
+    // Add it to the vector of fIterators that must be synchronized when a node is deleted.
+    // The vector of fIterators is kept in the "owner document" if there is one. If there isn't one, I assume that root is the
+    // owner document.
 
     DOMNodeIteratorImpl* iter = new (this) DOMNodeIteratorImpl(root, whatToShow, filter, entityReferenceExpansion);
     DOMDocument* doc = root->getOwnerDocument();
@@ -516,153 +518,15 @@ void DOMDocumentImpl::setNodeValue(const XMLCh *x)
 };
 
 
-
-
 //Introduced in DOM Level 2
-
 DOMNode *DOMDocumentImpl::importNode(DOMNode *source, bool deep)
 {
-    DOMNode *newnode=0;
-    bool oldErrorCheckingFlag = errorChecking;
-
-    switch (source->getNodeType())
-    {
-    case DOMNode::ELEMENT_NODE :
-        {
-            DOMElement *newelement;
-            if (source->getLocalName() == 0)
-                newelement = createElement(source->getNodeName());
-            else
-                newelement = createElementNS(source->getNamespaceURI(),
-                source->getNodeName());
-            DOMNamedNodeMap *srcattr=source->getAttributes();
-            if(srcattr!=0)
-                for(XMLSize_t i=0;i<srcattr->getLength();++i)
-                {
-                    DOMAttr *attr = (DOMAttr *) srcattr->item(i);
-                    if (attr -> getSpecified())	{ // not a default attribute
-                        DOMAttr *nattr = (DOMAttr *) importNode(attr, true);
-                        if (attr -> getLocalName() == 0)
-                            newelement->setAttributeNode(nattr);
-                        else
-                            newelement->setAttributeNodeNS(nattr);
-                    }
-                }
-                newnode=newelement;
-        }
-        break;
-    case DOMNode::ATTRIBUTE_NODE :
-        if (source->getLocalName() == 0)
-            newnode = createAttribute(source->getNodeName());
-        else
-            newnode = createAttributeNS(source->getNamespaceURI(),
-            source->getNodeName());
-        deep = true;
-        // Kids carry value
-        break;
-    case DOMNode::TEXT_NODE :
-        newnode = createTextNode(source->getNodeValue());
-        break;
-    case DOMNode::CDATA_SECTION_NODE :
-        newnode = createCDATASection(source->getNodeValue());
-        break;
-    case DOMNode::ENTITY_REFERENCE_NODE :
-        {
-            DOMEntityReferenceImpl* newentityRef = (DOMEntityReferenceImpl*)createEntityReference(source->getNodeName());
-            newnode=newentityRef;
-            errorChecking = false;
-            newentityRef->setReadOnly(false, true); //allow deep import temporarily
-        }
-        break;
-    case DOMNode::ENTITY_NODE :
-        {
-            DOMEntity *srcentity=(DOMEntity *)source;
-            DOMEntityImpl *newentity = (DOMEntityImpl *)createEntity(source->getNodeName());
-            newentity->setPublicId(srcentity->getPublicId());
-            newentity->setSystemId(srcentity->getSystemId());
-            newentity->setNotationName(srcentity->getNotationName());
-            // Kids carry additional value
-            newnode=newentity;
-            castToNodeImpl(newentity)->setReadOnly(false, true);// allow deep import temporarily
-        }
-        break;
-    case DOMNode::PROCESSING_INSTRUCTION_NODE :
-        newnode = createProcessingInstruction(source->getNodeName(),
-            source->getNodeValue());
-        break;
-    case DOMNode::COMMENT_NODE :
-        newnode = createComment(source->getNodeValue());
-        break;
-    case DOMNode::DOCUMENT_TYPE_NODE :
-        {
-            DOMDocumentType *srcdoctype = (DOMDocumentType *)source;
-            DOMDocumentType *newdoctype = (DOMDocumentType *)
-                createDocumentType(srcdoctype->getNodeName(),
-                srcdoctype->getPublicId(),
-                srcdoctype->getSystemId());
-            // Values are on NamedNodeMaps
-            DOMNamedNodeMap *smap = srcdoctype->getEntities();
-            DOMNamedNodeMap *tmap = newdoctype->getEntities();
-            if(smap != 0) {
-                for(XMLSize_t i = 0; i < smap->getLength(); i++) {
-                    tmap->setNamedItem(importNode(smap->item(i), true));
-                }
-            }
-            smap = srcdoctype->getNotations();
-            tmap = newdoctype->getNotations();
-            if (smap != 0) {
-                for(XMLSize_t i = 0; i < smap->getLength(); i++) {
-                    tmap->setNamedItem(importNode(smap->item(i), true));
-                }
-            }
-            // NOTE: At this time, the DOM definition of DocumentType
-            // doesn't cover Elements and their Attributes. domimpl's
-            // extentions in that area will not be preserved, even if
-            // copying from domimpl to domimpl. We could special-case
-            // that here. Arguably we should. Consider. ?????
-            newnode = newdoctype;
-        }
-        break;
-    case DOMNode::DOCUMENT_FRAGMENT_NODE :
-        newnode = createDocumentFragment();
-        // No name, kids carry value
-        break;
-    case DOMNode::NOTATION_NODE :
-        {
-            DOMNotation *srcnotation=(DOMNotation *)source;
-            DOMNotationImpl *newnotation = (DOMNotationImpl *)createNotation(source->getNodeName());
-            newnotation->setPublicId(srcnotation->getPublicId());
-            newnotation->setSystemId(srcnotation->getSystemId());
-            // Kids carry additional value
-            newnode=newnotation;
-            // No name, no value
-            break;
-        }
-
-    case DOMNode::DOCUMENT_NODE : // Document can't be child of Document
-    default:                       // Unknown node type
-        throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0);
-    }
-
-    // If deep, replicate and attach the kids.
-    if (deep)
-        for (DOMNode *srckid = source->getFirstChild();
-        srckid != 0;
-        srckid = srckid->getNextSibling()) {
-            newnode->appendChild(importNode(srckid, true));
-        }
-        if (newnode->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE
-            || newnode->getNodeType() == DOMNode::ENTITY_NODE) {
-            castToNodeImpl(newnode)->setReadOnly(true, true);
-            errorChecking = oldErrorCheckingFlag;
-        }
-
-        return newnode;
+    return importNode(source, deep, false);
 }
 
 
 DOMElement *DOMDocumentImpl::createElementNS(const XMLCh *fNamespaceURI,
-	const XMLCh *qualifiedName)
+    const XMLCh *qualifiedName)
 {
     if(!isXMLName(qualifiedName))
         throw DOMException(DOMException::INVALID_CHARACTER_ERR,0);
@@ -683,7 +547,7 @@ DOMElement *DOMDocumentImpl::createElementNS(const XMLCh *fNamespaceURI,
 
 
 DOMAttr *DOMDocumentImpl::createAttributeNS(const XMLCh *fNamespaceURI,
-	const XMLCh *qualifiedName)
+    const XMLCh *qualifiedName)
 {
     if(!isXMLName(qualifiedName))
         throw DOMException(DOMException::INVALID_CHARACTER_ERR,0);
@@ -692,7 +556,7 @@ DOMAttr *DOMDocumentImpl::createAttributeNS(const XMLCh *fNamespaceURI,
 
 
 DOMNodeList *DOMDocumentImpl::getElementsByTagNameNS(const XMLCh *fNamespaceURI,
-	const XMLCh *fLocalName)  const
+    const XMLCh *fLocalName)  const
 {
     // cast off the const of this because we will update the fNodeListPool
     return ((DOMDocumentImpl*)this)->getDeepNodeList(this, fNamespaceURI, fLocalName);
@@ -706,7 +570,7 @@ DOMElement *DOMDocumentImpl::getElementById(const XMLCh *elementId) const
 
     DOMAttr *theAttr = fNodeIDMap->find(elementId);
     if (theAttr == 0)
-	    return 0;
+        return 0;
 
     return theAttr->getOwnerElement();
 }
@@ -721,7 +585,7 @@ int DOMDocumentImpl::indexofQualifiedName(const XMLCh * qName)
     for (int i = 0; i < qNameLen; ++i) {
         if (qName[i] == chColon) {
             index = i;
-            ++count;	//number of ':' found
+            ++count;    //number of ':' found
         }
     }
 
@@ -809,41 +673,6 @@ bool DOMDocumentImpl::isKidOK(DOMNode *parent, DOMNode *child)
       return (kidOK[p] & 1<<ch) != 0;
 }
 
-void DOMDocumentImpl::setUserData(DOMNode* n, void* data)
-{
-	if (!fUserData && data)
-		fUserData = new (this) RefHashTableOf<void>(29, false, new (this) HashPtr());
-	if (!data && fUserData)
-		fUserData->removeKey((void*)n);
-	else
-		fUserData->put((void*)n,data);
-}
-
-void* DOMDocumentImpl::getUserData(const DOMNode* n) const
-{
-	if (fUserData)
-		return fUserData->get((void*)n);
-	else
-		return 0;
-}
-
-void* DOMDocumentImpl::getUserData() const
-{
-	return (fNode.hasUserData()) ? getUserData(this) : 0;
-}
-
-void DOMDocumentImpl::setUserData(void* val)
-{
-	setUserData(this, val);
-	if (val)
-		fNode.hasUserData(true);
-	else
-		fNode.hasUserData(false);
-};
-
-
-
-
 void            DOMDocumentImpl::changed()
 {
     fChanges++;
@@ -859,26 +688,30 @@ int             DOMDocumentImpl::changes() const{
 //
 //    Delegation for functions inherited from DOMNode
 //
-           DOMNode          *DOMDocumentImpl::appendChild(DOMNode *newChild)        {return insertBefore(newChild, 0); };
-           DOMNamedNodeMap  *DOMDocumentImpl::getAttributes() const 			        {return fNode.getAttributes (); };
-           DOMNodeList      *DOMDocumentImpl::getChildNodes() const 			        {return fParent.getChildNodes (); };
-           DOMNode          *DOMDocumentImpl::getFirstChild() const 			        {return fParent.getFirstChild (); };
-           DOMNode          *DOMDocumentImpl::getLastChild() const 		            {return fParent.getLastChild (); };
-     const XMLCh              *DOMDocumentImpl::getLocalName() const                    {return fNode.getLocalName (); };
-     const XMLCh              *DOMDocumentImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); };
-           DOMNode          *DOMDocumentImpl::getNextSibling() const                  {return fNode.getNextSibling (); };
-     const XMLCh              *DOMDocumentImpl::getNodeValue() const                    {return fNode.getNodeValue (); };
-     const XMLCh              *DOMDocumentImpl::getPrefix() const                       {return fNode.getPrefix (); };
-           DOMNode          *DOMDocumentImpl::getParentNode() const                   {return fNode.getParentNode (); };
-           DOMNode          *DOMDocumentImpl::getPreviousSibling() const              {return fNode.getPreviousSibling (); };
-           bool                DOMDocumentImpl::hasChildNodes() const                   {return fParent.hasChildNodes (); };
-           void                DOMDocumentImpl::normalize()                             {fParent.normalize (); };
-           DOMNode          *DOMDocumentImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
-                                                                            {return fParent.replaceChild (newChild, oldChild); };
-           bool                DOMDocumentImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
-                                                                            {return fNode.isSupported (feature, version); };
-           void                DOMDocumentImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); };
-           bool                DOMDocumentImpl::hasAttributes() const                   {return fNode.hasAttributes(); };
+           DOMNode*         DOMDocumentImpl::appendChild(DOMNode *newChild)          {return insertBefore(newChild, 0); };
+           DOMNamedNodeMap* DOMDocumentImpl::getAttributes() const                   {return fNode.getAttributes (); };
+           DOMNodeList*     DOMDocumentImpl::getChildNodes() const                   {return fParent.getChildNodes (); };
+           DOMNode*         DOMDocumentImpl::getFirstChild() const                   {return fParent.getFirstChild (); };
+           DOMNode*         DOMDocumentImpl::getLastChild() const                    {return fParent.getLastChild (); };
+     const XMLCh*           DOMDocumentImpl::getLocalName() const                    {return fNode.getLocalName (); };
+     const XMLCh*           DOMDocumentImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); };
+           DOMNode*         DOMDocumentImpl::getNextSibling() const                  {return fNode.getNextSibling (); };
+     const XMLCh*           DOMDocumentImpl::getNodeValue() const                    {return fNode.getNodeValue (); };
+     const XMLCh*           DOMDocumentImpl::getPrefix() const                       {return fNode.getPrefix (); };
+           DOMNode*         DOMDocumentImpl::getParentNode() const                   {return fNode.getParentNode (); };
+           DOMNode*         DOMDocumentImpl::getPreviousSibling() const              {return fNode.getPreviousSibling (); };
+           bool             DOMDocumentImpl::hasChildNodes() const                   {return fParent.hasChildNodes (); };
+           void             DOMDocumentImpl::normalize()                             {fParent.normalize (); };
+           DOMNode*         DOMDocumentImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
+                                                                                     {return fParent.replaceChild (newChild, oldChild); };
+           bool             DOMDocumentImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
+                                                                                     {return fNode.isSupported (feature, version); };
+           void             DOMDocumentImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); };
+           bool             DOMDocumentImpl::hasAttributes() const                   {return fNode.hasAttributes(); };
+           void*            DOMDocumentImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler)
+                                                                                     {return fNode.setUserData(key, data, handler); };
+           void*            DOMDocumentImpl::getUserData(const XMLCh* key) const     {return fNode.getUserData(key); };
+
 
 
 //-----------------------------------------------------------------------
@@ -1068,3 +901,245 @@ void DOMDocumentImpl::setDocumentURI(const XMLCh* documentURI){
     fDocumentURI = cloneString(documentURI);
 }
 
+//Introduced in DOM Level 2
+
+DOMNode *DOMDocumentImpl::importNode(DOMNode *source, bool deep, bool cloningDoc)
+{
+    DOMNode *newnode=0;
+    bool oldErrorCheckingFlag = errorChecking;
+
+    switch (source->getNodeType())
+    {
+    case DOMNode::ELEMENT_NODE :
+        {
+            DOMElement *newelement;
+            if (source->getLocalName() == 0)
+                newelement = createElement(source->getNodeName());
+            else
+                newelement = createElementNS(source->getNamespaceURI(),
+                source->getNodeName());
+            DOMNamedNodeMap *srcattr=source->getAttributes();
+            if(srcattr!=0)
+                for(XMLSize_t i=0;i<srcattr->getLength();++i)
+                {
+                    DOMAttr *attr = (DOMAttr *) srcattr->item(i);
+                    if (attr -> getSpecified()) { // not a default attribute
+                        DOMAttr *nattr = (DOMAttr *) importNode(attr, true, false);
+                        if (attr -> getLocalName() == 0)
+                            newelement->setAttributeNode(nattr);
+                        else
+                            newelement->setAttributeNodeNS(nattr);
+                    }
+                }
+                newnode=newelement;
+        }
+        break;
+    case DOMNode::ATTRIBUTE_NODE :
+        if (source->getLocalName() == 0)
+            newnode = createAttribute(source->getNodeName());
+        else
+            newnode = createAttributeNS(source->getNamespaceURI(),
+            source->getNodeName());
+        deep = true;
+        // Kids carry value
+        break;
+    case DOMNode::TEXT_NODE :
+        newnode = createTextNode(source->getNodeValue());
+        break;
+    case DOMNode::CDATA_SECTION_NODE :
+        newnode = createCDATASection(source->getNodeValue());
+        break;
+    case DOMNode::ENTITY_REFERENCE_NODE :
+        {
+            DOMEntityReferenceImpl* newentityRef = (DOMEntityReferenceImpl*)createEntityReference(source->getNodeName());
+            newnode=newentityRef;
+            errorChecking = false;
+            newentityRef->setReadOnly(false, true); //allow deep import temporarily
+        }
+        break;
+    case DOMNode::ENTITY_NODE :
+        {
+            DOMEntity *srcentity=(DOMEntity *)source;
+            DOMEntityImpl *newentity = (DOMEntityImpl *)createEntity(source->getNodeName());
+            newentity->setPublicId(srcentity->getPublicId());
+            newentity->setSystemId(srcentity->getSystemId());
+            newentity->setNotationName(srcentity->getNotationName());
+            // Kids carry additional value
+            newnode=newentity;
+            castToNodeImpl(newentity)->setReadOnly(false, true);// allow deep import temporarily
+        }
+        break;
+    case DOMNode::PROCESSING_INSTRUCTION_NODE :
+        newnode = createProcessingInstruction(source->getNodeName(),
+            source->getNodeValue());
+        break;
+    case DOMNode::COMMENT_NODE :
+        newnode = createComment(source->getNodeValue());
+        break;
+    case DOMNode::DOCUMENT_TYPE_NODE :
+        {
+            // unless this is used as part of cloning a Document
+            // forbid it for the sake of being compliant to the DOM spec
+            if (!cloningDoc)
+                throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0);
+
+            DOMDocumentType *srcdoctype = (DOMDocumentType *)source;
+            DOMDocumentType *newdoctype = (DOMDocumentType *)
+                createDocumentType(srcdoctype->getNodeName(),
+                srcdoctype->getPublicId(),
+                srcdoctype->getSystemId());
+            // Values are on NamedNodeMaps
+            DOMNamedNodeMap *smap = srcdoctype->getEntities();
+            DOMNamedNodeMap *tmap = newdoctype->getEntities();
+            if(smap != 0) {
+                for(XMLSize_t i = 0; i < smap->getLength(); i++) {
+                    tmap->setNamedItem(importNode(smap->item(i), true, false));
+                }
+            }
+            smap = srcdoctype->getNotations();
+            tmap = newdoctype->getNotations();
+            if (smap != 0) {
+                for(XMLSize_t i = 0; i < smap->getLength(); i++) {
+                    tmap->setNamedItem(importNode(smap->item(i), true, false));
+                }
+            }
+            // NOTE: At this time, the DOM definition of DocumentType
+            // doesn't cover Elements and their Attributes. domimpl's
+            // extentions in that area will not be preserved, even if
+            // copying from domimpl to domimpl. We could special-case
+            // that here. Arguably we should. Consider. ?????
+            newnode = newdoctype;
+        }
+        break;
+    case DOMNode::DOCUMENT_FRAGMENT_NODE :
+        newnode = createDocumentFragment();
+        // No name, kids carry value
+        break;
+    case DOMNode::NOTATION_NODE :
+        {
+            DOMNotation *srcnotation=(DOMNotation *)source;
+            DOMNotationImpl *newnotation = (DOMNotationImpl *)createNotation(source->getNodeName());
+            newnotation->setPublicId(srcnotation->getPublicId());
+            newnotation->setSystemId(srcnotation->getSystemId());
+            // Kids carry additional value
+            newnode=newnotation;
+            // No name, no value
+            break;
+        }
+
+    case DOMNode::DOCUMENT_NODE : // Document can't be child of Document
+    default:                       // Unknown node type
+        throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0);
+    }
+
+    // If deep, replicate and attach the kids.
+    if (deep)
+        for (DOMNode *srckid = source->getFirstChild();
+             srckid != 0;
+             srckid = srckid->getNextSibling())
+        {
+            newnode->appendChild(importNode(srckid, true, false));
+        }
+
+    if (newnode->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE
+        || newnode->getNodeType() == DOMNode::ENTITY_NODE) {
+        castToNodeImpl(newnode)->setReadOnly(true, true);
+        errorChecking = oldErrorCheckingFlag;
+    }
+
+    if (!cloningDoc)
+        fNode.callUserDataHandlers(DOMUserDataHandler::NODE_IMPORTED, source, newnode);
+
+    return newnode;
+}
+
+// user data utility
+void* DOMDocumentImpl::setUserData(DOMNodeImpl* n, const XMLCh* key, void* data, DOMUserDataHandler* handler)
+{
+    void* oldData = 0;
+    DOMNode_UserDataTable* node_userDataTable = 0;
+
+    if (!fUserDataTable) {
+        // create the table on heap so that it can be cleaned in destructor
+        fUserDataTable = new (this) RefHashTableOf<DOMNode_UserDataTable>(29, true, new HashPtr());
+    }
+    else {
+        node_userDataTable = fUserDataTable->get((void*)n);
+        DOMUserDataRecord* oldDataRecord = 0;
+
+        if (node_userDataTable) {
+            oldDataRecord = node_userDataTable->get((void*)key);
+
+            if (oldDataRecord) {
+                oldData = oldDataRecord->getKey();
+                node_userDataTable->removeKey((void*)key);
+            }
+        }
+    }
+
+    if (data) {
+
+        // create the DOMNode_UserDataTable if not exists
+        // create on the heap and adopted by the hashtable which will delete it upon removal.
+        if (!node_userDataTable) {
+            node_userDataTable  = new RefHashTableOf<DOMUserDataRecord>(29, true);
+            fUserDataTable->put(n, node_userDataTable);
+        }
+
+        // clone the key first, and create the DOMUserDataRecord
+        // create on the heap and adopted by the hashtable which will delete it upon removal.
+        node_userDataTable->put((void*)getPooledString(key), new DOMUserDataRecord(data, handler));
+    }
+    else {
+        if (node_userDataTable->isEmpty())
+            n->hasUserData(false);
+    }
+
+    return oldData;
+}
+
+void* DOMDocumentImpl::getUserData(const DOMNodeImpl* n, const XMLCh* key) const
+{
+    if (fUserDataTable) {
+        DOMNode_UserDataTable*  node_userDataTable = fUserDataTable->get((void*)n);
+
+        if (node_userDataTable) {
+            DOMUserDataRecord* dataRecord = node_userDataTable->get((void*)key);
+            if (dataRecord)
+                return dataRecord->getKey();
+        }
+    }
+
+    return 0;
+}
+
+void DOMDocumentImpl::callUserDataHandlers(const DOMNodeImpl* n, DOMUserDataHandler::DOMOperationType operation, const DOMNode* src, const DOMNode* dst) const
+{
+    if (fUserDataTable) {
+        DOMNode_UserDataTable*  node_userDataTable = fUserDataTable->get((void*)n);
+
+        if (node_userDataTable) {
+            RefHashTableOfEnumerator<DOMUserDataRecord> userDataEnum(node_userDataTable);
+
+            // walk through the entire node_userDataTable table
+            while (userDataEnum.hasMoreElements()) {
+                // get the key
+                XMLCh* key = (XMLCh*) userDataEnum.nextElementKey();
+
+                // get the DOMUserDataRecord
+                DOMUserDataRecord* userDataRecord = node_userDataTable->get((void*)key);
+
+                // get the handler
+                DOMUserDataHandler* handler = userDataRecord->getValue();
+
+                if (handler) {
+                    // get the data
+                    void* data = userDataRecord->getKey();
+                    handler->handle(operation, key, data, src, dst);
+                }
+            }
+        }
+    }
+}
+
+
diff --git a/src/xercesc/dom/impl/DOMDocumentImpl.hpp b/src/xercesc/dom/impl/DOMDocumentImpl.hpp
index b64ed02eb..ff0b8ed00 100644
--- a/src/xercesc/dom/impl/DOMDocumentImpl.hpp
+++ b/src/xercesc/dom/impl/DOMDocumentImpl.hpp
@@ -74,8 +74,10 @@
 #include <xercesc/util/XercesDefs.hpp>
 #include <xercesc/util/RefVectorOf.hpp>
 #include <xercesc/util/RefHashTableOf.hpp>
+#include <xercesc/util/KeyRefPair.hpp>
 
 #include <xercesc/dom/DOMDocument.hpp>
+#include <xercesc/dom/DOMUserDataHandler.hpp>
 #include "DOMNodeImpl.hpp"
 #include "DOMParentNode.hpp"
 #include "DOMDeepNodeListPool.hpp"
@@ -108,7 +110,8 @@ class DOMStringPool;
 typedef RefVectorOf<DOMNodeIteratorImpl> NodeIterators;
 typedef RefVectorOf<DOMTreeWalkerImpl>   TreeWalkers;
 typedef RefVectorOf<DOMRangeImpl>        Ranges;
-
+typedef KeyRefPair<void, DOMUserDataHandler> DOMUserDataRecord;
+typedef RefHashTableOf<DOMUserDataRecord> DOMNode_UserDataTable;
 
 class CDOM_EXPORT DOMDocumentImpl: public DOMDocument {
 public:
@@ -129,7 +132,6 @@ public:
     TreeWalkers*          fTreeWalkers;
     Ranges*               fRanges;
 
-    RefHashTableOf<void>* fUserData;
     int                   fChanges;
 
     bool                  errorChecking;    // Bypass error checking.
@@ -141,6 +143,8 @@ public:
     XMLCh*                fVersion;
     XMLCh*                fDocumentURI;
 
+    RefHashTableOf<DOMNode_UserDataTable>* fUserDataTable;
+
 
     // Per-Document heap Variables.
     //   The heap consists of one or more biggish blocks which are
@@ -179,54 +183,49 @@ public:
 
 public:
     DOMDocumentImpl();
-    DOMDocumentImpl(const XMLCh      *namespaceURI,	     //DOM Level 2
-                   const XMLCh      *qualifiedName,
-                   DOMDocumentType *doctype);
+    DOMDocumentImpl(const XMLCh*     namespaceURI,     //DOM Level 2
+                    const XMLCh*     qualifiedName,
+                    DOMDocumentType* doctype);
     virtual ~DOMDocumentImpl();
 
     // Add all functions that are pure virutal in DOMNODE
     DOMNODE_FUNCTIONS;
 
     // Add all functions that are pure virutal in DOMDocument
-    virtual DOMAttr             *createAttribute(const XMLCh *name);
-    virtual DOMCDATASection     *createCDATASection(const XMLCh *data);
-    virtual DOMComment          *createComment(const XMLCh *data);
-    virtual DOMDocumentFragment *createDocumentFragment();
-    virtual DOMDocumentType     *createDocumentType(const XMLCh *name);
-    virtual DOMDocumentType     *createDocumentType(const XMLCh *qName,
+    virtual DOMAttr*             createAttribute(const XMLCh *name);
+    virtual DOMCDATASection*     createCDATASection(const XMLCh *data);
+    virtual DOMComment*          createComment(const XMLCh *data);
+    virtual DOMDocumentFragment* createDocumentFragment();
+    virtual DOMDocumentType*     createDocumentType(const XMLCh *name);
+    virtual DOMDocumentType*     createDocumentType(const XMLCh *qName,
                                                     const XMLCh *publicId,
                                                     const XMLCh *systemId);
-    virtual DOMElement          *createElement(const XMLCh * tagName);
-    virtual DOMElement          *createElementNoCheck(const XMLCh *tagName);
-    virtual DOMEntity           *createEntity(const XMLCh * name);
-    virtual DOMEntityReference  *createEntityReference(const XMLCh * name);
-    virtual DOMNotation         *createNotation(const XMLCh * name);
-    virtual DOMProcessingInstruction *createProcessingInstruction(const XMLCh * target, const XMLCh * data);
-    virtual DOMText             *createTextNode(const XMLCh * data);
-    virtual DOMDocumentType     *getDoctype() const;
-    virtual DOMElement          *getDocumentElement() const;
-    virtual DOMNodeList         *getElementsByTagName(const XMLCh * tagname) const;
-    virtual DOMImplementation *getImplementation() const;
-    static  bool                  isXMLName(const XMLCh * s);
-    virtual DOMNodeIterator     *createNodeIterator(DOMNode *root,
-                                                      unsigned long whatToShow,
-                                                      DOMNodeFilter* filter,
-                                                      bool entityReferenceExpansion);
-    virtual DOMTreeWalker       *createTreeWalker(DOMNode *root,
+    virtual DOMElement*          createElement(const XMLCh * tagName);
+    virtual DOMElement*          createElementNoCheck(const XMLCh *tagName);
+    virtual DOMEntity*           createEntity(const XMLCh * name);
+    virtual DOMEntityReference*  createEntityReference(const XMLCh * name);
+    virtual DOMNotation*         createNotation(const XMLCh * name);
+    virtual DOMProcessingInstruction* createProcessingInstruction(const XMLCh * target, const XMLCh * data);
+    virtual DOMText*             createTextNode(const XMLCh * data);
+    virtual DOMDocumentType*     getDoctype() const;
+    virtual DOMElement*          getDocumentElement() const;
+    virtual DOMNodeList*         getElementsByTagName(const XMLCh * tagname) const;
+    virtual DOMImplementation*   getImplementation() const;
+    static  bool                 isXMLName(const XMLCh * s);
+    virtual DOMNodeIterator*     createNodeIterator(DOMNode *root,
                                                     unsigned long whatToShow,
                                                     DOMNodeFilter* filter,
                                                     bool entityReferenceExpansion);
+    virtual DOMTreeWalker*       createTreeWalker(DOMNode *root,
+                                                  unsigned long whatToShow,
+                                                  DOMNodeFilter* filter,
+                                                  bool entityReferenceExpansion);
 
-    virtual void*                  getUserData() const;
-    virtual void                   setUserData(void* value);
-    virtual DOMRange            *createRange();
-    virtual Ranges*                getRanges() const;  //non-standard api
-    virtual void                   removeRange(DOMRangeImpl* range); //non-standard api
 
+    virtual DOMRange*            createRange();
+    virtual Ranges*              getRanges() const;  //non-standard api
+    virtual void                 removeRange(DOMRangeImpl* range); //non-standard api
 
-    // helper functions to prevent storing userdata pointers on every node.
-    virtual void  setUserData(DOMNode* n, void* data);
-    virtual void* getUserData(const DOMNode* n) const;
 
     //
     // Functions to keep track of document mutations, so that node list chached
@@ -265,38 +264,49 @@ public:
     }
 
     //Introduced in DOM Level 2
-    virtual DOMNode            *importNode(DOMNode *source, bool deep);
-    virtual DOMElement         *createElementNS(const XMLCh *namespaceURI,
-                                                  const XMLCh *qualifiedName);
-    virtual DOMElement         *createElementNS(const XMLCh *namespaceURI,
-                                                  const XMLCh *qualifiedName,
-                                                  const XMLSSize_t lineNo,
-                                                  const XMLSSize_t columnNo);
-    virtual DOMAttr            *createAttributeNS(const XMLCh *namespaceURI,
-	                                             const XMLCh *qualifiedName);
-    virtual DOMNodeList        *getElementsByTagNameNS(const XMLCh *namespaceURI,
-	                                              const XMLCh *localName) const;
-    virtual DOMElement         *getElementById(const XMLCh *elementId) const;
+    virtual DOMNode*             importNode(DOMNode *source, bool deep);
+    virtual DOMElement*          createElementNS(const XMLCh *namespaceURI,
+                                                 const XMLCh *qualifiedName);
+    virtual DOMElement*          createElementNS(const XMLCh *namespaceURI,
+                                                 const XMLCh *qualifiedName,
+                                                 const XMLSSize_t lineNo,
+                                                 const XMLSSize_t columnNo);
+    virtual DOMAttr*             createAttributeNS(const XMLCh *namespaceURI,
+                                                   const XMLCh *qualifiedName);
+    virtual DOMNodeList*         getElementsByTagNameNS(const XMLCh *namespaceURI,
+                                                        const XMLCh *localName) const;
+    virtual DOMElement*          getElementById(const XMLCh *elementId) const;
 
     //Introduced in DOM Level 3
-    virtual const XMLCh*           getActualEncoding() const;
-    virtual void                   setActualEncoding(const XMLCh* actualEncoding);
-    virtual const XMLCh*           getEncoding() const;
-    virtual void                   setEncoding(const XMLCh* encoding);
-    virtual bool                   getStandalone() const;
-    virtual void                   setStandalone(bool standalone);
-    virtual const XMLCh*           getVersion() const;
-    virtual void                   setVersion(const XMLCh* version);
-    virtual const XMLCh*           getDocumentURI() const;
-    virtual void                   setDocumentURI(const XMLCh* documentURI);
+    virtual const XMLCh*         getActualEncoding() const;
+    virtual void                 setActualEncoding(const XMLCh* actualEncoding);
+    virtual const XMLCh*         getEncoding() const;
+    virtual void                 setEncoding(const XMLCh* encoding);
+    virtual bool                 getStandalone() const;
+    virtual void                 setStandalone(bool standalone);
+    virtual const XMLCh*         getVersion() const;
+    virtual void                 setVersion(const XMLCh* version);
+    virtual const XMLCh*         getDocumentURI() const;
+    virtual void                 setDocumentURI(const XMLCh* documentURI);
 
+    // helper functions to prevent storing userdata pointers on every node.
+    void*                        setUserData(DOMNodeImpl* n,
+                                            const XMLCh* key,
+                                            void* data,
+                                            DOMUserDataHandler* handler);
+    void*                        getUserData(const DOMNodeImpl* n,
+                                             const XMLCh* key) const;
+    void                         callUserDataHandlers(const DOMNodeImpl* n,
+                                                      DOMUserDataHandler::DOMOperationType operation,
+                                                      const DOMNode* src,
+                                                      const DOMNode* dst) const;
 
     //Return the index > 0 of ':' in the given qualified name qName="prefix:localName".
     //Return 0 if there is no ':', or -1 if qName is malformed such as ":abcd".
-    static  int                 indexofQualifiedName(const XMLCh * qName);
-    static  bool                isKidOK(DOMNode *parent, DOMNode *child);
+    static  int                  indexofQualifiedName(const XMLCh * qName);
+    static  bool                 isKidOK(DOMNode *parent, DOMNode *child);
 
-    inline DOMNodeIDMap *          getNodeIDMap() {return fNodeIDMap;};
+    inline DOMNodeIDMap*         getNodeIDMap() {return fNodeIDMap;};
 
 
     //
@@ -305,23 +315,28 @@ public:
     //                               document itself is deleted.
     //
 
-    void        * allocate(size_t amount);
-    XMLCh       * cloneString(const XMLCh *src);
-    const XMLCh * getPooledString(const XMLCh *src);
-    void          deleteHeap();
+    void*                        allocate(size_t amount);
+    XMLCh*                       cloneString(const XMLCh *src);
+    const XMLCh*                 getPooledString(const XMLCh *src);
+    void                         deleteHeap();
 
 
     // Factory methods for getting/creating node lists.
     // Because nothing is ever deleted, the implementation caches and recycles
     //  previously used instances of DOMDeepNodeList
     //
-    DOMNodeList *getDeepNodeList(const DOMNode *rootNode, const XMLCh *tagName);
-    DOMNodeList *getDeepNodeList(const DOMNode *rootNode,	//DOM Level 2
-			                            const XMLCh *namespaceURI,
-                                     const XMLCh *localName);
+    DOMNodeList*                 getDeepNodeList(const DOMNode *rootNode, const XMLCh *tagName);
+    DOMNodeList*                 getDeepNodeList(const DOMNode *rootNode,    //DOM Level 2
+                                                 const XMLCh *namespaceURI,
+                                                 const XMLCh *localName);
 
 private:
-    DOMDeepNodeListPool<DOMDeepNodeListImpl> *fNodeListPool;
+    //Internal helper functions
+    virtual DOMNode*             importNode(DOMNode *source, bool deep, bool cloningNode);
+
+private:
+    DOMDeepNodeListPool<DOMDeepNodeListImpl>* fNodeListPool;
+
 };
 
 //
diff --git a/src/xercesc/dom/impl/DOMDocumentTypeImpl.cpp b/src/xercesc/dom/impl/DOMDocumentTypeImpl.cpp
index abae71a09..eb34441dc 100644
--- a/src/xercesc/dom/impl/DOMDocumentTypeImpl.cpp
+++ b/src/xercesc/dom/impl/DOMDocumentTypeImpl.cpp
@@ -100,7 +100,7 @@ DOMDocumentTypeImpl::DOMDocumentTypeImpl(DOMDocument *ownerDoc,
                                    const XMLCh *qualifiedName,
                                    const XMLCh *pubId,
                                    const XMLCh *sysId)
-	: fNode(ownerDoc),
+    : fNode(ownerDoc),
     fParent(ownerDoc),
     publicId(0),
     systemId(0),
@@ -152,9 +152,9 @@ DOMDocumentTypeImpl::DOMDocumentTypeImpl(const DOMDocumentTypeImpl &other, bool
         if (deep)
             fParent.cloneChildren(&other);
         //DOM Level 2
-        publicId		= other.publicId;
-        systemId		= other.systemId;
-        internalSubset	= other.internalSubset;
+        publicId        = other.publicId;
+        systemId        = other.systemId;
+        internalSubset  = other.internalSubset;
     }
     else {
         name = XMLString::replicate(other.name);
@@ -194,10 +194,14 @@ DOMDocumentTypeImpl::~DOMDocumentTypeImpl()
 
 DOMNode *DOMDocumentTypeImpl::cloneNode(bool deep) const
 {
+    DOMNode* newNode = 0;
     if (castToNodeImpl(this)->getOwnerDocument())
-        return new (castToNodeImpl(this)->getOwnerDocument()) DOMDocumentTypeImpl(*this, deep);
+        newNode = new (castToNodeImpl(this)->getOwnerDocument()) DOMDocumentTypeImpl(*this, deep);
+    else
+        newNode = new DOMDocumentTypeImpl(*this, deep);
 
-    return new DOMDocumentTypeImpl(*this, deep);
+    fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode);
+    return newNode;
 }
 
 /**
@@ -375,28 +379,31 @@ void        DOMDocumentTypeImpl::setInternalSubset(const XMLCh *value)
 // Delegation for functions inherited from Node
 //
 
-           DOMNode          *DOMDocumentTypeImpl::appendChild(DOMNode *newChild)        {return fParent.appendChild (newChild); };
-           DOMNamedNodeMap  *DOMDocumentTypeImpl::getAttributes() const 			        {return fNode.getAttributes (); };
-           DOMNodeList      *DOMDocumentTypeImpl::getChildNodes() const 			        {return fParent.getChildNodes (); };
-           DOMNode          *DOMDocumentTypeImpl::getFirstChild() const 			        {return fParent.getFirstChild (); };
-           DOMNode          *DOMDocumentTypeImpl::getLastChild() const 		            {return fParent.getLastChild (); };
-     const XMLCh              *DOMDocumentTypeImpl::getLocalName() const                    {return fNode.getLocalName (); };
-     const XMLCh              *DOMDocumentTypeImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); };
-           DOMNode          *DOMDocumentTypeImpl::getNextSibling() const                  {return fChild.getNextSibling (); };
-     const XMLCh              *DOMDocumentTypeImpl::getNodeValue() const                    {return fNode.getNodeValue (); };
-           DOMDocument      *DOMDocumentTypeImpl::getOwnerDocument() const                {return fNode.getOwnerDocument (); };
-     const XMLCh              *DOMDocumentTypeImpl::getPrefix() const                       {return fNode.getPrefix (); };
-           DOMNode          *DOMDocumentTypeImpl::getParentNode() const                   {return fChild.getParentNode (this); };
-           DOMNode          *DOMDocumentTypeImpl::getPreviousSibling() const              {return fChild.getPreviousSibling (this); };
-           bool                DOMDocumentTypeImpl::hasChildNodes() const                   {return fParent.hasChildNodes (); };
-           DOMNode          *DOMDocumentTypeImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
-                                                                            {return fParent.insertBefore (newChild, refChild); };
-           void                DOMDocumentTypeImpl::normalize()                             {fParent.normalize (); };
-           DOMNode          *DOMDocumentTypeImpl::removeChild(DOMNode *oldChild)        {return fParent.removeChild (oldChild); };
-           DOMNode          *DOMDocumentTypeImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
-                                                                            {return fParent.replaceChild (newChild, oldChild); };
-           bool                DOMDocumentTypeImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
-                                                                            {return fNode.isSupported (feature, version); };
-           void                DOMDocumentTypeImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); };
-           bool                DOMDocumentTypeImpl::hasAttributes() const                   {return fNode.hasAttributes(); };
+           DOMNode*         DOMDocumentTypeImpl::appendChild(DOMNode *newChild)          {return fParent.appendChild (newChild); };
+           DOMNamedNodeMap* DOMDocumentTypeImpl::getAttributes() const                   {return fNode.getAttributes (); };
+           DOMNodeList*     DOMDocumentTypeImpl::getChildNodes() const                   {return fParent.getChildNodes (); };
+           DOMNode*         DOMDocumentTypeImpl::getFirstChild() const                   {return fParent.getFirstChild (); };
+           DOMNode*         DOMDocumentTypeImpl::getLastChild() const                    {return fParent.getLastChild (); };
+     const XMLCh*           DOMDocumentTypeImpl::getLocalName() const                    {return fNode.getLocalName (); };
+     const XMLCh*           DOMDocumentTypeImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); };
+           DOMNode*         DOMDocumentTypeImpl::getNextSibling() const                  {return fChild.getNextSibling (); };
+     const XMLCh*           DOMDocumentTypeImpl::getNodeValue() const                    {return fNode.getNodeValue (); };
+           DOMDocument*     DOMDocumentTypeImpl::getOwnerDocument() const                {return fNode.getOwnerDocument (); };
+     const XMLCh*           DOMDocumentTypeImpl::getPrefix() const                       {return fNode.getPrefix (); };
+           DOMNode*         DOMDocumentTypeImpl::getParentNode() const                   {return fChild.getParentNode (this); };
+           DOMNode*         DOMDocumentTypeImpl::getPreviousSibling() const              {return fChild.getPreviousSibling (this); };
+           bool             DOMDocumentTypeImpl::hasChildNodes() const                   {return fParent.hasChildNodes (); };
+           DOMNode*         DOMDocumentTypeImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
+                                                                                         {return fParent.insertBefore (newChild, refChild); };
+           void             DOMDocumentTypeImpl::normalize()                             {fParent.normalize (); };
+           DOMNode*         DOMDocumentTypeImpl::removeChild(DOMNode *oldChild)          {return fParent.removeChild (oldChild); };
+           DOMNode*         DOMDocumentTypeImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
+                                                                                         {return fParent.replaceChild (newChild, oldChild); };
+           bool             DOMDocumentTypeImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
+                                                                                         {return fNode.isSupported (feature, version); };
+           void             DOMDocumentTypeImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); };
+           bool             DOMDocumentTypeImpl::hasAttributes() const                   {return fNode.hasAttributes(); };
+           void*            DOMDocumentTypeImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler)
+                                                                                         {return fNode.setUserData(key, data, handler); };
+           void*            DOMDocumentTypeImpl::getUserData(const XMLCh* key) const     {return fNode.getUserData(key); };
 
diff --git a/src/xercesc/dom/impl/DOMElementImpl.cpp b/src/xercesc/dom/impl/DOMElementImpl.cpp
index 8b6d1c75c..bf5570357 100644
--- a/src/xercesc/dom/impl/DOMElementImpl.cpp
+++ b/src/xercesc/dom/impl/DOMElementImpl.cpp
@@ -117,8 +117,9 @@ DOMElementImpl::~DOMElementImpl()
 
 DOMNode *DOMElementImpl::cloneNode(bool deep) const
 {
-    return new (getOwnerDocument()) DOMElementImpl(*this, deep);
-    return 0;
+    DOMNode* newNode = new (getOwnerDocument()) DOMElementImpl(*this, deep);
+    fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode);
+    return newNode;
 };
 
 
@@ -208,7 +209,7 @@ DOMAttr *DOMElementImpl::removeAttributeNode(DOMAttr *oldAttr)
     else
         throw DOMException(DOMException::NOT_FOUND_ERR, 0);
 
-    return (DOMAttr *)found;	
+    return (DOMAttr *)found;
 
 };
 
@@ -267,7 +268,7 @@ void DOMElementImpl::setReadOnly(bool readOnl, bool deep)
 
 //Introduced in DOM Level 2
 const XMLCh * DOMElementImpl::getAttributeNS(const XMLCh *fNamespaceURI,
-	const XMLCh *fLocalName) const
+    const XMLCh *fLocalName) const
 {
     DOMAttr * attr=
       (DOMAttr *)(fAttributes->getNamedItemNS(fNamespaceURI, fLocalName));
@@ -276,11 +277,11 @@ const XMLCh * DOMElementImpl::getAttributeNS(const XMLCh *fNamespaceURI,
 
 
 void DOMElementImpl::setAttributeNS(const XMLCh *fNamespaceURI,
-	const XMLCh *qualifiedName, const XMLCh *fValue)
+    const XMLCh *qualifiedName, const XMLCh *fValue)
 {
     if (fNode.isReadOnly())
         throw DOMException(
-	    DOMException::NO_MODIFICATION_ALLOWED_ERR, 0);
+        DOMException::NO_MODIFICATION_ALLOWED_ERR, 0);
 
     DOMAttr *newAttr =
         this->fNode.getOwnerDocument()->createAttributeNS(fNamespaceURI, qualifiedName);
@@ -290,7 +291,7 @@ void DOMElementImpl::setAttributeNS(const XMLCh *fNamespaceURI,
 
 
 void DOMElementImpl::removeAttributeNS(const XMLCh *fNamespaceURI,
-	const XMLCh *fLocalName)
+    const XMLCh *fLocalName)
 {
     if (fNode.isReadOnly())
         throw DOMException(
@@ -306,7 +307,7 @@ void DOMElementImpl::removeAttributeNS(const XMLCh *fNamespaceURI,
 
 
 DOMAttr *DOMElementImpl::getAttributeNodeNS(const XMLCh *fNamespaceURI,
-	const XMLCh *fLocalName) const
+    const XMLCh *fLocalName) const
 {
     return (DOMAttr *)fAttributes->getNamedItemNS(fNamespaceURI, fLocalName);
 }
@@ -316,7 +317,7 @@ DOMAttr *DOMElementImpl::setAttributeNodeNS(DOMAttr *newAttr)
 {
     if (fNode.isReadOnly())
         throw DOMException(
-	        DOMException::NO_MODIFICATION_ALLOWED_ERR, 0);
+            DOMException::NO_MODIFICATION_ALLOWED_ERR, 0);
 
     if (newAttr -> getOwnerDocument() != this -> getOwnerDocument())
         throw DOMException(DOMException::WRONG_DOCUMENT_ERR, 0);
@@ -331,7 +332,7 @@ DOMAttr *DOMElementImpl::setAttributeNodeNS(DOMAttr *newAttr)
 
 
 DOMNodeList *DOMElementImpl::getElementsByTagNameNS(const XMLCh *namespaceURI,
-	const XMLCh *localName) const
+    const XMLCh *localName) const
 {
     DOMDocumentImpl *docImpl = (DOMDocumentImpl *)getOwnerDocument();;
     return docImpl->getDeepNodeList(this, namespaceURI, localName);
@@ -350,7 +351,7 @@ bool DOMElementImpl::hasAttribute(const XMLCh *name) const
 
 
 bool DOMElementImpl::hasAttributeNS(const XMLCh *namespaceURI,
-	const XMLCh *localName) const
+    const XMLCh *localName) const
 {
     return (getAttributeNodeNS(namespaceURI, localName) != 0);
 };
@@ -360,15 +361,15 @@ bool DOMElementImpl::hasAttributeNS(const XMLCh *namespaceURI,
 // returns the default attribute map for this node from the owner document
 DOMAttrMapImpl *DOMElementImpl::getDefaultAttributes()
 {
-	if ((fNode.fOwnerNode == 0) || (getOwnerDocument() == 0))
-		return 0;
-
-	DOMDocument *tmpdoc = getOwnerDocument();
-	if (tmpdoc->getDoctype() == 0)
-		return 0;
-	
-	DOMNode *eldef = ((DOMDocumentTypeImpl*)tmpdoc->getDoctype())->getElements()->getNamedItem(getNodeName());
-	return (eldef == 0) ? 0 : (DOMAttrMapImpl *)(eldef->getAttributes());
+    if ((fNode.fOwnerNode == 0) || (getOwnerDocument() == 0))
+        return 0;
+
+    DOMDocument *tmpdoc = getOwnerDocument();
+    if (tmpdoc->getDoctype() == 0)
+        return 0;
+
+    DOMNode *eldef = ((DOMDocumentTypeImpl*)tmpdoc->getDoctype())->getElements()->getNamedItem(getNodeName());
+    return (eldef == 0) ? 0 : (DOMAttrMapImpl *)(eldef->getAttributes());
 }
 
 // resets all attributes for this node to their default values
@@ -389,27 +390,30 @@ void DOMElementImpl::setupDefaultAttributes()
 //
 //   Functions inherited from Node
 //
-           DOMNode          *DOMElementImpl::appendChild(DOMNode *newChild)        {return fParent.appendChild (newChild); };
-           DOMNodeList      *DOMElementImpl::getChildNodes() const 			        {return fParent.getChildNodes (); };
-           DOMNode          *DOMElementImpl::getFirstChild() const 			        {return fParent.getFirstChild (); };
-           DOMNode          *DOMElementImpl::getLastChild() const 		            {return fParent.getLastChild (); };
-     const XMLCh              *DOMElementImpl::getLocalName() const                    {return fNode.getLocalName (); };
-     const XMLCh              *DOMElementImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); };
-           DOMNode          *DOMElementImpl::getNextSibling() const                  {return fChild.getNextSibling (); };
-     const XMLCh              *DOMElementImpl::getNodeValue() const                    {return fNode.getNodeValue (); };
-           DOMDocument      *DOMElementImpl::getOwnerDocument() const                {return fNode.getOwnerDocument (); };
-     const XMLCh              *DOMElementImpl::getPrefix() const                       {return fNode.getPrefix (); };
-           DOMNode          *DOMElementImpl::getParentNode() const                   {return fChild.getParentNode (this); };
-           DOMNode          *DOMElementImpl::getPreviousSibling() const              {return fChild.getPreviousSibling (this); };
-           bool                DOMElementImpl::hasChildNodes() const                   {return fParent.hasChildNodes (); };
-           DOMNode          *DOMElementImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
-                                                                            {return fParent.insertBefore (newChild, refChild); };
-           void                DOMElementImpl::normalize()                             {fParent.normalize (); };
-           DOMNode          *DOMElementImpl::removeChild(DOMNode *oldChild)        {return fParent.removeChild (oldChild); };
-           DOMNode          *DOMElementImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
-                                                                            {return fParent.replaceChild (newChild, oldChild); };
-           bool                DOMElementImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
-                                                                            {return fNode.isSupported (feature, version); };
-           void                DOMElementImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); };
+           DOMNode*         DOMElementImpl::appendChild(DOMNode *newChild)          {return fParent.appendChild (newChild); };
+           DOMNodeList*     DOMElementImpl::getChildNodes() const                   {return fParent.getChildNodes (); };
+           DOMNode*         DOMElementImpl::getFirstChild() const                   {return fParent.getFirstChild (); };
+           DOMNode*         DOMElementImpl::getLastChild() const                    {return fParent.getLastChild (); };
+     const XMLCh*           DOMElementImpl::getLocalName() const                    {return fNode.getLocalName (); };
+     const XMLCh*           DOMElementImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); };
+           DOMNode*         DOMElementImpl::getNextSibling() const                  {return fChild.getNextSibling (); };
+     const XMLCh*           DOMElementImpl::getNodeValue() const                    {return fNode.getNodeValue (); };
+           DOMDocument*     DOMElementImpl::getOwnerDocument() const                {return fNode.getOwnerDocument (); };
+     const XMLCh*           DOMElementImpl::getPrefix() const                       {return fNode.getPrefix (); };
+           DOMNode*         DOMElementImpl::getParentNode() const                   {return fChild.getParentNode (this); };
+           DOMNode*         DOMElementImpl::getPreviousSibling() const              {return fChild.getPreviousSibling (this); };
+           bool             DOMElementImpl::hasChildNodes() const                   {return fParent.hasChildNodes (); };
+           DOMNode*         DOMElementImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
+                                                                                    {return fParent.insertBefore (newChild, refChild); };
+           void             DOMElementImpl::normalize()                             {fParent.normalize (); };
+           DOMNode*         DOMElementImpl::removeChild(DOMNode *oldChild)          {return fParent.removeChild (oldChild); };
+           DOMNode*         DOMElementImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
+                                                                                    {return fParent.replaceChild (newChild, oldChild); };
+           bool             DOMElementImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
+                                                                                    {return fNode.isSupported (feature, version); };
+           void             DOMElementImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); };
+           void*            DOMElementImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler)
+                                                                                    {return fNode.setUserData(key, data, handler); };
+           void*            DOMElementImpl::getUserData(const XMLCh* key) const     {return fNode.getUserData(key); };
 
 
diff --git a/src/xercesc/dom/impl/DOMElementNSImpl.cpp b/src/xercesc/dom/impl/DOMElementNSImpl.cpp
index cb9a0ebfe..4b04df798 100644
--- a/src/xercesc/dom/impl/DOMElementNSImpl.cpp
+++ b/src/xercesc/dom/impl/DOMElementNSImpl.cpp
@@ -116,7 +116,9 @@ DOMElementNSImpl::DOMElementNSImpl(const DOMElementNSImpl &other, bool deep) :
 };
 
 DOMNode * DOMElementNSImpl::cloneNode(bool deep) const {
-    return new (getOwnerDocument()) DOMElementNSImpl(*this, deep);
+    DOMNode* newNode = new (getOwnerDocument()) DOMElementNSImpl(*this, deep);
+    fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode);
+    return newNode;
 }
 
 const XMLCh * DOMElementNSImpl::getNamespaceURI() const
diff --git a/src/xercesc/dom/impl/DOMEntityImpl.cpp b/src/xercesc/dom/impl/DOMEntityImpl.cpp
index ba6a1068b..9785ceaca 100644
--- a/src/xercesc/dom/impl/DOMEntityImpl.cpp
+++ b/src/xercesc/dom/impl/DOMEntityImpl.cpp
@@ -94,7 +94,7 @@ DOMEntityImpl::DOMEntityImpl(const DOMEntityImpl &other, bool deep)
     fSystemId        = other.fSystemId;
     fNotationName    = other.fNotationName;
 
-    fRefEntity       = other.fRefEntity;	
+    fRefEntity       = other.fRefEntity;
     fNode.setReadOnly(true, true);
 };
 
@@ -105,7 +105,9 @@ DOMEntityImpl::~DOMEntityImpl() {
 
 DOMNode *DOMEntityImpl::cloneNode(bool deep) const
 {
-    return new (getOwnerDocument()) DOMEntityImpl(*this, deep);
+    DOMNode* newNode = new (getOwnerDocument()) DOMEntityImpl(*this, deep);
+    fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode);
+    return newNode;
 };
 
 
@@ -165,16 +167,16 @@ void DOMEntityImpl::setSystemId(const XMLCh *arg)
 
 void   DOMEntityImpl::setEntityRef(DOMEntityReference* other)
 {
-	fRefEntity = other;
+    fRefEntity = other;
 }
 
 
-DOMEntityReference*		DOMEntityImpl::getEntityRef() const
+DOMEntityReference*  DOMEntityImpl::getEntityRef() const
 {
-	return fRefEntity;
+    return fRefEntity;
 }
 
-void	DOMEntityImpl::cloneEntityRefTree() const
+void  DOMEntityImpl::cloneEntityRefTree() const
 {
     // cast off const.  This method is const because it is
     //   called from a bunch of logically const methods, like
@@ -195,26 +197,26 @@ void	DOMEntityImpl::cloneEntityRefTree() const
 DOMNode * DOMEntityImpl::getFirstChild() const
 {
     cloneEntityRefTree();
-	return fParent.fFirstChild;
+    return fParent.fFirstChild;
 };
 
 DOMNode *   DOMEntityImpl::getLastChild() const
 {
-	cloneEntityRefTree();
-	return fParent.getLastChild();
+    cloneEntityRefTree();
+    return fParent.getLastChild();
 }
 
 DOMNodeList* DOMEntityImpl::getChildNodes() const
 {
-	cloneEntityRefTree();
-	return this->fParent.getChildNodes();
+    cloneEntityRefTree();
+    return this->fParent.getChildNodes();
 
 }
 
 bool DOMEntityImpl::hasChildNodes() const
 {
-	cloneEntityRefTree();
-	return fParent.fFirstChild!=0;
+    cloneEntityRefTree();
+    return fParent.fFirstChild!=0;
 }
 
 
@@ -222,26 +224,29 @@ bool DOMEntityImpl::hasChildNodes() const
 //  Functions inherited from Node
 //
 
-           DOMNode          *DOMEntityImpl::appendChild(DOMNode *newChild)        {return fParent.appendChild (newChild); };
-           DOMNamedNodeMap  *DOMEntityImpl::getAttributes() const 			        {return fNode.getAttributes (); };
-     const XMLCh              *DOMEntityImpl::getLocalName() const                    {return fNode.getLocalName (); };
-     const XMLCh              *DOMEntityImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); };
-           DOMNode          *DOMEntityImpl::getNextSibling() const                  {return fNode.getNextSibling (); };
-     const XMLCh              *DOMEntityImpl::getNodeValue() const                    {return fNode.getNodeValue (); };
-           DOMDocument      *DOMEntityImpl::getOwnerDocument() const                {return fNode.getOwnerDocument (); };
-     const XMLCh              *DOMEntityImpl::getPrefix() const                       {return fNode.getPrefix (); };
-           DOMNode          *DOMEntityImpl::getParentNode() const                   {return fNode.getParentNode (); };
-           DOMNode          *DOMEntityImpl::getPreviousSibling() const              {return fNode.getPreviousSibling (); };
-           DOMNode          *DOMEntityImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
-                                                                            {return fParent.insertBefore (newChild, refChild); };
-           void                DOMEntityImpl::normalize()                             {fParent.normalize (); };
-           DOMNode          *DOMEntityImpl::removeChild(DOMNode *oldChild)        {return fParent.removeChild (oldChild); };
-           DOMNode          *DOMEntityImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
-                                                                            {return fParent.replaceChild (newChild, oldChild); };
-           bool                DOMEntityImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
-                                                                            {return fNode.isSupported (feature, version); };
-           void                DOMEntityImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); };
-           bool                DOMEntityImpl::hasAttributes() const                   {return fNode.hasAttributes(); };
+           DOMNode*         DOMEntityImpl::appendChild(DOMNode *newChild)          {return fParent.appendChild (newChild); };
+           DOMNamedNodeMap* DOMEntityImpl::getAttributes() const                   {return fNode.getAttributes (); };
+     const XMLCh*           DOMEntityImpl::getLocalName() const                    {return fNode.getLocalName (); };
+     const XMLCh*           DOMEntityImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); };
+           DOMNode*         DOMEntityImpl::getNextSibling() const                  {return fNode.getNextSibling (); };
+     const XMLCh*           DOMEntityImpl::getNodeValue() const                    {return fNode.getNodeValue (); };
+           DOMDocument*     DOMEntityImpl::getOwnerDocument() const                {return fNode.getOwnerDocument (); };
+     const XMLCh*           DOMEntityImpl::getPrefix() const                       {return fNode.getPrefix (); };
+           DOMNode*         DOMEntityImpl::getParentNode() const                   {return fNode.getParentNode (); };
+           DOMNode*         DOMEntityImpl::getPreviousSibling() const              {return fNode.getPreviousSibling (); };
+           DOMNode*         DOMEntityImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
+                                                                                   {return fParent.insertBefore (newChild, refChild); };
+           void             DOMEntityImpl::normalize()                             {fParent.normalize (); };
+           DOMNode*         DOMEntityImpl::removeChild(DOMNode *oldChild)          {return fParent.removeChild (oldChild); };
+           DOMNode*         DOMEntityImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
+                                                                                   {return fParent.replaceChild (newChild, oldChild); };
+           bool             DOMEntityImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
+                                                                                   {return fNode.isSupported (feature, version); };
+           void             DOMEntityImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); };
+           bool             DOMEntityImpl::hasAttributes() const                   {return fNode.hasAttributes(); };
+           void*            DOMEntityImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler) 
+                                                                                   {return fNode.setUserData(key, data, handler); };
+           void*            DOMEntityImpl::getUserData(const XMLCh* key) const     {return fNode.getUserData(key); };
 
 //Introduced in DOM Level 3
 const XMLCh* DOMEntityImpl::getActualEncoding() const {
diff --git a/src/xercesc/dom/impl/DOMEntityReferenceImpl.cpp b/src/xercesc/dom/impl/DOMEntityReferenceImpl.cpp
index 95791d505..79abc2f49 100644
--- a/src/xercesc/dom/impl/DOMEntityReferenceImpl.cpp
+++ b/src/xercesc/dom/impl/DOMEntityReferenceImpl.cpp
@@ -113,7 +113,9 @@ DOMEntityReferenceImpl::~DOMEntityReferenceImpl()
 
 DOMNode *DOMEntityReferenceImpl::cloneNode(bool deep) const
 {
-    return new (getOwnerDocument()) DOMEntityReferenceImpl(*this, deep);
+    DOMNode* newNode = new (getOwnerDocument()) DOMEntityReferenceImpl(*this, deep);
+    fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode);
+    return newNode;
 }
 
 
@@ -159,27 +161,30 @@ void DOMEntityReferenceImpl::setReadOnly(bool readOnl,bool deep)
 //
 
 
-           DOMNode          *DOMEntityReferenceImpl::appendChild(DOMNode *newChild)        {return fParent.appendChild (newChild); };
-           DOMNamedNodeMap  *DOMEntityReferenceImpl::getAttributes() const 			        {return fNode.getAttributes (); };
-           DOMNodeList      *DOMEntityReferenceImpl::getChildNodes() const 			        {return fParent.getChildNodes (); };
-           DOMNode          *DOMEntityReferenceImpl::getFirstChild() const 			        {return fParent.getFirstChild (); };
-           DOMNode          *DOMEntityReferenceImpl::getLastChild() const 		            {return fParent.getLastChild (); };
-     const XMLCh              *DOMEntityReferenceImpl::getLocalName() const                    {return fNode.getLocalName (); };
-     const XMLCh              *DOMEntityReferenceImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); };
-           DOMNode          *DOMEntityReferenceImpl::getNextSibling() const                  {return fChild.getNextSibling (); };
-     const XMLCh              *DOMEntityReferenceImpl::getNodeValue() const                    {return fNode.getNodeValue (); };
-           DOMDocument      *DOMEntityReferenceImpl::getOwnerDocument() const                {return fNode.getOwnerDocument (); };
-     const XMLCh              *DOMEntityReferenceImpl::getPrefix() const                       {return fNode.getPrefix (); };
-           DOMNode          *DOMEntityReferenceImpl::getParentNode() const                   {return fChild.getParentNode (this); };
-           DOMNode          *DOMEntityReferenceImpl::getPreviousSibling() const              {return fChild.getPreviousSibling (this); };
-           bool                DOMEntityReferenceImpl::hasChildNodes() const                   {return fParent.hasChildNodes (); };
-           DOMNode          *DOMEntityReferenceImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
-                                                                            {return fParent.insertBefore (newChild, refChild); };
-           void                DOMEntityReferenceImpl::normalize()                             {fParent.normalize (); };
-           DOMNode          *DOMEntityReferenceImpl::removeChild(DOMNode *oldChild)        {return fParent.removeChild (oldChild); };
-           DOMNode          *DOMEntityReferenceImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
-                                                                            {return fParent.replaceChild (newChild, oldChild); };
-           bool                DOMEntityReferenceImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
-                                                                            {return fNode.isSupported (feature, version); };
-           void                DOMEntityReferenceImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); };
-           bool                DOMEntityReferenceImpl::hasAttributes() const                   {return fNode.hasAttributes(); };
+           DOMNode*         DOMEntityReferenceImpl::appendChild(DOMNode *newChild)          {return fParent.appendChild (newChild); };
+           DOMNamedNodeMap* DOMEntityReferenceImpl::getAttributes() const                   {return fNode.getAttributes (); };
+           DOMNodeList*     DOMEntityReferenceImpl::getChildNodes() const                   {return fParent.getChildNodes (); };
+           DOMNode*         DOMEntityReferenceImpl::getFirstChild() const                   {return fParent.getFirstChild (); };
+           DOMNode*         DOMEntityReferenceImpl::getLastChild() const                    {return fParent.getLastChild (); };
+     const XMLCh*           DOMEntityReferenceImpl::getLocalName() const                    {return fNode.getLocalName (); };
+     const XMLCh*           DOMEntityReferenceImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); };
+           DOMNode*         DOMEntityReferenceImpl::getNextSibling() const                  {return fChild.getNextSibling (); };
+     const XMLCh*           DOMEntityReferenceImpl::getNodeValue() const                    {return fNode.getNodeValue (); };
+           DOMDocument*     DOMEntityReferenceImpl::getOwnerDocument() const                {return fNode.getOwnerDocument (); };
+     const XMLCh*           DOMEntityReferenceImpl::getPrefix() const                       {return fNode.getPrefix (); };
+           DOMNode*         DOMEntityReferenceImpl::getParentNode() const                   {return fChild.getParentNode (this); };
+           DOMNode*         DOMEntityReferenceImpl::getPreviousSibling() const              {return fChild.getPreviousSibling (this); };
+           bool             DOMEntityReferenceImpl::hasChildNodes() const                   {return fParent.hasChildNodes (); };
+           DOMNode*         DOMEntityReferenceImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
+                                                                                            {return fParent.insertBefore (newChild, refChild); };
+           void             DOMEntityReferenceImpl::normalize()                             {fParent.normalize (); };
+           DOMNode*         DOMEntityReferenceImpl::removeChild(DOMNode *oldChild)          {return fParent.removeChild (oldChild); };
+           DOMNode*         DOMEntityReferenceImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
+                                                                                            {return fParent.replaceChild (newChild, oldChild); };
+           bool             DOMEntityReferenceImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
+                                                                                            {return fNode.isSupported (feature, version); };
+           void             DOMEntityReferenceImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); };
+           bool             DOMEntityReferenceImpl::hasAttributes() const                   {return fNode.hasAttributes(); };
+           void*            DOMEntityReferenceImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler)
+                                                                                            {return fNode.setUserData(key, data, handler); };
+           void*            DOMEntityReferenceImpl::getUserData(const XMLCh* key) const     {return fNode.getUserData(key); };
diff --git a/src/xercesc/dom/impl/DOMNamedNodeMapImpl.cpp b/src/xercesc/dom/impl/DOMNamedNodeMapImpl.cpp
index 242e05eea..cf696ca36 100644
--- a/src/xercesc/dom/impl/DOMNamedNodeMapImpl.cpp
+++ b/src/xercesc/dom/impl/DOMNamedNodeMapImpl.cpp
@@ -284,9 +284,6 @@ void DOMNamedNodeMapImpl::setReadOnly(bool readOnl, bool deep)
     // this->fReadOnly=readOnl;
     if(deep && fNodes!=0)
     {
-        //Enumeration e=fNodes->elements();
-        //while(e->hasMoreElements())
-        //      ((NodeImpl)e->nextElement())->setReadOnly(readOnl,deep);
         int sz = fNodes->size();
         for (int i=0; i<sz; ++i) {
             castToNodeImpl(fNodes->elementAt(i))->setReadOnly(readOnl, deep);
diff --git a/src/xercesc/dom/impl/DOMNodeImpl.cpp b/src/xercesc/dom/impl/DOMNodeImpl.cpp
index fe272cea5..4fc8cfd8a 100644
--- a/src/xercesc/dom/impl/DOMNodeImpl.cpp
+++ b/src/xercesc/dom/impl/DOMNodeImpl.cpp
@@ -95,8 +95,8 @@ const unsigned short DOMNodeImpl::CHILDNODE    = 0x1<<11;
 static DOMNodeListImpl *gEmptyNodeList;  // make a singleton empty node list
 static void reinitEmptyNodeList()
 {
-	delete gEmptyNodeList;
-	gEmptyNodeList = 0;
+    delete gEmptyNodeList;
+    gEmptyNodeList = 0;
 }
 
 // -----------------------------------------------------------------------
@@ -111,7 +111,8 @@ DOMNodeImpl::DOMNodeImpl(DOMNode *ownerNode)
 
 // This only makes a shallow copy, cloneChildren must also be called for a
 // deep clone
-DOMNodeImpl::DOMNodeImpl(const DOMNodeImpl &other) {
+DOMNodeImpl::DOMNodeImpl(const DOMNodeImpl &other)
+{
     this->flags = other.flags;
     this->isReadOnly(false);
 
@@ -123,13 +124,6 @@ DOMNodeImpl::DOMNodeImpl(const DOMNodeImpl &other) {
 
 
 DOMNodeImpl::~DOMNodeImpl() {
-    //
-    //   Note:  With current memory mgmt, destructors are not called for nodes.
-
-    //	if (hasUserData())
-    //	{
-    //		setUserData(0);
-    //	}
 };
 
 
@@ -149,7 +143,7 @@ DOMNamedNodeMap * DOMNodeImpl::getAttributes() const {
 
 
 DOMNodeList *DOMNodeImpl::getChildNodes() const {
-	static XMLRegisterCleanup emptyNodeListCleanup;
+    static XMLRegisterCleanup emptyNodeListCleanup;
 
     if (gEmptyNodeList == 0)
     {
@@ -233,17 +227,29 @@ DOMNode*  DOMNodeImpl::getPreviousSibling() const
     return 0;                // overridden in ChildNode
 };
 
+void* DOMNodeImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler)
+{
+   if (!data && !hasUserData())
+       return 0;
+
+    hasUserData(true);
+    return ((DOMDocumentImpl*)getOwnerDocument())->setUserData(this, key, data, handler);
+}
 
-void *DOMNodeImpl::getUserData() const
+void* DOMNodeImpl::getUserData(const XMLCh* key) const
 {
-    void *userData = 0;
-#ifdef _revisit
-    if (hasUserData()) {
-        userData =  (DOMDocumentImpl *)getOwnerDocument()->getUserData(this);
-    }
-#endif
-  return userData;
-};
+   if (hasUserData())
+       return ((DOMDocumentImpl*)getOwnerDocument())->getUserData(this, key);
+    return 0;
+}
+
+void DOMNodeImpl::callUserDataHandlers(DOMUserDataHandler::DOMOperationType operation,
+                                       const DOMNode* src,
+                                       const DOMNode* dst) const
+{
+    ((DOMDocumentImpl*)getOwnerDocument())->callUserDataHandlers(this, operation, src, dst);
+}
+
 
 bool DOMNodeImpl::hasChildNodes() const
 {
@@ -294,19 +300,6 @@ void DOMNodeImpl::setReadOnly(bool readOnl, bool deep)
 }
 
 
-void DOMNodeImpl::setUserData(void * val)
-{
-	DOMDocumentImpl *doc = (DOMDocumentImpl *)this->getOwnerDocument();
-
-    doc->setUserData(val);
-	if (val)
-		hasUserData(true);
-	else
-		hasUserData(false);
-};
-
-
-
 //Introduced in DOM Level 2
 
 void DOMNodeImpl::normalize()
@@ -373,14 +366,14 @@ const XMLCh *DOMNodeImpl::getXmlnsString()    {return s_xmlns;};
 const XMLCh *DOMNodeImpl::getXmlnsURIString() {return s_xmlnsURI;};
 
 //Return a URI mapped from the given prefix and namespaceURI as below
-//	prefix   namespaceURI		output
+//    prefix   namespaceURI    output
 //---------------------------------------------------
-//	"xml"      xmlURI            xmlURI
-//	"xml"	   otherwise         NAMESPACE_ERR
-//	"xmlns"	   xmlnsURI	         xmlnsURI (nType = ATTRIBUTE_NODE only)
-//	"xmlns"	   otherwise         NAMESPACE_ERR (nType = ATTRIBUTE_NODE only)
-//   != null   null or ""        NAMESPACE_ERR
-//	else       any			     namesapceURI
+//    "xml"     xmlURI          xmlURI
+//    "xml"     otherwise       NAMESPACE_ERR
+//    "xmlns"   xmlnsURI        xmlnsURI (nType = ATTRIBUTE_NODE only)
+//    "xmlns"   otherwise       NAMESPACE_ERR (nType = ATTRIBUTE_NODE only)
+//    != null   null or ""      NAMESPACE_ERR
+//    else      any             namesapceURI
 const XMLCh* DOMNodeImpl::mapPrefix(const XMLCh *prefix,
                                      const XMLCh *namespaceURI, short nType)
 {
diff --git a/src/xercesc/dom/impl/DOMNodeImpl.hpp b/src/xercesc/dom/impl/DOMNodeImpl.hpp
index 70f9fed9f..1a335c0d4 100644
--- a/src/xercesc/dom/impl/DOMNodeImpl.hpp
+++ b/src/xercesc/dom/impl/DOMNodeImpl.hpp
@@ -89,6 +89,7 @@
  **/
 
 #include <xercesc/util/XercesDefs.hpp>
+#include <xercesc/dom/DOMUserDataHandler.hpp>
 
 class DOMNamedNodeMap;
 class DOMNodeList;
@@ -100,6 +101,7 @@ public:
 
     // data
     DOMNode                *fOwnerNode; // typically the parent but not always!
+
     unsigned short flags;
 
     static const unsigned short READONLY;
@@ -111,7 +113,7 @@ public:
     static const unsigned short IGNORABLEWS;
     static const unsigned short SETVALUE;
     static const unsigned short ID_ATTR;
-	static const unsigned short USERDATA;
+    static const unsigned short USERDATA;
     static const unsigned short LEAFNODETYPE;
     static const unsigned short CHILDNODE;
 
@@ -121,37 +123,43 @@ public:
     DOMNodeImpl(const DOMNodeImpl &other);
     ~DOMNodeImpl();
 
-     DOMNode         *appendChild(DOMNode *newChild);
-     DOMNamedNodeMap * getAttributes() const;
-     DOMNodeList     * getChildNodes() const;
-     DOMNode         * getFirstChild() const;
-     DOMNode         * getLastChild() const;
-     const XMLCh       * getLocalName() const;
-     const XMLCh       * getNamespaceURI() const;
-     DOMNode         * getNextSibling() const;
-     const XMLCh       * getNodeValue() const;
-     DOMDocument     * getOwnerDocument() const;
-     DOMNode         * getParentNode() const;
-     const XMLCh       * getPrefix() const;
-     DOMNode         * getPreviousSibling() const;
-     void              * getUserData() const;
-     bool                hasChildNodes() const;
-     DOMNode         * insertBefore(DOMNode *newChild, DOMNode *refChild);
-     void                normalize();
-     DOMNode         * removeChild(DOMNode *oldChild);
-     DOMNode         * replaceChild(DOMNode *newChild, DOMNode *oldChild);
-     void                setNodeValue(const XMLCh *value);
-     void                setPrefix(const XMLCh *fPrefix);
-     void                setReadOnly(bool readOnly, bool deep);
-     void                setUserData(void *value);
-     bool                isSupported(const XMLCh *feature, const XMLCh *version) const;
-     bool                hasAttributes() const;
-
-    static  bool         isKidOK(DOMNode *parent, DOMNode *child);
+    DOMNode         * appendChild(DOMNode *newChild);
+    DOMNamedNodeMap * getAttributes() const;
+    DOMNodeList     * getChildNodes() const;
+    DOMNode         * getFirstChild() const;
+    DOMNode         * getLastChild() const;
+    const XMLCh     * getLocalName() const;
+    const XMLCh     * getNamespaceURI() const;
+    DOMNode         * getNextSibling() const;
+    const XMLCh     * getNodeValue() const;
+    DOMDocument     * getOwnerDocument() const;
+    DOMNode         * getParentNode() const;
+    const XMLCh     * getPrefix() const;
+    DOMNode         * getPreviousSibling() const;
+    bool              hasChildNodes() const;
+    DOMNode         * insertBefore(DOMNode *newChild, DOMNode *refChild);
+    void              normalize();
+    DOMNode         * removeChild(DOMNode *oldChild);
+    DOMNode         * replaceChild(DOMNode *newChild, DOMNode *oldChild);
+    void              setNodeValue(const XMLCh *value);
+    void              setPrefix(const XMLCh *fPrefix);
+    void              setReadOnly(bool readOnly, bool deep);
+    bool              isSupported(const XMLCh *feature, const XMLCh *version) const;
+    bool              hasAttributes() const;
+
+    static  bool      isKidOK(DOMNode *parent, DOMNode *child);
+
+    // user data utility
+    void*             setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler);
+    void*             getUserData(const XMLCh* key) const;
+    void              callUserDataHandlers(DOMUserDataHandler::DOMOperationType operation,
+                                           const DOMNode* src,
+                                           const DOMNode* dst) const;
+
 
     //Utility, not part of DOM Level 2 API
-    static const XMLCh * mapPrefix(const XMLCh *prefix,
-	                                  const XMLCh *namespaceURI, short nType);
+    static const XMLCh *mapPrefix(const XMLCh *prefix,
+                               const XMLCh *namespaceURI, short nType);
 
     static const XMLCh *getXmlnsString();
     static const XMLCh *getXmlnsURIString();
@@ -283,31 +291,33 @@ public: // should really be protected - ALH
 //   accurately get all of the functions declared.
 //
 #define DOMNODE_FUNCTIONS \
-    virtual       DOMNode          *appendChild(DOMNode *newChild) ;\
-    virtual       DOMNode          *cloneNode(bool deep) const ;\
-    virtual       DOMNamedNodeMap  *getAttributes() const ;\
-    virtual       DOMNodeList      *getChildNodes() const ;\
-    virtual       DOMNode          *getFirstChild() const ;\
-    virtual       DOMNode          *getLastChild() const ;\
-    virtual const XMLCh *             getLocalName() const ;\
-    virtual const XMLCh *             getNamespaceURI() const ;\
-    virtual       DOMNode          *getNextSibling() const ;\
-    virtual const XMLCh              *getNodeName() const ;\
-    virtual       short               getNodeType() const ;\
-    virtual const XMLCh              *getNodeValue() const ;\
-    virtual       DOMDocument      *getOwnerDocument() const ;\
-    virtual const XMLCh *             getPrefix() const ;\
-    virtual       DOMNode          *getParentNode() const ;\
-    virtual       DOMNode          *getPreviousSibling() const ;\
-    virtual       bool                hasChildNodes() const ;\
-    virtual       DOMNode          *insertBefore(DOMNode *newChild, DOMNode *refChild) ;\
-    virtual       void                normalize() ;\
-    virtual       DOMNode          *removeChild(DOMNode *oldChild) ;\
-    virtual       DOMNode          *replaceChild(DOMNode *newChild, DOMNode *oldChild) ;\
-    virtual       void                setNodeValue(const XMLCh  *nodeValue) ;\
-    virtual       bool                isSupported(const XMLCh *feature, const XMLCh *version) const ;\
-    virtual       bool                hasAttributes() const ;\
-    virtual       void                setPrefix(const XMLCh * prefix)
+    virtual       DOMNode*         appendChild(DOMNode *newChild) ;\
+    virtual       DOMNode*         cloneNode(bool deep) const ;\
+    virtual       DOMNamedNodeMap* getAttributes() const ;\
+    virtual       DOMNodeList*     getChildNodes() const ;\
+    virtual       DOMNode*         getFirstChild() const ;\
+    virtual       DOMNode*         getLastChild() const ;\
+    virtual const XMLCh*           getLocalName() const ;\
+    virtual const XMLCh*           getNamespaceURI() const ;\
+    virtual       DOMNode*         getNextSibling() const ;\
+    virtual const XMLCh*           getNodeName() const ;\
+    virtual       short            getNodeType() const ;\
+    virtual const XMLCh*           getNodeValue() const ;\
+    virtual       DOMDocument*     getOwnerDocument() const ;\
+    virtual const XMLCh*           getPrefix() const ;\
+    virtual       DOMNode*         getParentNode() const ;\
+    virtual       DOMNode*         getPreviousSibling() const ;\
+    virtual       bool             hasChildNodes() const ;\
+    virtual       DOMNode*         insertBefore(DOMNode *newChild, DOMNode *refChild) ;\
+    virtual       void             normalize() ;\
+    virtual       DOMNode*         removeChild(DOMNode *oldChild) ;\
+    virtual       DOMNode*         replaceChild(DOMNode *newChild, DOMNode *oldChild) ;\
+    virtual       void             setNodeValue(const XMLCh  *nodeValue) ;\
+    virtual       bool             isSupported(const XMLCh *feature, const XMLCh *version) const ;\
+    virtual       bool             hasAttributes() const ;\
+    virtual       void             setPrefix(const XMLCh * prefix) ;\
+    virtual       void*            setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler);\
+    virtual       void*            getUserData(const XMLCh* key) const;
 
 
 /*
@@ -316,30 +326,33 @@ public: // should really be protected - ALH
  *    function to the appropriate implementation.
  *    Functions that must be supplied by every node class are omitted.
  *
-           DOMNode          *xxx::appendChild(DOMNode *newChild)        {return fParent.appendChild (newChild); };
-           DOMNamedNodeMap  *xxx::getAttributes() const 			        {return fNode.getAttributes (); };
-           DOMNodeList      *xxx::getChildNodes() const 			        {return fParent.getChildNodes (); };
-           DOMNode          *xxx::getFirstChild() const 			        {return fParent.getFirstChild (); };
-           DOMNode          *xxx::getLastChild() const 		            {return fParent.getLastChild (); };
-     const XMLCh              *xxx::getLocalName() const                    {return fNode.getLocalName (); };
-     const XMLCh              *xxx::getNamespaceURI() const                 {return fNode.getNamespaceURI (); };
-           DOMNode          *xxx::getNextSibling() const                  {return fChild.getNextSibling (); };
-     const XMLCh              *xxx::getNodeValue() const                    {return fNode.getNodeValue (); };
-           DOMDocument      *xxx::getOwnerDocument() const                {return fNode.getOwnerDocument (); };
-     const XMLCh              *xxx::getPrefix() const                       {return fNode.getPrefix (); };
-           DOMNode          *xxx::getParentNode() const                   {return fChild.getParentNode (this); };
-           DOMNode          *xxx::getPreviousSibling() const              {return fChild.getPreviousSibling (this); };
-           bool                xxx::hasChildNodes() const                   {return fParent.hasChildNodes (); };
-           DOMNode          *xxx::insertBefore(DOMNode *newChild, DOMNode *refChild)
-                                                                            {return fParent.insertBefore (newChild, refChild); };
-           void                xxx::normalize()                             {fNode.normalize (); };
-           DOMNode          *xxx::removeChild(DOMNode *oldChild)        {return fParent.removeChild (oldChild); };
-           DOMNode          *xxx::replaceChild(DOMNode *newChild, DOMNode *oldChild)
-                                                                            {return fParent.replaceChild (newChild, oldChild); };
-           void                xxx::setNodeValue(const XMLCh  *nodeValue)   {fNode.setNodeValue (nodeValue); };
-           bool                xxx::supports(const XMLCh *feature, const XMLCh *version) const
-                                                                            {return fNode.supports (feature, version); };
-           void                xxx::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); };
+           DOMNode*         xxx::appendChild(DOMNode *newChild)          {return fParent.appendChild (newChild); };
+           DOMNamedNodeMap* xxx::getAttributes() const                   {return fNode.getAttributes (); };
+           DOMNodeList*     xxx::getChildNodes() const                   {return fParent.getChildNodes (); };
+           DOMNode*         xxx::getFirstChild() const                   {return fParent.getFirstChild (); };
+           DOMNode*         xxx::getLastChild() const                    {return fParent.getLastChild (); };
+     const XMLCh*           xxx::getLocalName() const                    {return fNode.getLocalName (); };
+     const XMLCh*           xxx::getNamespaceURI() const                 {return fNode.getNamespaceURI (); };
+           DOMNode*         xxx::getNextSibling() const                  {return fChild.getNextSibling (); };
+     const XMLCh*           xxx::getNodeValue() const                    {return fNode.getNodeValue (); };
+           DOMDocument*     xxx::getOwnerDocument() const                {return fNode.getOwnerDocument (); };
+     const XMLCh*           xxx::getPrefix() const                       {return fNode.getPrefix (); };
+           DOMNode*         xxx::getParentNode() const                   {return fChild.getParentNode (this); };
+           DOMNode*         xxx::getPreviousSibling() const              {return fChild.getPreviousSibling (this); };
+           bool             xxx::hasChildNodes() const                   {return fParent.hasChildNodes (); };
+           DOMNode*         xxx::insertBefore(DOMNode *newChild, DOMNode *refChild)
+                                                                         {return fParent.insertBefore (newChild, refChild); };
+           void             xxx::normalize()                             {fParent.normalize(); };
+           DOMNode*         xxx::removeChild(DOMNode *oldChild)          {return fParent.removeChild (oldChild); };
+           DOMNode*         xxx::replaceChild(DOMNode *newChild, DOMNode *oldChild)
+                                                                         {return fParent.replaceChild (newChild, oldChild); };
+           bool             xxx::isSupported(const XMLCh *feature, const XMLCh *version) const
+                                                                         {return fNode.isSupported (feature, version); };
+           void             xxx::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); };
+           bool             xxx::hasAttributes() const                   {return fNode.hasAttributes(); };
+           void*            xxx::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler)
+                                                                         {return fNode.setUserData(key, data, handler); };
+           void*            xxx::getUserData(const XMLCh* key) const     {return fNode.getUserData(key); };
 
 */
 
diff --git a/src/xercesc/dom/impl/DOMNotationImpl.cpp b/src/xercesc/dom/impl/DOMNotationImpl.cpp
index ee15b4d78..00236a74a 100644
--- a/src/xercesc/dom/impl/DOMNotationImpl.cpp
+++ b/src/xercesc/dom/impl/DOMNotationImpl.cpp
@@ -89,7 +89,9 @@ DOMNotationImpl::~DOMNotationImpl()
 
 DOMNode *DOMNotationImpl::cloneNode(bool deep) const
 {
-    return new (getOwnerDocument()) DOMNotationImpl(*this, deep);
+    DOMNode* newNode = new (getOwnerDocument()) DOMNotationImpl(*this, deep);
+    fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode);
+    return newNode;
 };
 
 
@@ -144,29 +146,32 @@ void DOMNotationImpl::setSystemId(const XMLCh *arg)
 
 
 
-           DOMNode          *DOMNotationImpl::appendChild(DOMNode *newChild)        {return fNode.appendChild (newChild); };
-           DOMNamedNodeMap  *DOMNotationImpl::getAttributes() const 			        {return fNode.getAttributes (); };
-           DOMNodeList      *DOMNotationImpl::getChildNodes() const 			        {return fNode.getChildNodes (); };
-           DOMNode          *DOMNotationImpl::getFirstChild() const 			        {return fNode.getFirstChild (); };
-           DOMNode          *DOMNotationImpl::getLastChild() const 		            {return fNode.getLastChild (); };
-     const XMLCh              *DOMNotationImpl::getLocalName() const                    {return fNode.getLocalName (); };
-     const XMLCh              *DOMNotationImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); };
-           DOMNode          *DOMNotationImpl::getNextSibling() const                  {return fNode.getNextSibling (); };
-     const XMLCh              *DOMNotationImpl::getNodeValue() const                    {return fNode.getNodeValue (); };
-           DOMDocument      *DOMNotationImpl::getOwnerDocument() const                {return fNode.getOwnerDocument (); };
-     const XMLCh              *DOMNotationImpl::getPrefix() const                       {return fNode.getPrefix (); };
-           DOMNode          *DOMNotationImpl::getParentNode() const                   {return fNode.getParentNode (); };
-           DOMNode          *DOMNotationImpl::getPreviousSibling() const              {return fNode.getPreviousSibling (); };
-           bool                DOMNotationImpl::hasChildNodes() const                   {return fNode.hasChildNodes (); };
-           DOMNode          *DOMNotationImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
-                                                                            {return fNode.insertBefore (newChild, refChild); };
-           void                DOMNotationImpl::normalize()                             {fNode.normalize (); };
-           DOMNode          *DOMNotationImpl::removeChild(DOMNode *oldChild)        {return fNode.removeChild (oldChild); };
-           DOMNode          *DOMNotationImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
-                                                                            {return fNode.replaceChild (newChild, oldChild); };
-           bool                DOMNotationImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
-                                                                            {return fNode.isSupported (feature, version); };
-           void                DOMNotationImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); };
-           bool                DOMNotationImpl::hasAttributes() const                   {return fNode.hasAttributes(); };
+           DOMNode*         DOMNotationImpl::appendChild(DOMNode *newChild)          {return fNode.appendChild (newChild); };
+           DOMNamedNodeMap* DOMNotationImpl::getAttributes() const                   {return fNode.getAttributes (); };
+           DOMNodeList*     DOMNotationImpl::getChildNodes() const                   {return fNode.getChildNodes (); };
+           DOMNode*         DOMNotationImpl::getFirstChild() const                   {return fNode.getFirstChild (); };
+           DOMNode*         DOMNotationImpl::getLastChild() const                    {return fNode.getLastChild (); };
+     const XMLCh*           DOMNotationImpl::getLocalName() const                    {return fNode.getLocalName (); };
+     const XMLCh*           DOMNotationImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); };
+           DOMNode*         DOMNotationImpl::getNextSibling() const                  {return fNode.getNextSibling (); };
+     const XMLCh*           DOMNotationImpl::getNodeValue() const                    {return fNode.getNodeValue (); };
+           DOMDocument*     DOMNotationImpl::getOwnerDocument() const                {return fNode.getOwnerDocument (); };
+     const XMLCh*           DOMNotationImpl::getPrefix() const                       {return fNode.getPrefix (); };
+           DOMNode*         DOMNotationImpl::getParentNode() const                   {return fNode.getParentNode (); };
+           DOMNode*         DOMNotationImpl::getPreviousSibling() const              {return fNode.getPreviousSibling (); };
+           bool             DOMNotationImpl::hasChildNodes() const                   {return fNode.hasChildNodes (); };
+           DOMNode*         DOMNotationImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
+                                                                                     {return fNode.insertBefore (newChild, refChild); };
+           void             DOMNotationImpl::normalize()                             {fNode.normalize (); };
+           DOMNode*         DOMNotationImpl::removeChild(DOMNode *oldChild)          {return fNode.removeChild (oldChild); };
+           DOMNode*         DOMNotationImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
+                                                                                     {return fNode.replaceChild (newChild, oldChild); };
+           bool             DOMNotationImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
+                                                                                     {return fNode.isSupported (feature, version); };
+           void             DOMNotationImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); };
+           bool             DOMNotationImpl::hasAttributes() const                   {return fNode.hasAttributes(); };
+           void*            DOMNotationImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler)
+                                                                                     {return fNode.setUserData(key, data, handler); };
+           void*            DOMNotationImpl::getUserData(const XMLCh* key) const     {return fNode.getUserData(key); };
 
 
diff --git a/src/xercesc/dom/impl/DOMProcessingInstructionImpl.cpp b/src/xercesc/dom/impl/DOMProcessingInstructionImpl.cpp
index fefa6dc29..9c85d00ab 100644
--- a/src/xercesc/dom/impl/DOMProcessingInstructionImpl.cpp
+++ b/src/xercesc/dom/impl/DOMProcessingInstructionImpl.cpp
@@ -94,7 +94,9 @@ DOMProcessingInstructionImpl::~DOMProcessingInstructionImpl()
 
 DOMNode *DOMProcessingInstructionImpl::cloneNode(bool deep) const
 {
-    return new (getOwnerDocument()) DOMProcessingInstructionImpl(*this, deep);
+    DOMNode* newNode = new (getOwnerDocument()) DOMProcessingInstructionImpl(*this, deep);
+    fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode);
+    return newNode;
 };
 
 
@@ -164,26 +166,29 @@ void DOMProcessingInstructionImpl::setData(const XMLCh *arg)
 //
 //    Delegation stubs for inherited functions
 //
-           DOMNode          *DOMProcessingInstructionImpl::appendChild(DOMNode *newChild)        {return fNode.appendChild (newChild); };
-           DOMNamedNodeMap  *DOMProcessingInstructionImpl::getAttributes() const 			        {return fNode.getAttributes (); };
-           DOMNodeList      *DOMProcessingInstructionImpl::getChildNodes() const 			        {return fNode.getChildNodes (); };
-           DOMNode          *DOMProcessingInstructionImpl::getFirstChild() const 			        {return fNode.getFirstChild (); };
-           DOMNode          *DOMProcessingInstructionImpl::getLastChild() const 		            {return fNode.getLastChild (); };
-     const XMLCh              *DOMProcessingInstructionImpl::getLocalName() const                    {return fNode.getLocalName (); };
-     const XMLCh              *DOMProcessingInstructionImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); };
-           DOMNode          *DOMProcessingInstructionImpl::getNextSibling() const                  {return fChild.getNextSibling (); };
-           DOMDocument      *DOMProcessingInstructionImpl::getOwnerDocument() const                {return fNode.getOwnerDocument (); };
-     const XMLCh              *DOMProcessingInstructionImpl::getPrefix() const                       {return fNode.getPrefix (); };
-           DOMNode          *DOMProcessingInstructionImpl::getParentNode() const                   {return fChild.getParentNode (this); };
-           DOMNode          *DOMProcessingInstructionImpl::getPreviousSibling() const              {return fChild.getPreviousSibling (this); };
-           bool                DOMProcessingInstructionImpl::hasChildNodes() const                   {return fNode.hasChildNodes (); };
-           DOMNode          *DOMProcessingInstructionImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
-                                                                                                    {return fNode.insertBefore (newChild, refChild); };
-           void                DOMProcessingInstructionImpl::normalize()                             {fNode.normalize (); };
-           DOMNode          *DOMProcessingInstructionImpl::removeChild(DOMNode *oldChild)        {return fNode.removeChild (oldChild); };
-           DOMNode          *DOMProcessingInstructionImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
-                                                                                                    {return fNode.replaceChild (newChild, oldChild); };
-           bool                DOMProcessingInstructionImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
-                                                                                                    {return fNode.isSupported (feature, version); };
-           void                DOMProcessingInstructionImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); };
-           bool                DOMProcessingInstructionImpl::hasAttributes() const                   {return fNode.hasAttributes(); };
+           DOMNode*         DOMProcessingInstructionImpl::appendChild(DOMNode *newChild)          {return fNode.appendChild (newChild); };
+           DOMNamedNodeMap* DOMProcessingInstructionImpl::getAttributes() const                   {return fNode.getAttributes (); };
+           DOMNodeList*     DOMProcessingInstructionImpl::getChildNodes() const                   {return fNode.getChildNodes (); };
+           DOMNode*         DOMProcessingInstructionImpl::getFirstChild() const                   {return fNode.getFirstChild (); };
+           DOMNode*         DOMProcessingInstructionImpl::getLastChild() const                    {return fNode.getLastChild (); };
+     const XMLCh*           DOMProcessingInstructionImpl::getLocalName() const                    {return fNode.getLocalName (); };
+     const XMLCh*           DOMProcessingInstructionImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); };
+           DOMNode*         DOMProcessingInstructionImpl::getNextSibling() const                  {return fChild.getNextSibling (); };
+           DOMDocument*     DOMProcessingInstructionImpl::getOwnerDocument() const                {return fNode.getOwnerDocument (); };
+     const XMLCh*           DOMProcessingInstructionImpl::getPrefix() const                       {return fNode.getPrefix (); };
+           DOMNode*         DOMProcessingInstructionImpl::getParentNode() const                   {return fChild.getParentNode (this); };
+           DOMNode*         DOMProcessingInstructionImpl::getPreviousSibling() const              {return fChild.getPreviousSibling (this); };
+           bool             DOMProcessingInstructionImpl::hasChildNodes() const                   {return fNode.hasChildNodes (); };
+           DOMNode*         DOMProcessingInstructionImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
+                                                                                                  {return fNode.insertBefore (newChild, refChild); };
+           void             DOMProcessingInstructionImpl::normalize()                             {fNode.normalize (); };
+           DOMNode*         DOMProcessingInstructionImpl::removeChild(DOMNode *oldChild)          {return fNode.removeChild (oldChild); };
+           DOMNode*         DOMProcessingInstructionImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
+                                                                                                  {return fNode.replaceChild (newChild, oldChild); };
+           bool             DOMProcessingInstructionImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
+                                                                                                  {return fNode.isSupported (feature, version); };
+           void             DOMProcessingInstructionImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); };
+           bool             DOMProcessingInstructionImpl::hasAttributes() const                   {return fNode.hasAttributes(); };
+           void*            DOMProcessingInstructionImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler)
+                                                                                                  {return fNode.setUserData(key, data, handler); };
+           void*            DOMProcessingInstructionImpl::getUserData(const XMLCh* key) const     {return fNode.getUserData(key); };
diff --git a/src/xercesc/dom/impl/DOMTextImpl.cpp b/src/xercesc/dom/impl/DOMTextImpl.cpp
index efa3fad61..9b27292a1 100644
--- a/src/xercesc/dom/impl/DOMTextImpl.cpp
+++ b/src/xercesc/dom/impl/DOMTextImpl.cpp
@@ -94,7 +94,9 @@ DOMTextImpl::~DOMTextImpl()
 
 DOMNode *DOMTextImpl::cloneNode(bool deep) const
 {
-    return new (getOwnerDocument()) DOMTextImpl(*this, deep);
+    DOMNode* newNode = new (getOwnerDocument()) DOMTextImpl(*this, deep);
+    fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode);
+    return newNode;
 };
 
 
@@ -164,30 +166,33 @@ void DOMTextImpl::setIgnorableWhitespace(bool ignorable)
 //
 //  Delegation functions
 //
-           DOMNode          *DOMTextImpl::appendChild(DOMNode *newChild)        {return fNode.appendChild (newChild); };
-           DOMNamedNodeMap  *DOMTextImpl::getAttributes() const 			        {return fNode.getAttributes (); };
-           DOMNodeList      *DOMTextImpl::getChildNodes() const 			        {return fNode.getChildNodes (); };
-           DOMNode          *DOMTextImpl::getFirstChild() const 			        {return fNode.getFirstChild (); };
-           DOMNode          *DOMTextImpl::getLastChild() const 		            {return fNode.getLastChild (); };
-     const XMLCh              *DOMTextImpl::getLocalName() const                    {return fNode.getLocalName (); };
-     const XMLCh              *DOMTextImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); };
-           DOMNode          *DOMTextImpl::getNextSibling() const                  {return fChild.getNextSibling (); };
-     const XMLCh              *DOMTextImpl::getNodeValue() const                    {return fCharacterData.getNodeValue (); };
-           DOMDocument      *DOMTextImpl::getOwnerDocument() const                {return fNode.getOwnerDocument (); };
-     const XMLCh              *DOMTextImpl::getPrefix() const                       {return fNode.getPrefix (); };
-           DOMNode          *DOMTextImpl::getParentNode() const                   {return fChild.getParentNode (this); };
-           DOMNode          *DOMTextImpl::getPreviousSibling() const              {return fChild.getPreviousSibling (this); };
-           bool                DOMTextImpl::hasChildNodes() const                   {return fNode.hasChildNodes (); };
-           DOMNode          *DOMTextImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
-                                                                                    {return fNode.insertBefore (newChild, refChild); };
-           void                DOMTextImpl::normalize()                             {fNode.normalize (); };
-           DOMNode          *DOMTextImpl::removeChild(DOMNode *oldChild)        {return fNode.removeChild (oldChild); };
-           DOMNode          *DOMTextImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
-                                                                                    {return fNode.replaceChild (newChild, oldChild); };
-           bool                DOMTextImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
-                                                                                    {return fNode.isSupported (feature, version); };
-           void                DOMTextImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); };
-           bool                DOMTextImpl::hasAttributes() const                   {return fNode.hasAttributes(); };
+           DOMNode*         DOMTextImpl::appendChild(DOMNode *newChild)          {return fNode.appendChild (newChild); };
+           DOMNamedNodeMap* DOMTextImpl::getAttributes() const                   {return fNode.getAttributes (); };
+           DOMNodeList*     DOMTextImpl::getChildNodes() const                   {return fNode.getChildNodes (); };
+           DOMNode*         DOMTextImpl::getFirstChild() const                   {return fNode.getFirstChild (); };
+           DOMNode*         DOMTextImpl::getLastChild() const                    {return fNode.getLastChild (); };
+     const XMLCh*           DOMTextImpl::getLocalName() const                    {return fNode.getLocalName (); };
+     const XMLCh*           DOMTextImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); };
+           DOMNode*         DOMTextImpl::getNextSibling() const                  {return fChild.getNextSibling (); };
+     const XMLCh*           DOMTextImpl::getNodeValue() const                    {return fCharacterData.getNodeValue (); };
+           DOMDocument*     DOMTextImpl::getOwnerDocument() const                {return fNode.getOwnerDocument (); };
+     const XMLCh*           DOMTextImpl::getPrefix() const                       {return fNode.getPrefix (); };
+           DOMNode*         DOMTextImpl::getParentNode() const                   {return fChild.getParentNode (this); };
+           DOMNode*         DOMTextImpl::getPreviousSibling() const              {return fChild.getPreviousSibling (this); };
+           bool             DOMTextImpl::hasChildNodes() const                   {return fNode.hasChildNodes (); };
+           DOMNode*         DOMTextImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
+                                                                                 {return fNode.insertBefore (newChild, refChild); };
+           void             DOMTextImpl::normalize()                             {fNode.normalize (); };
+           DOMNode*         DOMTextImpl::removeChild(DOMNode *oldChild)          {return fNode.removeChild (oldChild); };
+           DOMNode*         DOMTextImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
+                                                                                 {return fNode.replaceChild (newChild, oldChild); };
+           bool             DOMTextImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
+                                                                                 {return fNode.isSupported (feature, version); };
+           void             DOMTextImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); };
+           bool             DOMTextImpl::hasAttributes() const                   {return fNode.hasAttributes(); };
+           void*            DOMTextImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler)
+                                                                                 {return fNode.setUserData(key, data, handler); };
+           void*            DOMTextImpl::getUserData(const XMLCh* key) const     {return fNode.getUserData(key); };
 
 
 //
@@ -195,17 +200,17 @@ void DOMTextImpl::setIgnorableWhitespace(bool ignorable)
 //
 
 
-     const XMLCh * DOMTextImpl::getData() const                  {return fCharacterData.getData();};
-     XMLSize_t  DOMTextImpl::getLength() const                {return fCharacterData.getLength();};
-     const XMLCh * DOMTextImpl::substringData(XMLSize_t offset, XMLSize_t count) const
-                                                                {return fCharacterData.substringData(this, offset, count);};
-     void          DOMTextImpl::appendData(const XMLCh *arg)     {fCharacterData.appendData(this, arg);};
-     void          DOMTextImpl::insertData(XMLSize_t offset, const  XMLCh *arg)
-                                                                {fCharacterData.insertData(this, offset, arg);};
-     void          DOMTextImpl::deleteData(XMLSize_t offset, XMLSize_t count)
-                                                                {fCharacterData.deleteData(this, offset, count);};
-     void          DOMTextImpl::replaceData(XMLSize_t offset, XMLSize_t count, const XMLCh *arg)
-                                                                {fCharacterData.replaceData(this, offset, count, arg);};
-     void          DOMTextImpl::setData(const XMLCh *data)       {fCharacterData.setData(this, data);};
-     void          DOMTextImpl::setNodeValue(const XMLCh  *nodeValue)   {fCharacterData.setNodeValue (this, nodeValue); };
+          const XMLCh*      DOMTextImpl::getData() const                         {return fCharacterData.getData();};
+          XMLSize_t         DOMTextImpl::getLength() const                       {return fCharacterData.getLength();};
+          const XMLCh*      DOMTextImpl::substringData(XMLSize_t offset, XMLSize_t count) const
+                                                                                 {return fCharacterData.substringData(this, offset, count);};
+          void              DOMTextImpl::appendData(const XMLCh *arg)            {fCharacterData.appendData(this, arg);};
+          void              DOMTextImpl::insertData(XMLSize_t offset, const  XMLCh *arg)
+                                                                                 {fCharacterData.insertData(this, offset, arg);};
+          void              DOMTextImpl::deleteData(XMLSize_t offset, XMLSize_t count)
+                                                                                 {fCharacterData.deleteData(this, offset, count);};
+          void              DOMTextImpl::replaceData(XMLSize_t offset, XMLSize_t count, const XMLCh *arg)
+                                                                                 {fCharacterData.replaceData(this, offset, count, arg);};
+          void              DOMTextImpl::setData(const XMLCh *data)              {fCharacterData.setData(this, data);};
+          void              DOMTextImpl::setNodeValue(const XMLCh  *nodeValue)   {fCharacterData.setNodeValue (this, nodeValue); };
 
diff --git a/src/xercesc/dom/impl/XSDElementNSImpl.cpp b/src/xercesc/dom/impl/XSDElementNSImpl.cpp
index 40942da88..21a95fd30 100644
--- a/src/xercesc/dom/impl/XSDElementNSImpl.cpp
+++ b/src/xercesc/dom/impl/XSDElementNSImpl.cpp
@@ -90,7 +90,9 @@ XSDElementNSImpl::XSDElementNSImpl(const XSDElementNSImpl &other, bool deep) :
 };
 
 DOMNode * XSDElementNSImpl::cloneNode(bool deep) const {
-    return new (getOwnerDocument()) XSDElementNSImpl(*this, deep);
+    DOMNode* newNode = new (getOwnerDocument()) XSDElementNSImpl(*this, deep);
+    fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode);
+    return newNode;
 }
 
 
-- 
GitLab