source: icXML/icXML-devel/src/xercesc/dom/impl/DOMAttrImpl.cpp @ 2722

Last change on this file since 2722 was 2722, checked in by cameron, 6 years ago

Original Xerces files with import mods for icxercesc

File size: 12.3 KB
Line 
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/*
19 * $Id: DOMAttrImpl.cpp 678709 2008-07-22 10:56:56Z borisk $
20 */
21
22#include <xercesc/dom/DOMDocument.hpp>
23#include <xercesc/dom/DOMException.hpp>
24
25#include "DOMAttrImpl.hpp"
26#include "DOMStringPool.hpp"
27#include "DOMDocumentImpl.hpp"
28#include "DOMCasts.hpp"
29#include "DOMTypeInfoImpl.hpp"
30
31XERCES_CPP_NAMESPACE_BEGIN
32
33DOMAttrImpl::DOMAttrImpl(DOMDocument *ownerDoc, const XMLCh *aName)
34    : fNode(ownerDoc), fParent (ownerDoc), fSchemaType(0)
35{
36    DOMDocumentImpl *docImpl = (DOMDocumentImpl *)ownerDoc;
37    fName = docImpl->getPooledString(aName);
38    fNode.isSpecified(true);
39}
40
41DOMAttrImpl::DOMAttrImpl(const DOMAttrImpl &other, bool /*deep*/)
42    : DOMAttr(other)
43    , fNode(other.fNode)
44    , fParent (other.fParent)
45    , fName(other.fName)
46    , fSchemaType(other.fSchemaType)
47{
48    if (other.fNode.isSpecified())
49        fNode.isSpecified(true);
50    else
51        fNode.isSpecified(false);
52
53    if (other.fNode.isIdAttr())
54    {
55        fNode.isIdAttr(true);
56        DOMDocumentImpl *doc = (DOMDocumentImpl *)fParent.fOwnerDocument;
57        doc->getNodeIDMap()->add(this);
58    }
59
60    fParent.cloneChildren(&other);
61}
62
63
64DOMAttrImpl::~DOMAttrImpl() {
65}
66
67
68DOMNode * DOMAttrImpl::cloneNode(bool deep) const
69{
70    DOMNode* newNode = new (fParent.fOwnerDocument, DOMDocumentImpl::ATTR_OBJECT) DOMAttrImpl(*this, deep);
71    fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode);
72    return newNode;
73}
74
75
76const XMLCh * DOMAttrImpl::getNodeName()  const{
77    return fName;
78}
79
80DOMNode::NodeType DOMAttrImpl::getNodeType() const {
81    return DOMNode::ATTRIBUTE_NODE;
82}
83
84
85const XMLCh * DOMAttrImpl::getName() const {
86    return fName;
87}
88
89
90const XMLCh * DOMAttrImpl::getNodeValue() const
91{
92    return getValue();
93}
94
95
96bool DOMAttrImpl::getSpecified() const
97{
98    return fNode.isSpecified();
99}
100
101
102
103
104const XMLCh * DOMAttrImpl::getValue() const
105{
106    if (fParent.fFirstChild == 0) {
107        return XMLUni::fgZeroLenString; // return "";
108    }
109
110    // Simple case where attribute value is just a single text node
111    DOMNode *node = castToChildImpl(fParent.fFirstChild)->nextSibling;
112    if (node == 0 && fParent.fFirstChild->getNodeType() == DOMNode::TEXT_NODE) {
113        return fParent.fFirstChild->getNodeValue();
114    }
115
116    //
117    // Complicated case where attribute value is a DOM tree
118    //
119    // According to the spec, the child nodes of the Attr node may be either
120    // Text or EntityReference nodes.
121    //
122    // The parser will not create such thing, this is for those created by users.
123    //
124    // In such case, we have to visit each child to retrieve the text
125    //
126
127    DOMDocumentImpl* doc = (DOMDocumentImpl*)fParent.fOwnerDocument;
128
129    XMLBuffer buf(1023, doc->getMemoryManager());
130    for (node = fParent.fFirstChild; node != 0; node = castToChildImpl(node)->nextSibling)
131        getTextValue(node, buf);
132
133    return doc->getPooledString(buf.getRawBuffer());
134}
135
136void DOMAttrImpl::getTextValue(DOMNode* node, XMLBuffer& buf) const
137{
138    if (node->getNodeType() == DOMNode::TEXT_NODE)
139        buf.append(node->getNodeValue());
140    else if (node->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE)
141    {
142        for (node = node->getFirstChild(); node != 0; node = castToChildImpl(node)->nextSibling)
143        {
144            getTextValue(node, buf);
145        }
146    }
147
148    return;
149}
150
151
152void DOMAttrImpl::setNodeValue(const XMLCh *val)
153{
154    setValue(val);
155}
156
157
158
159void DOMAttrImpl::setSpecified(bool arg)
160{
161    fNode.isSpecified(arg);
162}
163
164
165
166void DOMAttrImpl::setValue(const XMLCh *val)
167{
168    if (fNode.isReadOnly())
169    {
170        throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
171    }
172
173    //  If this attribute was of type ID and in the map, take it out,
174    //    then put it back in with the new name.  For now, we don't worry
175    //    about what happens if the new name conflicts
176    //
177    DOMDocumentImpl *doc = (DOMDocumentImpl *)fParent.fOwnerDocument;
178    if (fNode.isIdAttr())
179        doc->getNodeIDMap()->remove(this);
180
181    DOMNode *kid;
182    while ((kid = fParent.fFirstChild) != 0)         // Remove existing kids
183    {
184        DOMNode* node = removeChild(kid);
185        if (node)
186            node->release();
187    }
188
189    if (val != 0)              // Create and add the new one
190        fParent.appendChildFast(doc->createTextNode(val));
191    fNode.isSpecified(true);
192    fParent.changed();
193
194    if (fNode.isIdAttr())
195        doc->getNodeIDMap()->add(this);
196
197}
198
199void DOMAttrImpl::setValueFast(const XMLCh *val)
200{
201    if (val != 0)
202      fParent.appendChildFast(fParent.fOwnerDocument->createTextNode(val));
203
204    fNode.isSpecified (true);
205}
206
207
208
209//Introduced in DOM Level 2
210
211DOMElement *DOMAttrImpl::getOwnerElement() const
212{
213    // if we have an owner, ownerNode is our ownerElement, otherwise it's
214    // our ownerDocument and we don't have an ownerElement
215    return (DOMElement *) (fNode.isOwned() ? fNode.fOwnerNode : 0);
216}
217
218
219//internal use by parser only
220void DOMAttrImpl::setOwnerElement(DOMElement *ownerElem)
221{
222    fNode.fOwnerNode = ownerElem;
223    // revisit.  Is this backwards?  isOwned(true)?
224    fNode.isOwned(false);
225}
226
227
228//For DOM Level 3
229
230void DOMAttrImpl::release()
231{
232    if (fNode.isOwned() && !fNode.isToBeReleased())
233        throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager);
234
235    DOMDocumentImpl* doc = (DOMDocumentImpl*)fParent.fOwnerDocument;
236    if (doc) {
237        fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0);
238        fParent.release();
239        doc->release(this, DOMMemoryManager::ATTR_OBJECT);
240    }
241    else {
242        // shouldn't reach here
243        throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager);
244    }
245}
246
247
248bool DOMAttrImpl::isId() const {
249    return fNode.isIdAttr();
250}
251
252
253DOMNode* DOMAttrImpl::rename(const XMLCh* namespaceURI, const XMLCh* name)
254{
255    DOMElement* el = getOwnerElement();
256    DOMDocumentImpl* doc = (DOMDocumentImpl*)fParent.fOwnerDocument;
257
258    if (el)
259        el->removeAttributeNode(this);
260
261    if (!namespaceURI || !*namespaceURI) {
262        fName = doc->getPooledString(name);
263
264        if (el)
265            el->setAttributeNode(this);
266
267        // and fire user data NODE_RENAMED event
268        castToNodeImpl(this)->callUserDataHandlers(DOMUserDataHandler::NODE_RENAMED, this, this);
269
270        return this;
271    }
272    else {
273
274        // create a new AttrNS
275        DOMAttr* newAttr = doc->createAttributeNS(namespaceURI, name);
276
277        // transfer the userData
278        doc->transferUserData(castToNodeImpl(this), castToNodeImpl(newAttr));
279
280        // move children to new node
281        DOMNode* child = getFirstChild();
282        while (child) {
283            removeChild(child);
284            newAttr->appendChild(child);
285            child = getFirstChild();
286        }
287
288        // reattach attr to element
289        if (el)
290            el->setAttributeNodeNS(newAttr);
291
292        // and fire user data NODE_RENAMED event
293        castToNodeImpl(newAttr)->callUserDataHandlers(DOMUserDataHandler::NODE_RENAMED, this, newAttr);
294
295        return newAttr;
296    }
297}
298
299const DOMTypeInfo *DOMAttrImpl::getSchemaTypeInfo() const
300{
301    if(!fSchemaType)
302        return &DOMTypeInfoImpl::g_DtdNotValidatedAttribute;
303
304    return fSchemaType;
305}
306
307
308void DOMAttrImpl::setSchemaTypeInfo(const DOMTypeInfoImpl* typeInfo)
309{
310    fSchemaType = typeInfo;
311}
312
313bool DOMAttrImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
314{
315    // check for '+DOMPSVITypeInfo'
316    if(feature && *feature=='+' && XMLString::equals(feature+1, XMLUni::fgXercescInterfacePSVITypeInfo))
317        return true;
318    return fNode.isSupported (feature, version);
319}
320
321void* DOMAttrImpl::getFeature(const XMLCh* feature, const XMLCh* version) const
322{
323    if(XMLString::equals(feature, XMLUni::fgXercescInterfacePSVITypeInfo))
324        return (DOMPSVITypeInfo*)fSchemaType;
325    return fNode.getFeature(feature, version);
326}
327
328           DOMNode*         DOMAttrImpl::appendChild(DOMNode *newChild)          {return fParent.appendChild (newChild); }
329           DOMNamedNodeMap* DOMAttrImpl::getAttributes() const                   {return fNode.getAttributes (); }
330           DOMNodeList*     DOMAttrImpl::getChildNodes() const                   {return fParent.getChildNodes (); }
331           DOMNode*         DOMAttrImpl::getFirstChild() const                   {return fParent.getFirstChild (); }
332           DOMNode*         DOMAttrImpl::getLastChild() const                    {return fParent.getLastChild (); }
333     const XMLCh*           DOMAttrImpl::getLocalName() const                    {return fNode.getLocalName (); }
334     const XMLCh*           DOMAttrImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); }
335           DOMNode*         DOMAttrImpl::getNextSibling() const                  {return fNode.getNextSibling (); }
336           DOMDocument*     DOMAttrImpl::getOwnerDocument() const                {return fParent.fOwnerDocument; }
337     const XMLCh*           DOMAttrImpl::getPrefix() const                       {return fNode.getPrefix (); }
338           DOMNode*         DOMAttrImpl::getParentNode() const                   {return fNode.getParentNode (); }
339           DOMNode*         DOMAttrImpl::getPreviousSibling() const              {return fNode.getPreviousSibling (); }
340           bool             DOMAttrImpl::hasChildNodes() const                   {return fParent.hasChildNodes (); }
341           DOMNode*         DOMAttrImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
342                                                                                 {return fParent.insertBefore (newChild, refChild); }
343           void             DOMAttrImpl::normalize()                             {fParent.normalize (); }
344           DOMNode*         DOMAttrImpl::removeChild(DOMNode *oldChild)          {return fParent.removeChild (oldChild); }
345           DOMNode*         DOMAttrImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
346                                                                                 {return fParent.replaceChild (newChild, oldChild); }
347           void             DOMAttrImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); }
348           bool             DOMAttrImpl::hasAttributes() const                   {return fNode.hasAttributes(); }
349           bool             DOMAttrImpl::isSameNode(const DOMNode* other) const  {return fNode.isSameNode(other); }
350           bool             DOMAttrImpl::isEqualNode(const DOMNode* arg) const   {return fParent.isEqualNode(arg); }
351           void*            DOMAttrImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler)
352                                                                                 {return fNode.setUserData(key, data, handler); }
353           void*            DOMAttrImpl::getUserData(const XMLCh* key) const     {return fNode.getUserData(key); }
354           const XMLCh*     DOMAttrImpl::getBaseURI() const                      {return fNode.getBaseURI(); }
355           short            DOMAttrImpl::compareDocumentPosition(const DOMNode* other) const {return fNode.compareDocumentPosition(other); }
356           const XMLCh*     DOMAttrImpl::getTextContent() const                  {return fNode.getTextContent(); }
357           void             DOMAttrImpl::setTextContent(const XMLCh* textContent){fNode.setTextContent(textContent); }
358           const XMLCh*     DOMAttrImpl::lookupPrefix(const XMLCh* namespaceURI) const  {return fNode.lookupPrefix(namespaceURI); }
359           bool             DOMAttrImpl::isDefaultNamespace(const XMLCh* namespaceURI) const {return fNode.isDefaultNamespace(namespaceURI); }
360           const XMLCh*     DOMAttrImpl::lookupNamespaceURI(const XMLCh* prefix) const  {return fNode.lookupNamespaceURI(prefix); }
361
362XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.