diff --git a/src/dom/DOM_NamedNodeMap.cpp b/src/dom/DOM_NamedNodeMap.cpp
index 9a7ad9a0fc3b76373034c23b357ed290785c3787..f3c0b478c69522c684eec7d786dfa7ef5f9628ab 100644
--- a/src/dom/DOM_NamedNodeMap.cpp
+++ b/src/dom/DOM_NamedNodeMap.cpp
@@ -56,6 +56,10 @@
 
 /*
  * $Log$
+ * Revision 1.8  2000/06/07 22:49:40  andyh
+ * Memory usage reduction:  DOM NamedNodeMaps for attributes are allocated
+ * only for elements that actually have attributes.  By Joe Polastre.
+ *
  * Revision 1.7  2000/03/11 03:19:12  chchou
  * Fix bug # 19, add const keyword to API
  *
@@ -87,32 +91,49 @@
 #include "DOM_Node.hpp"
 #include "DOM_NamedNodeMap.hpp"
 #include "NamedNodeMapImpl.hpp"
+#include "ElementImpl.hpp"
+
+
+const unsigned short DOM_NamedNodeMap::NNM_ELEMENT  = 0;
+const unsigned short DOM_NamedNodeMap::NNM_OTHER    = 1;
 
 
 DOM_NamedNodeMap::DOM_NamedNodeMap()
 {
-    fImpl = null;
+    fImpl = 0;
+	flagElem = NNM_OTHER;
 };
 
 
 DOM_NamedNodeMap::DOM_NamedNodeMap(const DOM_NamedNodeMap & other)
 {
     this->fImpl = other.fImpl;
-    NamedNodeMapImpl::addRef(fImpl);
+	this->flagElem = other.flagElem;
+	(other.flagElem == NNM_ELEMENT) ? NodeImpl::addRef((NodeImpl *)fImpl) :	
+	                                  NamedNodeMapImpl::addRef((NamedNodeMapImpl *)fImpl);
 };
 
 
 DOM_NamedNodeMap::DOM_NamedNodeMap(NamedNodeMapImpl *impl)
 {
-    fImpl = impl;
-    NamedNodeMapImpl::addRef(fImpl);
+	fImpl = impl;
+	flagElem = NNM_OTHER;
+	if (impl != null)
+		NamedNodeMapImpl::addRef((NamedNodeMapImpl *)fImpl);
 };
 
+DOM_NamedNodeMap::DOM_NamedNodeMap(NodeImpl *impl)
+{
+	fImpl = impl;
+	flagElem = NNM_ELEMENT;
+	NodeImpl::addRef((NodeImpl *)fImpl);
+}
 
 
 DOM_NamedNodeMap::~DOM_NamedNodeMap() 
 {
-    NamedNodeMapImpl::removeRef(fImpl);
+	(flagElem == NNM_OTHER) ? NamedNodeMapImpl::removeRef((NamedNodeMapImpl *)fImpl) : 
+	                          NodeImpl::removeRef((NodeImpl *)fImpl);
 };
 
 bool DOM_NamedNodeMap::operator == (const DOM_NamedNodeMap &other) const
@@ -143,9 +164,13 @@ DOM_NamedNodeMap & DOM_NamedNodeMap::operator = (const DOM_NamedNodeMap & other)
 {
     if (this->fImpl != other.fImpl) 
     {
-        NamedNodeMapImpl::removeRef(fImpl);
+		// update reference counts and change pointers
+        (flagElem == NNM_OTHER) ? NamedNodeMapImpl::removeRef((NamedNodeMapImpl *)fImpl) : NodeImpl::removeRef((NodeImpl *)fImpl);
+
         this->fImpl = other.fImpl;
-        NamedNodeMapImpl::addRef(fImpl);
+		this->flagElem = other.flagElem;
+
+        (flagElem == NNM_OTHER) ? NamedNodeMapImpl::addRef((NamedNodeMapImpl *)fImpl) : NodeImpl::addRef((NodeImpl *)fImpl);
     }
     return *this;
 };
@@ -153,39 +178,46 @@ DOM_NamedNodeMap & DOM_NamedNodeMap::operator = (const DOM_NamedNodeMap & other)
 
 DOM_NamedNodeMap & DOM_NamedNodeMap::operator = (const DOM_NullPtr *other)
 {
-    NamedNodeMapImpl::removeRef(fImpl);
+    
+    (flagElem == NNM_OTHER) ? NamedNodeMapImpl::removeRef((NamedNodeMapImpl *)fImpl) : NodeImpl::removeRef((NodeImpl *)fImpl);
     this->fImpl = 0;
+	this->flagElem = NNM_OTHER;
     return *this;
 };
 
 
 DOM_Node DOM_NamedNodeMap::getNamedItem(const DOMString &name) const
 {
-    return DOM_Node(fImpl->getNamedItem(name));
+	return (flagElem == NNM_OTHER) ? DOM_Node(((NamedNodeMapImpl *)fImpl)->getNamedItem(name)) : 
+	                                 DOM_Node(((ElementImpl *)fImpl)->NNM_getNamedItem(name));
 };
 
 
 DOM_Node DOM_NamedNodeMap::setNamedItem(DOM_Node arg)
 {
-    return DOM_Node(fImpl->setNamedItem(arg.fImpl));
+	return (flagElem == NNM_OTHER) ? DOM_Node(((NamedNodeMapImpl *)fImpl)->setNamedItem(arg.fImpl)) : 
+	                                 DOM_Node(((ElementImpl *)fImpl)->NNM_setNamedItem(arg.fImpl));
 };
 
 
 DOM_Node DOM_NamedNodeMap::removeNamedItem(const DOMString &name)
 {
-    return DOM_Node(fImpl->removeNamedItem(name));
+	return (flagElem == NNM_OTHER) ? DOM_Node(((NamedNodeMapImpl *)fImpl)->removeNamedItem(name)) : 
+	                                 DOM_Node(((ElementImpl *)fImpl)->NNM_removeNamedItem(name));
 };
 
 
 DOM_Node DOM_NamedNodeMap::item(unsigned int index) const
 {
-    return DOM_Node(fImpl->item(index));
+	return (flagElem == NNM_OTHER) ? DOM_Node(((NamedNodeMapImpl *)fImpl)->item(index)) : 
+	                                 DOM_Node(((ElementImpl *)fImpl)->NNM_item(index));
 };
 
 
 unsigned int DOM_NamedNodeMap::getLength() const
 {
-    return fImpl->getLength();
+	return (flagElem == NNM_OTHER) ? ((NamedNodeMapImpl *)fImpl)->getLength() : 
+	                                 ((ElementImpl *)fImpl)->NNM_getLength();
 };
 
 
@@ -194,16 +226,19 @@ unsigned int DOM_NamedNodeMap::getLength() const
 DOM_Node DOM_NamedNodeMap::getNamedItemNS(const DOMString &namespaceURI,
 	const DOMString &localName)
 {
-    return DOM_Node(fImpl->getNamedItemNS(namespaceURI, localName));
+	return (flagElem == NNM_OTHER) ? DOM_Node(((NamedNodeMapImpl *)fImpl)->getNamedItemNS(namespaceURI, localName)) :
+									 DOM_Node(((ElementImpl *)fImpl)->NNM_getNamedItemNS(namespaceURI, localName));
 }
 
 DOM_Node DOM_NamedNodeMap::setNamedItemNS(DOM_Node arg)
 {
-    return DOM_Node(fImpl->setNamedItemNS(arg.fImpl));
+    return (flagElem == NNM_OTHER) ? DOM_Node(((NamedNodeMapImpl *)fImpl)->setNamedItemNS(arg.fImpl)) :
+	                                 DOM_Node(((ElementImpl *)fImpl)->NNM_setNamedItemNS(arg.fImpl));
 }
 
 DOM_Node DOM_NamedNodeMap::removeNamedItemNS(const DOMString &namespaceURI,
 	const DOMString &localName)
 {
-    return DOM_Node(fImpl->removeNamedItemNS(namespaceURI, localName));
+	return (flagElem == NNM_OTHER) ? DOM_Node(((NamedNodeMapImpl *)fImpl)->removeNamedItemNS(namespaceURI, localName)) :
+                                     DOM_Node(((ElementImpl *)fImpl)->NNM_removeNamedItemNS(namespaceURI, localName));
 }
diff --git a/src/dom/DOM_NamedNodeMap.hpp b/src/dom/DOM_NamedNodeMap.hpp
index 9c8ae74f0d2acb53b8c089e6b7adf0915422ad2e..9752ec4961e453f1cd9daa5db3c64026e3c31f57 100644
--- a/src/dom/DOM_NamedNodeMap.hpp
+++ b/src/dom/DOM_NamedNodeMap.hpp
@@ -56,6 +56,10 @@
 
 /*
  * $Log$
+ * Revision 1.13  2000/06/07 22:49:40  andyh
+ * Memory usage reduction:  DOM NamedNodeMaps for attributes are allocated
+ * only for elements that actually have attributes.  By Joe Polastre.
+ *
  * Revision 1.12  2000/03/11 03:19:13  chchou
  * Fix bug # 19, add const keyword to API
  *
@@ -124,7 +128,11 @@ class NamedNodeMapImpl;
 */
 class CDOM_EXPORT DOM_NamedNodeMap {
 private:
-    NamedNodeMapImpl        *fImpl;
+    void     *fImpl;
+	short    flagElem;
+
+	static const unsigned short NNM_ELEMENT;
+	static const unsigned short NNM_OTHER;	
     
 public:
     /** @name Constructors and assignment operator */
@@ -384,6 +392,7 @@ public:
  protected:
 
     DOM_NamedNodeMap(NamedNodeMapImpl *impl);
+	DOM_NamedNodeMap(NodeImpl *impl);
 
     friend class DOM_DocumentType;
     friend class DOM_Node;
diff --git a/src/dom/DOM_Node.cpp b/src/dom/DOM_Node.cpp
index a17e6b698dbdbe91d1d3cfce3e0c0f504df3f7a9..95eab62438f475cd0ee177566ae3dc68f7f8f4e7 100644
--- a/src/dom/DOM_Node.cpp
+++ b/src/dom/DOM_Node.cpp
@@ -56,6 +56,10 @@
 
 /*
  * $Log$
+ * Revision 1.6  2000/06/07 22:49:40  andyh
+ * Memory usage reduction:  DOM NamedNodeMaps for attributes are allocated
+ * only for elements that actually have attributes.  By Joe Polastre.
+ *
  * Revision 1.5  2000/03/02 19:53:56  roddey
  * This checkin includes many changes done while waiting for the
  * 1.1.0 code to be finished. I can't list them all here, but a list is
@@ -239,7 +243,7 @@ void          *DOM_Node::getUserData() const
   
 DOM_NamedNodeMap DOM_Node::getAttributes() const
 {
-    return DOM_NamedNodeMap(fImpl->getAttributes());
+    return (fImpl->getAttributes() == null) ? DOM_NamedNodeMap(fImpl) : DOM_NamedNodeMap(fImpl->getAttributes());
 };
 
   
diff --git a/src/dom/ElementImpl.cpp b/src/dom/ElementImpl.cpp
index a125c2e80a0c5ba7ab2312fc1c61335c8cac6c6c..de3ff2eb1651fa1fa9ab63b4ddd019f235e0296e 100644
--- a/src/dom/ElementImpl.cpp
+++ b/src/dom/ElementImpl.cpp
@@ -73,7 +73,7 @@ ElementImpl::ElementImpl(DocumentImpl *ownerDoc, const DOMString &eName)
     : ChildAndParentNode(ownerDoc)
 {
     name = eName.clone();
-    attributes = new NamedNodeMapImpl(this);
+    attributes = null;
 };
 
 
@@ -81,9 +81,11 @@ ElementImpl::ElementImpl(const ElementImpl &other, bool deep)
     : ChildAndParentNode(other)
 {
     name = other.name.clone();
+	attributes = null;
     if (deep)
         cloneChildren(other);
-    attributes = other.attributes->cloneMap(this);
+	if (other.attributes != null)
+		attributes = other.attributes->cloneMap(this);
 };
 
 
@@ -109,7 +111,8 @@ NodeImpl *ElementImpl::cloneNode(bool deep)
  */
 void ElementImpl::setOwnerDocument(DocumentImpl *doc) {
     ChildAndParentNode::setOwnerDocument(doc);
-    attributes->setOwnerDocument(doc);
+	if (attributes != null)
+		attributes->setOwnerDocument(doc);
 }
 
 
@@ -134,7 +137,7 @@ DOMString ElementImpl::getAttribute(const DOMString &nam)
 
 AttrImpl *ElementImpl::getAttributeNode(const DOMString &nam)
 {
-    return (AttrImpl *)(attributes->getNamedItem(nam));
+    return (attributes == null) ? null : (AttrImpl *)(attributes->getNamedItem(nam));
 };
 
 
@@ -212,6 +215,8 @@ AttrImpl *ElementImpl::setAttribute(const DOMString &nam, const DOMString &val)
     AttrImpl* newAttr = (AttrImpl*)getAttributeNode(nam);
     if (!newAttr)
     {
+		if (attributes == null)
+			attributes = new NamedNodeMapImpl(this);
         newAttr = (AttrImpl*)ownerDocument->createAttribute(nam);
         attributes->setNamedItem(newAttr);
     }
@@ -232,6 +237,8 @@ AttrImpl * ElementImpl::setAttributeNode(AttrImpl *newAttr)
     
     if (!(newAttr->isAttrImpl()))
         throw DOM_DOMException(DOM_DOMException::WRONG_DOCUMENT_ERR, null);
+	if (attributes == null)
+		attributes = new NamedNodeMapImpl(this);
     AttrImpl *oldAttr =
       (AttrImpl *) attributes->getNamedItem(newAttr->getName());
     // This will throw INUSE if necessary
@@ -285,6 +292,8 @@ AttrImpl *ElementImpl::setAttributeNS(const DOMString &fNamespaceURI,
       (AttrImpl *) ownerDocument->createAttributeNS(fNamespaceURI,
                                                     qualifiedName);
     newAttr->setNodeValue(fValue);
+	if (attributes == null)
+		attributes = new NamedNodeMapImpl(this);
     AttrImpl *oldAttr = (AttrImpl *)attributes->setNamedItem(newAttr);
 
     if (oldAttr) {
@@ -328,8 +337,9 @@ AttrImpl *ElementImpl::setAttributeNodeNS(AttrImpl *newAttr)
     
     if (newAttr -> getOwnerDocument() != this -> getOwnerDocument())
         throw DOM_DOMException(DOM_DOMException::WRONG_DOCUMENT_ERR, null);
-    AttrImpl *oldAttr = (AttrImpl *) attributes->getNamedItemNS(
-	newAttr->getNamespaceURI(), newAttr->getLocalName());
+	if (attributes == null)
+		attributes = new NamedNodeMapImpl(this);
+    AttrImpl *oldAttr = (AttrImpl *) attributes->getNamedItemNS(newAttr->getNamespaceURI(), newAttr->getLocalName());
     
     // This will throw INUSE if necessary
     attributes->setNamedItemNS(newAttr);
@@ -353,3 +363,88 @@ DeepNodeListImpl *ElementImpl::getElementsByTagNameNS(const DOMString &fNamespac
     return new DeepNodeListImpl(this,fNamespaceURI, fLocalName);
 }
 
+// DOM_NamedNodeMap UTILITIES
+NamedNodeMapImpl *ElementImpl::NNM_cloneMap(NodeImpl *ownerNode) 
+{
+	return (getAttributes() == null) ? null : ownerNode->getAttributes()->cloneMap(ownerNode);
+}
+
+int ElementImpl::NNM_findNamePoint(const DOMString &name)
+{
+	return (getAttributes() == null) ? -1 : getAttributes()->findNamePoint(name);
+}
+
+unsigned int ElementImpl::NNM_getLength()
+{
+	return (getAttributes() == null) ? 0 : getAttributes()->getLength();
+}
+
+NodeImpl *ElementImpl::NNM_getNamedItem(const DOMString &name)
+{
+	return (getAttributes() == null) ? null : getAttributes()->getNamedItem(name);
+}
+
+NodeImpl *ElementImpl::NNM_item(unsigned int index)
+{
+	return (getAttributes() == null) ? null : getAttributes()->item(index);
+}
+
+void ElementImpl::NNM_removeAll() 
+{
+	if (getAttributes() != null)
+		getAttributes()->removeAll();
+}
+
+NodeImpl *ElementImpl::NNM_removeNamedItem(const DOMString &name)
+{
+	if (getAttributes() == null)
+		throw DOM_DOMException(DOM_DOMException::NOT_FOUND_ERR, null);
+	else
+		return getAttributes()->removeNamedItem(name);
+	return null;
+}
+
+NodeImpl *ElementImpl::NNM_setNamedItem(NodeImpl *arg)
+{
+	if (getAttributes() == null)
+		attributes = new NamedNodeMapImpl(this);
+	return attributes->setNamedItem(arg);
+}
+
+void ElementImpl::NNM_setReadOnly(bool readOnly, bool deep)
+{
+	if (getAttributes() != null)
+		getAttributes()->setReadOnly(readOnly, deep);
+}
+
+int ElementImpl::NNM_findNamePoint(const DOMString &namespaceURI, const DOMString &localName)
+{
+	return (getAttributes() == null) ? -1 : getAttributes()->findNamePoint(namespaceURI, localName);
+}
+
+NodeImpl *ElementImpl::NNM_getNamedItemNS(const DOMString &namespaceURI, const DOMString &localName)
+{
+	return (getAttributes() == null) ? null : getAttributes()->getNamedItemNS(namespaceURI, localName);
+}
+
+NodeImpl *ElementImpl::NNM_setNamedItemNS(NodeImpl *arg)
+{
+	if (getAttributes() == null)
+		attributes = new NamedNodeMapImpl(this);
+	return getAttributes()->setNamedItemNS(arg);
+}
+
+NodeImpl *ElementImpl::NNM_removeNamedItemNS(const DOMString &namespaceURI, const DOMString &localName)
+{
+	if (getAttributes() == null)
+        throw DOM_DOMException(DOM_DOMException::NOT_FOUND_ERR, null);
+	else
+		return getAttributes()->removeNamedItemNS(namespaceURI, localName);
+	return null;
+}
+
+void ElementImpl::NNM_setOwnerDocument(DocumentImpl *doc)
+{
+	if (getAttributes() != null)
+		getAttributes()->setOwnerDocument(doc);
+}
diff --git a/src/dom/ElementImpl.hpp b/src/dom/ElementImpl.hpp
index b4d340468c968ec49770778d01f85fe5dccead48..38879c90bfc7eb6a40faf126f154fa22135a629a 100644
--- a/src/dom/ElementImpl.hpp
+++ b/src/dom/ElementImpl.hpp
@@ -117,6 +117,28 @@ public:
 	const DOMString &localName);
 
     virtual void setOwnerDocument(DocumentImpl *doc);
+
+	//Utils for the DOM_NamedNodeMap wrapper class
+	//All NamedNodeMap utils begin with NNM
+    virtual NamedNodeMapImpl *NNM_cloneMap(NodeImpl *ownerNode);
+//    static  void            NNM_addRef(NamedNodeMapImpl *);
+    virtual int             NNM_findNamePoint(const DOMString &name);
+    virtual unsigned int    NNM_getLength();
+    virtual NodeImpl       *NNM_getNamedItem(const DOMString &name);
+    virtual NodeImpl       *NNM_item(unsigned int index);
+    virtual void            NNM_removeAll();
+    virtual NodeImpl       *NNM_removeNamedItem(const DOMString &name);
+//    static  void            NNM_removeRef(NamedNodeMapImpl *);
+    virtual NodeImpl       *NNM_setNamedItem(NodeImpl *arg);
+    virtual void            NNM_setReadOnly(bool readOnly, bool deep);
+    //Introduced in DOM Level 2
+    virtual int             NNM_findNamePoint(const DOMString &namespaceURI, const DOMString &localName);
+    virtual NodeImpl       *NNM_getNamedItemNS(const DOMString &namespaceURI, const DOMString &localName);
+    virtual NodeImpl       *NNM_setNamedItemNS(NodeImpl *arg);
+    virtual NodeImpl       *NNM_removeNamedItemNS(const DOMString &namespaceURI, const DOMString &localName);
+    virtual void            NNM_setOwnerDocument(DocumentImpl *doc);
+
+
 };
 
 #endif