GME
13
|
00001 /* 00002 * Licensed to the Apache Software Foundation (ASF) under one or more 00003 * contributor license agreements. See the NOTICE file distributed with 00004 * this work for additional information regarding copyright ownership. 00005 * The ASF licenses this file to You under the Apache License, Version 2.0 00006 * (the "License"); you may not use this file except in compliance with 00007 * the License. You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 /* 00019 * $Id: DOMAttrImpl.cpp 678709 2008-07-22 10:56:56Z borisk $ 00020 */ 00021 00022 #include <xercesc/dom/DOMDocument.hpp> 00023 #include <xercesc/dom/DOMException.hpp> 00024 00025 #include "DOMAttrImpl.hpp" 00026 #include "DOMStringPool.hpp" 00027 #include "DOMDocumentImpl.hpp" 00028 #include "DOMCasts.hpp" 00029 #include "DOMTypeInfoImpl.hpp" 00030 00031 XERCES_CPP_NAMESPACE_BEGIN 00032 00033 DOMAttrImpl::DOMAttrImpl(DOMDocument *ownerDoc, const XMLCh *aName) 00034 : fNode(ownerDoc), fParent (ownerDoc), fSchemaType(0) 00035 { 00036 DOMDocumentImpl *docImpl = (DOMDocumentImpl *)ownerDoc; 00037 fName = docImpl->getPooledString(aName); 00038 fNode.isSpecified(true); 00039 } 00040 00041 DOMAttrImpl::DOMAttrImpl(const DOMAttrImpl &other, bool /*deep*/) 00042 : DOMAttr(other) 00043 , fNode(other.fNode) 00044 , fParent (other.fParent) 00045 , fName(other.fName) 00046 , fSchemaType(other.fSchemaType) 00047 { 00048 if (other.fNode.isSpecified()) 00049 fNode.isSpecified(true); 00050 else 00051 fNode.isSpecified(false); 00052 00053 if (other.fNode.isIdAttr()) 00054 { 00055 fNode.isIdAttr(true); 00056 DOMDocumentImpl *doc = (DOMDocumentImpl *)fParent.fOwnerDocument; 00057 doc->getNodeIDMap()->add(this); 00058 } 00059 00060 fParent.cloneChildren(&other); 00061 } 00062 00063 00064 DOMAttrImpl::~DOMAttrImpl() { 00065 } 00066 00067 00068 DOMNode * DOMAttrImpl::cloneNode(bool deep) const 00069 { 00070 DOMNode* newNode = new (fParent.fOwnerDocument, DOMDocumentImpl::ATTR_OBJECT) DOMAttrImpl(*this, deep); 00071 fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode); 00072 return newNode; 00073 } 00074 00075 00076 const XMLCh * DOMAttrImpl::getNodeName() const{ 00077 return fName; 00078 } 00079 00080 DOMNode::NodeType DOMAttrImpl::getNodeType() const { 00081 return DOMNode::ATTRIBUTE_NODE; 00082 } 00083 00084 00085 const XMLCh * DOMAttrImpl::getName() const { 00086 return fName; 00087 } 00088 00089 00090 const XMLCh * DOMAttrImpl::getNodeValue() const 00091 { 00092 return getValue(); 00093 } 00094 00095 00096 bool DOMAttrImpl::getSpecified() const 00097 { 00098 return fNode.isSpecified(); 00099 } 00100 00101 00102 00103 00104 const XMLCh * DOMAttrImpl::getValue() const 00105 { 00106 if (fParent.fFirstChild == 0) { 00107 return XMLUni::fgZeroLenString; // return ""; 00108 } 00109 00110 // Simple case where attribute value is just a single text node 00111 DOMNode *node = castToChildImpl(fParent.fFirstChild)->nextSibling; 00112 if (node == 0 && fParent.fFirstChild->getNodeType() == DOMNode::TEXT_NODE) { 00113 return fParent.fFirstChild->getNodeValue(); 00114 } 00115 00116 // 00117 // Complicated case where attribute value is a DOM tree 00118 // 00119 // According to the spec, the child nodes of the Attr node may be either 00120 // Text or EntityReference nodes. 00121 // 00122 // The parser will not create such thing, this is for those created by users. 00123 // 00124 // In such case, we have to visit each child to retrieve the text 00125 // 00126 00127 DOMDocumentImpl* doc = (DOMDocumentImpl*)fParent.fOwnerDocument; 00128 00129 XMLBuffer buf(1023, doc->getMemoryManager()); 00130 for (node = fParent.fFirstChild; node != 0; node = castToChildImpl(node)->nextSibling) 00131 getTextValue(node, buf); 00132 00133 return doc->getPooledString(buf.getRawBuffer()); 00134 } 00135 00136 void DOMAttrImpl::getTextValue(DOMNode* node, XMLBuffer& buf) const 00137 { 00138 if (node->getNodeType() == DOMNode::TEXT_NODE) 00139 buf.append(node->getNodeValue()); 00140 else if (node->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE) 00141 { 00142 for (node = node->getFirstChild(); node != 0; node = castToChildImpl(node)->nextSibling) 00143 { 00144 getTextValue(node, buf); 00145 } 00146 } 00147 00148 return; 00149 } 00150 00151 00152 void DOMAttrImpl::setNodeValue(const XMLCh *val) 00153 { 00154 setValue(val); 00155 } 00156 00157 00158 00159 void DOMAttrImpl::setSpecified(bool arg) 00160 { 00161 fNode.isSpecified(arg); 00162 } 00163 00164 00165 00166 void DOMAttrImpl::setValue(const XMLCh *val) 00167 { 00168 if (fNode.isReadOnly()) 00169 { 00170 throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager); 00171 } 00172 00173 // If this attribute was of type ID and in the map, take it out, 00174 // then put it back in with the new name. For now, we don't worry 00175 // about what happens if the new name conflicts 00176 // 00177 DOMDocumentImpl *doc = (DOMDocumentImpl *)fParent.fOwnerDocument; 00178 if (fNode.isIdAttr()) 00179 doc->getNodeIDMap()->remove(this); 00180 00181 DOMNode *kid; 00182 while ((kid = fParent.fFirstChild) != 0) // Remove existing kids 00183 { 00184 DOMNode* node = removeChild(kid); 00185 if (node) 00186 node->release(); 00187 } 00188 00189 if (val != 0) // Create and add the new one 00190 fParent.appendChildFast(doc->createTextNode(val)); 00191 fNode.isSpecified(true); 00192 fParent.changed(); 00193 00194 if (fNode.isIdAttr()) 00195 doc->getNodeIDMap()->add(this); 00196 00197 } 00198 00199 void DOMAttrImpl::setValueFast(const XMLCh *val) 00200 { 00201 if (val != 0) 00202 fParent.appendChildFast(fParent.fOwnerDocument->createTextNode(val)); 00203 00204 fNode.isSpecified (true); 00205 } 00206 00207 00208 00209 //Introduced in DOM Level 2 00210 00211 DOMElement *DOMAttrImpl::getOwnerElement() const 00212 { 00213 // if we have an owner, ownerNode is our ownerElement, otherwise it's 00214 // our ownerDocument and we don't have an ownerElement 00215 return (DOMElement *) (fNode.isOwned() ? fNode.fOwnerNode : 0); 00216 } 00217 00218 00219 //internal use by parser only 00220 void DOMAttrImpl::setOwnerElement(DOMElement *ownerElem) 00221 { 00222 fNode.fOwnerNode = ownerElem; 00223 // revisit. Is this backwards? isOwned(true)? 00224 fNode.isOwned(false); 00225 } 00226 00227 00228 //For DOM Level 3 00229 00230 void DOMAttrImpl::release() 00231 { 00232 if (fNode.isOwned() && !fNode.isToBeReleased()) 00233 throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager); 00234 00235 DOMDocumentImpl* doc = (DOMDocumentImpl*)fParent.fOwnerDocument; 00236 if (doc) { 00237 fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0); 00238 fParent.release(); 00239 doc->release(this, DOMMemoryManager::ATTR_OBJECT); 00240 } 00241 else { 00242 // shouldn't reach here 00243 throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager); 00244 } 00245 } 00246 00247 00248 bool DOMAttrImpl::isId() const { 00249 return fNode.isIdAttr(); 00250 } 00251 00252 00253 DOMNode* DOMAttrImpl::rename(const XMLCh* namespaceURI, const XMLCh* name) 00254 { 00255 DOMElement* el = getOwnerElement(); 00256 DOMDocumentImpl* doc = (DOMDocumentImpl*)fParent.fOwnerDocument; 00257 00258 if (el) 00259 el->removeAttributeNode(this); 00260 00261 if (!namespaceURI || !*namespaceURI) { 00262 fName = doc->getPooledString(name); 00263 00264 if (el) 00265 el->setAttributeNode(this); 00266 00267 // and fire user data NODE_RENAMED event 00268 castToNodeImpl(this)->callUserDataHandlers(DOMUserDataHandler::NODE_RENAMED, this, this); 00269 00270 return this; 00271 } 00272 else { 00273 00274 // create a new AttrNS 00275 DOMAttr* newAttr = doc->createAttributeNS(namespaceURI, name); 00276 00277 // transfer the userData 00278 doc->transferUserData(castToNodeImpl(this), castToNodeImpl(newAttr)); 00279 00280 // move children to new node 00281 DOMNode* child = getFirstChild(); 00282 while (child) { 00283 removeChild(child); 00284 newAttr->appendChild(child); 00285 child = getFirstChild(); 00286 } 00287 00288 // reattach attr to element 00289 if (el) 00290 el->setAttributeNodeNS(newAttr); 00291 00292 // and fire user data NODE_RENAMED event 00293 castToNodeImpl(newAttr)->callUserDataHandlers(DOMUserDataHandler::NODE_RENAMED, this, newAttr); 00294 00295 return newAttr; 00296 } 00297 } 00298 00299 const DOMTypeInfo *DOMAttrImpl::getSchemaTypeInfo() const 00300 { 00301 if(!fSchemaType) 00302 return &DOMTypeInfoImpl::g_DtdNotValidatedAttribute; 00303 00304 return fSchemaType; 00305 } 00306 00307 00308 void DOMAttrImpl::setSchemaTypeInfo(const DOMTypeInfoImpl* typeInfo) 00309 { 00310 fSchemaType = typeInfo; 00311 } 00312 00313 bool DOMAttrImpl::isSupported(const XMLCh *feature, const XMLCh *version) const 00314 { 00315 // check for '+DOMPSVITypeInfo' 00316 if(feature && *feature=='+' && XMLString::equals(feature+1, XMLUni::fgXercescInterfacePSVITypeInfo)) 00317 return true; 00318 return fNode.isSupported (feature, version); 00319 } 00320 00321 void* DOMAttrImpl::getFeature(const XMLCh* feature, const XMLCh* version) const 00322 { 00323 if(XMLString::equals(feature, XMLUni::fgXercescInterfacePSVITypeInfo)) 00324 return (DOMPSVITypeInfo*)fSchemaType; 00325 return fNode.getFeature(feature, version); 00326 } 00327 00328 DOMNode* DOMAttrImpl::appendChild(DOMNode *newChild) {return fParent.appendChild (newChild); } 00329 DOMNamedNodeMap* DOMAttrImpl::getAttributes() const {return fNode.getAttributes (); } 00330 DOMNodeList* DOMAttrImpl::getChildNodes() const {return fParent.getChildNodes (); } 00331 DOMNode* DOMAttrImpl::getFirstChild() const {return fParent.getFirstChild (); } 00332 DOMNode* DOMAttrImpl::getLastChild() const {return fParent.getLastChild (); } 00333 const XMLCh* DOMAttrImpl::getLocalName() const {return fNode.getLocalName (); } 00334 const XMLCh* DOMAttrImpl::getNamespaceURI() const {return fNode.getNamespaceURI (); } 00335 DOMNode* DOMAttrImpl::getNextSibling() const {return fNode.getNextSibling (); } 00336 DOMDocument* DOMAttrImpl::getOwnerDocument() const {return fParent.fOwnerDocument; } 00337 const XMLCh* DOMAttrImpl::getPrefix() const {return fNode.getPrefix (); } 00338 DOMNode* DOMAttrImpl::getParentNode() const {return fNode.getParentNode (); } 00339 DOMNode* DOMAttrImpl::getPreviousSibling() const {return fNode.getPreviousSibling (); } 00340 bool DOMAttrImpl::hasChildNodes() const {return fParent.hasChildNodes (); } 00341 DOMNode* DOMAttrImpl::insertBefore(DOMNode *newChild, DOMNode *refChild) 00342 {return fParent.insertBefore (newChild, refChild); } 00343 void DOMAttrImpl::normalize() {fParent.normalize (); } 00344 DOMNode* DOMAttrImpl::removeChild(DOMNode *oldChild) {return fParent.removeChild (oldChild); } 00345 DOMNode* DOMAttrImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild) 00346 {return fParent.replaceChild (newChild, oldChild); } 00347 void DOMAttrImpl::setPrefix(const XMLCh *prefix) {fNode.setPrefix(prefix); } 00348 bool DOMAttrImpl::hasAttributes() const {return fNode.hasAttributes(); } 00349 bool DOMAttrImpl::isSameNode(const DOMNode* other) const {return fNode.isSameNode(other); } 00350 bool DOMAttrImpl::isEqualNode(const DOMNode* arg) const {return fParent.isEqualNode(arg); } 00351 void* DOMAttrImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler) 00352 {return fNode.setUserData(key, data, handler); } 00353 void* DOMAttrImpl::getUserData(const XMLCh* key) const {return fNode.getUserData(key); } 00354 const XMLCh* DOMAttrImpl::getBaseURI() const {return fNode.getBaseURI(); } 00355 short DOMAttrImpl::compareDocumentPosition(const DOMNode* other) const {return fNode.compareDocumentPosition(other); } 00356 const XMLCh* DOMAttrImpl::getTextContent() const {return fNode.getTextContent(); } 00357 void DOMAttrImpl::setTextContent(const XMLCh* textContent){fNode.setTextContent(textContent); } 00358 const XMLCh* DOMAttrImpl::lookupPrefix(const XMLCh* namespaceURI) const {return fNode.lookupPrefix(namespaceURI); } 00359 bool DOMAttrImpl::isDefaultNamespace(const XMLCh* namespaceURI) const {return fNode.isDefaultNamespace(namespaceURI); } 00360 const XMLCh* DOMAttrImpl::lookupNamespaceURI(const XMLCh* prefix) const {return fNode.lookupNamespaceURI(prefix); } 00361 00362 XERCES_CPP_NAMESPACE_END