Newer
Older
/*
* Copyright 2001-2002,2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id$
*/
#include <xercesc/dom/DOMDocument.hpp>
#include <xercesc/dom/DOMException.hpp>
#include "DOMAttrImpl.hpp"
#include "DOMStringPool.hpp"
#include "DOMDocumentImpl.hpp"
#include "DOMCasts.hpp"
DOMAttrImpl::DOMAttrImpl(DOMDocument *ownerDoc, const XMLCh *aName)
: fNode(ownerDoc), fParent (ownerDoc), fSchemaType(0)
{
DOMDocumentImpl *docImpl = (DOMDocumentImpl *)ownerDoc;
fName = docImpl->getPooledString(aName);
fNode.isSpecified(true);
David Abram Cargill
committed
}
David Abram Cargill
committed
DOMAttrImpl::DOMAttrImpl(const DOMAttrImpl &other, bool)
: fNode(other.fNode), fParent (other.fParent), fName(other.fName), fSchemaType(other.fSchemaType)
{
if (other.fNode.isSpecified())
fNode.isSpecified(true);
else
fNode.isSpecified(false);
if (other.fNode.isIdAttr())
{
fNode.isIdAttr(true);
DOMDocumentImpl *doc = (DOMDocumentImpl *)this->getOwnerDocument();
doc->getNodeIDMap()->add(this);
}
David Abram Cargill
committed
}
DOMAttrImpl::~DOMAttrImpl() {
David Abram Cargill
committed
}
DOMNode * DOMAttrImpl::cloneNode(bool deep) const
{
DOMNode* newNode = new (this->getOwnerDocument(), DOMDocumentImpl::ATTR_OBJECT) DOMAttrImpl(*this, deep);
fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode);
return newNode;
David Abram Cargill
committed
}
const XMLCh * DOMAttrImpl::getNodeName() const{
return fName;
David Abram Cargill
committed
}
short DOMAttrImpl::getNodeType() const {
return DOMNode::ATTRIBUTE_NODE;
David Abram Cargill
committed
}
const XMLCh * DOMAttrImpl::getName() const {
return fName;
David Abram Cargill
committed
}
const XMLCh * DOMAttrImpl::getNodeValue() const
{
return getValue();
David Abram Cargill
committed
}
bool DOMAttrImpl::getSpecified() const
{
return fNode.isSpecified();
David Abram Cargill
committed
}
const XMLCh * DOMAttrImpl::getValue() const
{
if (fParent.fFirstChild == 0) {
return XMLUni::fgZeroLenString; // return "";
}
Tinny Ng
committed
// Simple case where attribute value is just a single text node
DOMNode *node = castToChildImpl(fParent.fFirstChild)->nextSibling;
Tinny Ng
committed
if (node == 0 && fParent.fFirstChild->getNodeType() == DOMNode::TEXT_NODE) {
return fParent.fFirstChild->getNodeValue();
}
Tinny Ng
committed
//
// Complicated case whre attribute value is a DOM tree
//
// According to the spec, the child nodes of the Attr node may be either
// Text or EntityReference nodes.
//
// The parser will not create such thing, this is for those created by users.
//
// In such case, we have to visit each child to retrieve the text
//
Khaled Noaman
committed
XMLBuffer buf(1023, ((DOMDocumentImpl *)this->getOwnerDocument())->getMemoryManager());
Tinny Ng
committed
getTextValue(fParent.fFirstChild, buf);
return (XMLCh*) ((DOMDocumentImpl *)this->getOwnerDocument())->getPooledString(buf.getRawBuffer());
David Abram Cargill
committed
}
Tinny Ng
committed
void DOMAttrImpl::getTextValue(DOMNode* node, XMLBuffer& buf) const
{
if (node->getNodeType() == DOMNode::TEXT_NODE)
buf.append(node->getNodeValue());
else if (node->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE)
{
for (node = node->getFirstChild(); node != 0; node = castToChildImpl(node)->nextSibling)
{
getTextValue(node, buf);
}
}
return;
}
void DOMAttrImpl::setNodeValue(const XMLCh *val)
{
setValue(val);
David Abram Cargill
committed
}
void DOMAttrImpl::setSpecified(bool arg)
{
fNode.isSpecified(arg);
David Abram Cargill
committed
}
void DOMAttrImpl::setValue(const XMLCh *val)
{
if (fNode.isReadOnly())
{
throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
}
// If this attribute was of type ID and in the map, take it out,
// then put it back in with the new name. For now, we don't worry
// about what happens if the new name conflicts
//
DOMDocumentImpl *doc = (DOMDocumentImpl *)getOwnerDocument();
if (fNode.isIdAttr())
doc->getNodeIDMap()->remove(this);
DOMNode *kid;
while ((kid = fParent.fFirstChild) != 0) // Remove existing kids
{
DOMNode* node = removeChild(kid);
if (node)
node->release();
}
if (val != 0) // Create and add the new one
appendChild(doc->createTextNode(val));
fNode.isSpecified(true);
fParent.changed();
if (fNode.isIdAttr())
doc->getNodeIDMap()->add(this);
David Abram Cargill
committed
}
//Introduced in DOM Level 2
DOMElement *DOMAttrImpl::getOwnerElement() const
{
// if we have an owner, ownerNode is our ownerElement, otherwise it's
// our ownerDocument and we don't have an ownerElement
return (DOMElement *) (fNode.isOwned() ? fNode.fOwnerNode : 0);
}
//internal use by parser only
void DOMAttrImpl::setOwnerElement(DOMElement *ownerElem)
{
fNode.fOwnerNode = ownerElem;
// revisit. Is this backwards? isOwned(true)?
fNode.isOwned(false);
}
void DOMAttrImpl::release()
{
if (fNode.isOwned() && !fNode.isToBeReleased())
throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager);
DOMDocumentImpl* doc = (DOMDocumentImpl*) getOwnerDocument();
if (doc) {
fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0);
fParent.release();
doc->release(this, DOMDocumentImpl::ATTR_OBJECT);
}
else {
// shouldn't reach here
throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager);
}
}
Gareth Reakes
committed
bool DOMAttrImpl::isId() const {
return fNode.isIdAttr();
}
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
DOMNode* DOMAttrImpl::rename(const XMLCh* namespaceURI, const XMLCh* name)
{
DOMElement* el = getOwnerElement();
DOMDocumentImpl* doc = (DOMDocumentImpl*) getOwnerDocument();
if (el)
el->removeAttributeNode(this);
if (!namespaceURI || !*namespaceURI) {
fName = doc->getPooledString(name);
if (el)
el->setAttributeNode(this);
return this;
}
else {
// create a new AttrNS
DOMAttr* newAttr = doc->createAttributeNS(namespaceURI, name);
// transfer the userData
doc->transferUserData(castToNodeImpl(this), castToNodeImpl(newAttr));
// move children to new node
DOMNode* child = getFirstChild();
while (child) {
removeChild(child);
newAttr->appendChild(child);
child = getFirstChild();
}
// and fire user data NODE_RENAMED event
castToNodeImpl(newAttr)->callUserDataHandlers(DOMUserDataHandler::NODE_RENAMED, this, newAttr);
// reattach attr to element
if (el)
el->setAttributeNodeNS(newAttr);
return newAttr;
}
}
const DOMTypeInfo *DOMAttrImpl::getTypeInfo() const
{
if(!fSchemaType)
return &DOMTypeInfoImpl::g_DtdNotValidatedAttribute;
void DOMAttrImpl::setTypeInfo(const DOMTypeInfoImpl* typeInfo)
fSchemaType = typeInfo;
DOMNode * DOMAttrImpl::getInterface(const XMLCh* feature)
{
if(XMLString::equals(feature, XMLUni::fgXercescInterfacePSVITypeInfo))
return (DOMNode*)(DOMPSVITypeInfo*)fSchemaType;
return fNode.getInterface(feature);
}
David Abram Cargill
committed
DOMNode* DOMAttrImpl::appendChild(DOMNode *newChild) {return fParent.appendChild (newChild); }
DOMNamedNodeMap* DOMAttrImpl::getAttributes() const {return fNode.getAttributes (); }
DOMNodeList* DOMAttrImpl::getChildNodes() const {return fParent.getChildNodes (); }
DOMNode* DOMAttrImpl::getFirstChild() const {return fParent.getFirstChild (); }
DOMNode* DOMAttrImpl::getLastChild() const {return fParent.getLastChild (); }
const XMLCh* DOMAttrImpl::getLocalName() const {return fNode.getLocalName (); }
const XMLCh* DOMAttrImpl::getNamespaceURI() const {return fNode.getNamespaceURI (); }
DOMNode* DOMAttrImpl::getNextSibling() const {return fNode.getNextSibling (); }
DOMDocument* DOMAttrImpl::getOwnerDocument() const {return fParent.fOwnerDocument; }
const XMLCh* DOMAttrImpl::getPrefix() const {return fNode.getPrefix (); }
DOMNode* DOMAttrImpl::getParentNode() const {return fNode.getParentNode (); }
DOMNode* DOMAttrImpl::getPreviousSibling() const {return fNode.getPreviousSibling (); }
bool DOMAttrImpl::hasChildNodes() const {return fParent.hasChildNodes (); }
DOMNode* DOMAttrImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
David Abram Cargill
committed
{return fParent.insertBefore (newChild, refChild); }
void DOMAttrImpl::normalize() {fParent.normalize (); }
DOMNode* DOMAttrImpl::removeChild(DOMNode *oldChild) {return fParent.removeChild (oldChild); }
DOMNode* DOMAttrImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
David Abram Cargill
committed
{return fParent.replaceChild (newChild, oldChild); }
bool DOMAttrImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
David Abram Cargill
committed
{return fNode.isSupported (feature, version); }
void DOMAttrImpl::setPrefix(const XMLCh *prefix) {fNode.setPrefix(prefix); }
bool DOMAttrImpl::hasAttributes() const {return fNode.hasAttributes(); }
bool DOMAttrImpl::isSameNode(const DOMNode* other) const {return fNode.isSameNode(other); }
bool DOMAttrImpl::isEqualNode(const DOMNode* arg) const {return fParent.isEqualNode(arg); }
void* DOMAttrImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler)
David Abram Cargill
committed
{return fNode.setUserData(key, data, handler); }
void* DOMAttrImpl::getUserData(const XMLCh* key) const {return fNode.getUserData(key); }
const XMLCh* DOMAttrImpl::getBaseURI() const {return fNode.getBaseURI(); }
short DOMAttrImpl::compareTreePosition(const DOMNode* other) const {return fNode.compareTreePosition(other); }
const XMLCh* DOMAttrImpl::getTextContent() const {return fNode.getTextContent(); }
void DOMAttrImpl::setTextContent(const XMLCh* textContent){fNode.setTextContent(textContent); }
const XMLCh* DOMAttrImpl::lookupNamespacePrefix(const XMLCh* namespaceURI, bool useDefault) const {return fNode.lookupNamespacePrefix(namespaceURI, useDefault); }
bool DOMAttrImpl::isDefaultNamespace(const XMLCh* namespaceURI) const {return fNode.isDefaultNamespace(namespaceURI); }
const XMLCh* DOMAttrImpl::lookupNamespaceURI(const XMLCh* prefix) const {return fNode.lookupNamespaceURI(prefix); }