patch from Lars Heete:
Correct the generation of DOMAttrModified and DOMCharacterDataModified
mutation events.
   - DOMAttrModified and DOMCharacterDataModified events get dispatched to
     the parent chain.
   - removing an attribute now generates a DOMAttrModified event with
      newval=null
   - adding an attribute now generates only one DOMAttrModified event
      with oldval=null


git-svn-id: https://svn.apache.org/repos/asf/xerces/java/trunk@316096 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/org/apache/xerces/dom/AttributeMap.java b/src/org/apache/xerces/dom/AttributeMap.java
index c7e1835..bcdad25 100644
--- a/src/org/apache/xerces/dom/AttributeMap.java
+++ b/src/org/apache/xerces/dom/AttributeMap.java
@@ -274,6 +274,21 @@
             }
         }
 
+        LCount lc=null;
+        String oldvalue="";
+        AttrImpl enclosingAttribute=null;
+        if (NodeImpl.MUTATIONEVENTS
+            && ownerNode.ownerDocument().mutationEvents)
+        {
+            // MUTATION PREPROCESSING AND PRE-EVENTS:
+            lc=LCount.lookup(MutationEventImpl.DOM_ATTR_MODIFIED);
+            if(lc.captures+lc.bubbles+lc.defaults>0)
+            {
+               enclosingAttribute=(AttrImpl)(nodes.elementAt(i));
+               oldvalue=enclosingAttribute.getNodeValue();
+            }
+        } // End mutation preprocessing
+
         NodeImpl n = (NodeImpl)nodes.elementAt(i);
         // If there's a default, add it instead
         if (hasDefaults()) {
@@ -302,6 +317,30 @@
         n.isOwned(false);
         // make sure it won't be mistaken with defaults in case it's reused
         n.isSpecified(true);
+
+        // We can't use the standard dispatchAggregate, since it assumes
+        // that the Attr is still attached to an owner. This code is
+        // similar but dispatches to the previous owner, "element".
+        if(NodeImpl.MUTATIONEVENTS && ownerNode.ownerDocument().mutationEvents)
+        {
+    	    // If we have to send DOMAttrModified (determined earlier),
+            // do so.
+            if(lc.captures+lc.bubbles+lc.defaults>0) {
+                MutationEvent me= new MutationEventImpl();
+                //?????ownerDocument.createEvent("MutationEvents");
+                me.initMutationEvent(MutationEventImpl.DOM_ATTR_MODIFIED,
+                                     true, false,
+                                     null, n.getNodeValue(),
+				     null, name);
+                ownerNode.dispatchEvent(me);
+            }
+
+            // We can hand off to process DOMSubtreeModified, though.
+            // Note that only the Element needs to be informed; the
+            // Attr's subtree has not been changed by this operation.
+            ownerNode.dispatchAggregateEvents(null,null);
+        }
+
         return n;
 
     } // removeNamedItem(String):Node
@@ -422,7 +461,7 @@
                 me.initMutationEvent(MutationEventImpl.DOM_ATTR_MODIFIED,
                                      true, false,
                                      null, n.getNodeValue(),
-                             ((ElementImpl)ownerNode).getAttribute(name),name);
+				     null, name);
                 ownerNode.dispatchEvent(me);
             }
 
diff --git a/src/org/apache/xerces/dom/ElementImpl.java b/src/org/apache/xerces/dom/ElementImpl.java
index 6e3eaf9..4a11213 100644
--- a/src/org/apache/xerces/dom/ElementImpl.java
+++ b/src/org/apache/xerces/dom/ElementImpl.java
@@ -427,9 +427,13 @@
             if (attributes == null) {
                 attributes = new AttributeMap(this, null);
             }
+
+	    newAttr.setNodeValue(value);
             attributes.setNamedItem(newAttr);
         }
-    	newAttr.setNodeValue(value);
+	else {
+	    newAttr.setNodeValue(value);
+	}
 
     } // setAttribute(String,String)
  
@@ -567,9 +571,12 @@
             if (attributes == null) {
                 attributes = new AttributeMap(this, null);
             }
+	    newAttr.setNodeValue(value);
             attributes.setNamedItemNS(newAttr);
     	}
-    	newAttr.setNodeValue(value);
+	else {
+	    newAttr.setNodeValue(value);
+	}
 
     } // setAttributeNS(String,String,String)
     
diff --git a/src/org/apache/xerces/dom/NodeImpl.java b/src/org/apache/xerces/dom/NodeImpl.java
index 0307bb0..539c7b7 100644
--- a/src/org/apache/xerces/dom/NodeImpl.java
+++ b/src/org/apache/xerces/dom/NodeImpl.java
@@ -1141,12 +1141,7 @@
 	{
       if(MUTATIONEVENTS && ownerDocument().mutationEvents)
       {
-          Vector nodeListeners = ownerDocument().getEventListeners(this);
-	    if(nodeListeners==null)
-            return;
-
-	    // If we have to send DOMAttrModified (determined earlier),
-	    // do so.
+	    // We have to send DOMAttrModified.
 	    NodeImpl owner=null;
 	    if(enclosingAttr!=null)
 	    {