Apply patch from bugzilla: Bug 341179 - StackOverflow in AttributesReconcileAdapter while manually editing xml schema doc
diff --git a/plugins/org.eclipse.wst.sse.sieditor.model/api/org/eclipse/wst/sse/sieditor/model/reconcile/adapters/AttributesReconcileAdapter.java b/plugins/org.eclipse.wst.sse.sieditor.model/api/org/eclipse/wst/sse/sieditor/model/reconcile/adapters/AttributesReconcileAdapter.java
index ac2cd1b..635b75b 100644
--- a/plugins/org.eclipse.wst.sse.sieditor.model/api/org/eclipse/wst/sse/sieditor/model/reconcile/adapters/AttributesReconcileAdapter.java
+++ b/plugins/org.eclipse.wst.sse.sieditor.model/api/org/eclipse/wst/sse/sieditor/model/reconcile/adapters/AttributesReconcileAdapter.java
@@ -36,11 +36,12 @@
 import org.eclipse.xsd.util.XSDConstants;
 import org.w3c.dom.Attr;
 import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
 
 import org.eclipse.wst.sse.sieditor.model.reconcile.adapters.componentsource.IConcreteComponentSource;
 import org.eclipse.wst.sse.sieditor.model.utils.EmfXsdUtils;
 
-
 /**
  * Subclass of the {@link AbstractModelReconcileAdapter}. This adapter is
  * responsible for the fixing of problems caused by DOM element attributes
@@ -171,11 +172,23 @@
         final String prefix = getPrefix(attr);
         if (newValue == null) {
             /*
-             * the new value is null, so we need to remove the prefix/namespace
+             * The new value is null, so we need to remove the prefix/namespace
              * from the EMF model map. In some cases (on undo/redo) the EMF
-             * didn't do that
+             * didn't do that.
+             * 
+             * We also need to check the number of times this attribute is
+             * appearing in the schema element's body, because we don't want to
+             * update the map if more than one attribute with the same name
+             * exists. This is causing an unwanted DOM update of all the
+             * attribute values with the same name, instead of just the
+             * currently edited one.
+             * 
+             * Please note here that the currently edited attribute is already
+             * removed from DOM and that's why we check if the current count is
+             * zero
              */
-            if (xsdSchema.getQNamePrefixToNamespaceMap().containsKey(prefix)) {
+            if (countAttributeWithSameName(attr.getName(), xsdSchema.getElement()) == 0
+                    && xsdSchema.getQNamePrefixToNamespaceMap().containsKey(prefix)) {
                 xsdSchema.getQNamePrefixToNamespaceMap().remove(prefix);
             }
             /*
@@ -188,11 +201,14 @@
              * we have non-null value, so we must be updating existing
              * namespace, or adding a new one
              */
-            if (/*
-                 * XSDConstants.isSchemaForSchemaNamespace(attr.getValue()) &&
-                 */!attr.getValue().equals(xsdSchema.getQNamePrefixToNamespaceMap().get(prefix))) {
-                // add the namespace to the map
-                xsdSchema.getQNamePrefixToNamespaceMap().put(prefix, attr.getValue());
+            final String newNamespaceValue = attr.getValue();
+            final String oldNamespaceValue = xsdSchema.getQNamePrefixToNamespaceMap().get(prefix);
+
+            // we should not be updating the map when there are more than one
+            // attribute with same name in the element
+            if (countAttributeWithSameName(attr.getName(), xsdSchema.getElement()) <= 1
+                    && !newNamespaceAndOldNamespaceAreTheSame(newNamespaceValue, oldNamespaceValue)) {
+                xsdSchema.getQNamePrefixToNamespaceMap().put(prefix, newNamespaceValue);
             }
             /*
              * notify for the change anyway, since we want to run the
@@ -202,6 +218,37 @@
         }
     }
 
+    /**
+     * @return the number of times the given attribute name is appearing in the
+     *         element attributes collection.
+     */
+    private int countAttributeWithSameName(final String attributeName, final Element element) {
+        final NamedNodeMap attributes = element.getAttributes();
+        final int attributesSize = attributes.getLength();
+
+        int count = 0;
+        for (int i = 0; i < attributesSize; i++) {
+            final Node item = attributes.item(i);
+            if (attributeName.equals(item.getNodeName())) {
+                count++;
+            }
+        }
+        return count;
+    }
+
+    private boolean newNamespaceAndOldNamespaceAreTheSame(final String newNamespaceValue, final String oldNamespaceValue) {
+        if (newNamespaceValue == null && oldNamespaceValue == null) {
+            return true;
+        }
+        if (oldNamespaceValue == null && newNamespaceValue.isEmpty()) {
+            // generally, "null" namespace and empty one will be treated the
+            // same
+            return true;
+        }
+        // XSDConstants.isSchemaForSchemaNamespace(attr.getValue()) &&
+        return newNamespaceValue.equals(oldNamespaceValue);
+    }
+
     private void processParameterOrderAttribute(final INodeNotifier notifier, final String attributeName) {
         if (WSDLConstants.PARAMETER_ORDER_ATTRIBUTE.equals(attributeName)) {
             /* we need to check if we are updating a part name */
@@ -300,7 +347,7 @@
                 final EObject eObject = concreteComponentSource.getConcreteComponentFor((Element) notifier);
                 ((XSDFeature)eObject).setLexicalValue((String)newValue);
                 eObject.eNotify(new ENotificationImpl((InternalEObject) eObject, Notification.SET, XSDPackage.XSD_FEATURE__VALUE, null,
-                	     newValue));
+                             newValue));
             }
         }
     }