diff --git a/doc/releases.xml b/doc/releases.xml index 192ccb88c59e8e6fb0dc9b4d4b99aea20eb5e4cd..09221812396d575bb2206579b1c97abf51af3845 100644 --- a/doc/releases.xml +++ b/doc/releases.xml @@ -25,6 +25,13 @@ <td>Description</td> </tr> + <tr> + <td>2002-07-19</td> + <td>Tinny Ng</td> + <td>[Bug 10968] Default attributes from Schema not restored by removeAttribute. + </td> + </tr> + <tr> <td>2002-07-18</td> <td>Khaled Noaman</td> diff --git a/src/xercesc/dom/impl/DOMElementImpl.cpp b/src/xercesc/dom/impl/DOMElementImpl.cpp index 8aa96b4d99a6e6c505bb7c16d535a33b823c3255..cb19f8c8f41d5e4df5848d5675c2ee85cba7c232 100644 --- a/src/xercesc/dom/impl/DOMElementImpl.cpp +++ b/src/xercesc/dom/impl/DOMElementImpl.cpp @@ -80,20 +80,26 @@ class DOMAttr; DOMElementImpl::DOMElementImpl(DOMDocument *ownerDoc, const XMLCh *eName) - : fNode(ownerDoc), fParent(ownerDoc), fAttributes(0) + : fNode(ownerDoc), fParent(ownerDoc), fAttributes(0), fDefaultAttributes(0) { DOMDocumentImpl *docImpl = (DOMDocumentImpl *)ownerDoc; fName = docImpl->fNamePool->getPooledString(eName); setupDefaultAttributes(); - if (!fAttributes) + if (!fDefaultAttributes) { + fDefaultAttributes = new (getOwnerDocument()) DOMAttrMapImpl(this); fAttributes = new (getOwnerDocument()) DOMAttrMapImpl(this); + } + else { + fAttributes = new (getOwnerDocument()) DOMAttrMapImpl(this, fDefaultAttributes); + } }; DOMElementImpl::DOMElementImpl(const DOMElementImpl &other, bool deep) : fNode(other.getOwnerDocument()), fParent(other.getOwnerDocument()), - fAttributes(0) + fAttributes(0), + fDefaultAttributes(0) { fName = other.fName; if (deep) @@ -104,10 +110,24 @@ DOMElementImpl::DOMElementImpl(const DOMElementImpl &other, bool deep) fAttributes = ((DOMAttrMapImpl *)other.getAttributes())->cloneAttrMap(this); } - if (!fAttributes) { + if (other.getDefaultAttributes()) + { + fDefaultAttributes = ((DOMAttrMapImpl *)other.getDefaultAttributes())->cloneAttrMap(this); + } + + if (!fDefaultAttributes) setupDefaultAttributes(); - if (!fAttributes) + + if (!fDefaultAttributes) + fDefaultAttributes = new (getOwnerDocument()) DOMAttrMapImpl(this); + + if (!fAttributes) { + if (!fDefaultAttributes) { fAttributes = new (getOwnerDocument()) DOMAttrMapImpl(this); + } + else { + fAttributes = new (getOwnerDocument()) DOMAttrMapImpl(this, fDefaultAttributes); + } } }; @@ -375,29 +395,57 @@ bool DOMElementImpl::hasAttributeNS(const XMLCh *namespaceURI, // util functions for default attributes // returns the default attribute map for this node from the owner document -DOMAttrMapImpl *DOMElementImpl::getDefaultAttributes() +DOMAttrMapImpl *DOMElementImpl::getDefaultAttributes() const { - if ((fNode.fOwnerNode == 0) || (getOwnerDocument() == 0)) - return 0; + return fDefaultAttributes; +} +// initially set up the default attribute information based on doctype information +void DOMElementImpl::setupDefaultAttributes() +{ DOMDocument *tmpdoc = getOwnerDocument(); - if (tmpdoc->getDoctype() == 0) - return 0; + if ((fNode.fOwnerNode == 0) || (tmpdoc == 0) || (tmpdoc->getDoctype() == 0)) + return; DOMNode *eldef = ((DOMDocumentTypeImpl*)tmpdoc->getDoctype())->getElements()->getNamedItem(getNodeName()); - return (eldef == 0) ? 0 : (DOMAttrMapImpl *)(eldef->getAttributes()); + DOMAttrMapImpl* defAttrs = (eldef == 0) ? 0 : (DOMAttrMapImpl *)(eldef->getAttributes()); + + if (defAttrs) + fDefaultAttributes = new (getOwnerDocument()) DOMAttrMapImpl(this, defAttrs); } -// resets all attributes for this node to their default values -void DOMElementImpl::setupDefaultAttributes() +DOMAttr * DOMElementImpl::setDefaultAttributeNode(DOMAttr *newAttr) { - if ((fNode.fOwnerNode == 0) || (getOwnerDocument() == 0) || (getOwnerDocument()->getDoctype() == 0)) - return; + if (fNode.isReadOnly()) + throw DOMException( + DOMException::NO_MODIFICATION_ALLOWED_ERR, 0); - DOMAttrMapImpl* defAttrs = getDefaultAttributes(); + if (newAttr->getNodeType() != DOMNode::ATTRIBUTE_NODE) + throw DOMException(DOMException::WRONG_DOCUMENT_ERR, 0); + // revisit. Exception doesn't match test. - if (defAttrs) - fAttributes = new (getOwnerDocument()) DOMAttrMapImpl(this, defAttrs); + // This will throw INUSE if necessary + DOMAttr *oldAttr = (DOMAttr *) fDefaultAttributes->setNamedItem(newAttr); + fAttributes->hasDefaults(true); + + return oldAttr; +}; + + +DOMAttr *DOMElementImpl::setDefaultAttributeNodeNS(DOMAttr *newAttr) +{ + if (fNode.isReadOnly()) + throw DOMException( + DOMException::NO_MODIFICATION_ALLOWED_ERR, 0); + + if (newAttr -> getOwnerDocument() != this -> getOwnerDocument()) + throw DOMException(DOMException::WRONG_DOCUMENT_ERR, 0); + + // This will throw INUSE if necessary + DOMAttr *oldAttr = (DOMAttr *) fDefaultAttributes->setNamedItemNS(newAttr); + fAttributes->hasDefaults(true); + + return oldAttr; } void DOMElementImpl::release() diff --git a/src/xercesc/dom/impl/DOMElementImpl.hpp b/src/xercesc/dom/impl/DOMElementImpl.hpp index a427bb2b191fe9ea3685b2e633de7af953d8be9e..0545840c06f46212a020a26991b6346649f1530b 100644 --- a/src/xercesc/dom/impl/DOMElementImpl.hpp +++ b/src/xercesc/dom/impl/DOMElementImpl.hpp @@ -95,6 +95,7 @@ public: DOMParentNode fParent; DOMChildNode fChild; DOMAttrMapImpl *fAttributes; + DOMAttrMapImpl *fDefaultAttributes; const XMLCh *fName; public: @@ -107,39 +108,45 @@ public: DOMNODE_FUNCTIONS; // Functions introduced on Element... - virtual const XMLCh * getAttribute(const XMLCh *name) const; - virtual DOMAttr * getAttributeNode(const XMLCh *name) const; - virtual DOMNodeList * getElementsByTagName(const XMLCh *tagname) const; - virtual const XMLCh * getTagName() const; + virtual const XMLCh* getAttribute(const XMLCh *name) const; + virtual DOMAttr* getAttributeNode(const XMLCh *name) const; + virtual DOMNodeList* getElementsByTagName(const XMLCh *tagname) const; + virtual const XMLCh* getTagName() const; virtual void removeAttribute(const XMLCh *name); - virtual DOMAttr * removeAttributeNode(DOMAttr * oldAttr); + virtual DOMAttr* removeAttributeNode(DOMAttr * oldAttr); virtual void setAttribute(const XMLCh *name, const XMLCh *value); - virtual DOMAttr * setAttributeNode(DOMAttr *newAttr); + virtual DOMAttr* setAttributeNode(DOMAttr *newAttr); virtual void setReadOnly(bool readOnly, bool deep); //Introduced in DOM Level 2 - virtual const XMLCh * getAttributeNS(const XMLCh *namespaceURI, - const XMLCh *localName) const; + virtual const XMLCh* getAttributeNS(const XMLCh *namespaceURI, + const XMLCh *localName) const; virtual void setAttributeNS(const XMLCh *namespaceURI, - const XMLCh *qualifiedName, - const XMLCh *value); + const XMLCh *qualifiedName, + const XMLCh *value); virtual void removeAttributeNS(const XMLCh *namespaceURI, - const XMLCh *localName); - virtual DOMAttr *getAttributeNodeNS(const XMLCh *namespaceURI, - const XMLCh *localName) const; - virtual DOMAttr *setAttributeNodeNS(DOMAttr *newAttr); - virtual DOMNodeList *getElementsByTagNameNS(const XMLCh *namespaceURI, - const XMLCh *localName) const; + const XMLCh *localName); + virtual DOMAttr* getAttributeNodeNS(const XMLCh *namespaceURI, + const XMLCh *localName) const; + virtual DOMAttr* setAttributeNodeNS(DOMAttr *newAttr); + virtual DOMNodeList* getElementsByTagNameNS(const XMLCh *namespaceURI, + const XMLCh *localName) const; virtual bool hasAttribute(const XMLCh *name) const; virtual bool hasAttributeNS(const XMLCh *namespaceURI, const XMLCh *localName) const; - // default attribute helper functions - virtual DOMAttrMapImpl *getDefaultAttributes(); - virtual void setupDefaultAttributes(); + // for handling of default attribute + virtual DOMAttr* setDefaultAttributeNode(DOMAttr *newAttr); + virtual DOMAttr* setDefaultAttributeNodeNS(DOMAttr *newAttr); + virtual DOMAttrMapImpl* getDefaultAttributes() const; + + // helper function for DOM Level 3 renameNode + virtual DOMNode* rename(const XMLCh* namespaceURI, const XMLCh* name); + +protected: + // default attribute helper functions + virtual void setupDefaultAttributes(); - // helper function for DOM Level 3 renameNode - virtual DOMNode* rename(const XMLCh* namespaceURI, const XMLCh* name); }; #endif diff --git a/src/xercesc/parsers/AbstractDOMParser.cpp b/src/xercesc/parsers/AbstractDOMParser.cpp index ff2fe7629abeeb2c88b79a2169e7d1e17950e190..c9f42e64b69f4beb60f71825d3044d040a1009ea 100644 --- a/src/xercesc/parsers/AbstractDOMParser.cpp +++ b/src/xercesc/parsers/AbstractDOMParser.cpp @@ -611,6 +611,7 @@ void AbstractDOMParser::startElement(const XMLElementDecl& elemDecl , const bool isRoot) { DOMElement *elem; + DOMElementImpl *elemImpl; if (fScanner -> getDoNamespaces()) { //DOM Level 2, doNamespaces on @@ -632,7 +633,7 @@ void AbstractDOMParser::startElement(const XMLElementDecl& elemDecl elemQName.append(elemDecl.getBaseName()); elem = createElementNSNode(namespaceURI, elemQName.getRawBuffer()); - DOMElementImpl *elemImpl = (DOMElementImpl *) elem; + elemImpl = (DOMElementImpl *) elem; for (unsigned int index = 0; index < attrCount; ++index) { static const XMLCh XMLNS[] = { chLatin_x, chLatin_m, chLatin_l, chLatin_n, chLatin_s, chNull @@ -674,7 +675,7 @@ void AbstractDOMParser::startElement(const XMLElementDecl& elemDecl } else { //DOM Level 1 elem = fDocument->createElement(elemDecl.getFullName()); - DOMElementImpl *elemImpl = (DOMElementImpl *) elem; + elemImpl = (DOMElementImpl *) elem; for (unsigned int index = 0; index < attrCount; ++index) { const XMLAttr* oneAttrib = attrList.elementAt(index); //AttrImpl *attr = elemImpl->setAttribute(oneAttrib->getName(), oneAttrib->getValue()); @@ -699,6 +700,90 @@ void AbstractDOMParser::startElement(const XMLElementDecl& elemDecl } } + // set up the default attributes + if (elemDecl.hasAttDefs()) + { + XMLAttDefList* defAttrs = &elemDecl.getAttDefList(); + XMLAttDef* attr = 0; + + DOMAttrImpl * insertAttr = 0; + + while (defAttrs->hasMoreElements()) + { + attr = &defAttrs->nextElement(); + const XMLAttDef::DefAttTypes defType = attr->getDefaultType(); + + if ((defType == XMLAttDef::Default) + || (defType == XMLAttDef::Fixed)) + { + if (attr->getValue() != 0) + { + if (fScanner->getDoNamespaces()) + { + // DOM Level 2 wants all namespace declaration attributes + // to be bound to "http://www.w3.org/2000/xmlns/" + // So as long as the XML parser doesn't do it, it needs to + // done here. + const XMLCh* qualifiedName = attr->getFullName(); + int index = DOMDocumentImpl::indexofQualifiedName(qualifiedName); + + XMLBufBid bbQName(&fBufMgr); + XMLBuffer& buf = bbQName.getBuffer(); + static const XMLCh XMLNS[] = { + chLatin_x, chLatin_m, chLatin_l, chLatin_n, chLatin_s, chNull}; + + if (index > 0) { + // there is prefix + // map to XML URI for all cases except when prefix == "xmlns" + XMLCh* prefix; + XMLCh temp[1000]; + + if (index > 999) + prefix = new XMLCh[index+1]; + else + prefix = temp; + + XMLString::subString(prefix ,qualifiedName, 0, index); + + if (!XMLString::compareString(prefix,XMLNS)) + buf.append(XMLUni::fgXMLNSURIName); + else + buf.append(XMLUni::fgXMLURIName); + + if (index > 999) + delete prefix; + } + else { + // No prefix + if (!XMLString::compareString(qualifiedName,XMLNS)) + buf.append(XMLUni::fgXMLNSURIName); + } + + insertAttr = (DOMAttrImpl *) fDocument->createAttributeNS( + buf.getRawBuffer(), // NameSpaceURI + qualifiedName); // qualified name + + DOMNode* remAttr = elemImpl->setDefaultAttributeNodeNS(insertAttr); + if (remAttr) + remAttr->release(); + } + else + { + // Namespaces is turned off... + insertAttr = (DOMAttrImpl *) fDocument->createAttribute(attr->getFullName()); + DOMNode* remAttr = elemImpl->setDefaultAttributeNode(insertAttr); + if (remAttr) + remAttr->release(); + } + + insertAttr->setValue(attr->getValue()); + insertAttr->setSpecified(false); + } + } + } + } + + fCurrentParent->appendChild(elem); fNodeStack->push(fCurrentParent);