~ubuntu-branches/ubuntu/precise/xerces-c/precise

« back to all changes in this revision

Viewing changes to src/xercesc/dom/impl/DOMNodeImpl.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jay Berkenbilt
  • Date: 2009-02-22 16:52:23 UTC
  • Revision ID: james.westby@ubuntu.com-20090222165223-klimp8u8m73yn9zp
Tags: upstream-3.0.1
ImportĀ upstreamĀ versionĀ 3.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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: DOMNodeImpl.cpp 673428 2008-07-02 16:00:35Z amassari $
 
20
 */
 
21
 
 
22
// This class doesn't support having any children, and implements the behavior
 
23
// of an empty NodeList as far getChildNodes is concerned.
 
24
// The ParentNode subclass overrides this behavior.
 
25
 
 
26
 
 
27
#include "DOMCasts.hpp"
 
28
 
 
29
#include "DOMDocumentTypeImpl.hpp"
 
30
#include "DOMElementImpl.hpp"
 
31
#include "DOMAttrImpl.hpp"
 
32
 
 
33
#include <xercesc/dom/DOMImplementation.hpp>
 
34
#include <xercesc/dom/DOMException.hpp>
 
35
 
 
36
#include <xercesc/util/XMLUniDefs.hpp>
 
37
#include <xercesc/util/PlatformUtils.hpp>
 
38
#include <xercesc/util/XMLInitializer.hpp>
 
39
#include <stdio.h>
 
40
#include <assert.h>
 
41
 
 
42
XERCES_CPP_NAMESPACE_BEGIN
 
43
 
 
44
//Though DOMNodeImpl does not derivate from DOMNode, it shares
 
45
//the same GetDOMNodeMemoryManager
 
46
 
 
47
const unsigned short DOMNodeImpl::READONLY     = 0x1<<0;
 
48
const unsigned short DOMNodeImpl::SYNCDATA     = 0x1<<1;
 
49
const unsigned short DOMNodeImpl::SYNCCHILDREN = 0x1<<2;
 
50
const unsigned short DOMNodeImpl::OWNED        = 0x1<<3;
 
51
const unsigned short DOMNodeImpl::FIRSTCHILD   = 0x1<<4;
 
52
const unsigned short DOMNodeImpl::SPECIFIED    = 0x1<<5;
 
53
const unsigned short DOMNodeImpl::IGNORABLEWS  = 0x1<<6;
 
54
const unsigned short DOMNodeImpl::SETVALUE     = 0x1<<7;
 
55
const unsigned short DOMNodeImpl::ID_ATTR      = 0x1<<8;
 
56
const unsigned short DOMNodeImpl::USERDATA     = 0x1<<9;
 
57
const unsigned short DOMNodeImpl::LEAFNODETYPE = 0x1<<10;
 
58
const unsigned short DOMNodeImpl::CHILDNODE    = 0x1<<11;
 
59
const unsigned short DOMNodeImpl::TOBERELEASED = 0x1<<12;
 
60
 
 
61
//
 
62
//
 
63
static DOMNodeListImpl *gEmptyNodeList = 0; // Singleton empty node list.
 
64
 
 
65
void XMLInitializer::initializeDOMNodeListImpl()
 
66
{
 
67
    gEmptyNodeList = new DOMNodeListImpl(0);
 
68
}
 
69
 
 
70
void XMLInitializer::terminateDOMNodeListImpl()
 
71
{
 
72
    delete gEmptyNodeList;
 
73
    gEmptyNodeList = 0;
 
74
}
 
75
 
 
76
// -----------------------------------------------------------------------
 
77
//  DOMNodeImpl Functions
 
78
// -----------------------------------------------------------------------
 
79
DOMNodeImpl::DOMNodeImpl(DOMNode *ownerNode)
 
80
:  fOwnerNode(ownerNode)
 
81
{
 
82
    this->flags = 0;
 
83
    // as long as we do not have any owner, fOwnerNode is our ownerDocument
 
84
}
 
85
 
 
86
// This only makes a shallow copy, cloneChildren must also be called for a
 
87
// deep clone
 
88
DOMNodeImpl::DOMNodeImpl(const DOMNodeImpl &other)
 
89
{
 
90
    this->flags = other.flags;
 
91
    this->isReadOnly(false);
 
92
 
 
93
    // Need to break the association w/ original parent
 
94
    this->fOwnerNode = other.getOwnerDocument();
 
95
    this->isOwned(false);
 
96
}
 
97
 
 
98
 
 
99
 
 
100
DOMNodeImpl::~DOMNodeImpl() {
 
101
}
 
102
 
 
103
 
 
104
DOMNode * DOMNodeImpl::appendChild(DOMNode *)
 
105
{
 
106
    // Only node types that don't allow children will use this default function.
 
107
    //   Others will go to DOMParentNode::appendChild.
 
108
    throw DOMException(DOMException::HIERARCHY_REQUEST_ERR,0, GetDOMNodeMemoryManager);
 
109
    return 0;
 
110
    //  return insertBefore(newChild, 0);
 
111
}
 
112
 
 
113
 
 
114
DOMNamedNodeMap * DOMNodeImpl::getAttributes() const {
 
115
    return 0;                   // overridden in ElementImpl
 
116
}
 
117
 
 
118
 
 
119
DOMNodeList *DOMNodeImpl::getChildNodes() const {
 
120
    return gEmptyNodeList;
 
121
}
 
122
 
 
123
 
 
124
 
 
125
DOMNode * DOMNodeImpl::getFirstChild() const {
 
126
    return 0;                   // overridden in ParentNode
 
127
}
 
128
 
 
129
 
 
130
DOMNode * DOMNodeImpl::getLastChild() const
 
131
{
 
132
    return 0;                   // overridden in ParentNode
 
133
}
 
134
 
 
135
 
 
136
DOMNode * DOMNodeImpl::getNextSibling() const {
 
137
    return 0;                // overridden in ChildNode
 
138
}
 
139
 
 
140
 
 
141
const XMLCh * DOMNodeImpl::getNodeValue() const {
 
142
    return 0;                    // Overridden by anything that has a value
 
143
}
 
144
 
 
145
 
 
146
//
 
147
//  Unlike the external getOwnerDocument, this one returns the owner document
 
148
//     for document nodes as well as all of the other node types.
 
149
//
 
150
DOMDocument *DOMNodeImpl::getOwnerDocument() const
 
151
{
 
152
    if (!this->isLeafNode())
 
153
    {
 
154
        DOMElementImpl *ep = (DOMElementImpl *)castToNode(this);
 
155
        return ep->fParent.fOwnerDocument;
 
156
    }
 
157
 
 
158
    //  Leaf node types - those that cannot have children, like Text.
 
159
    if (isOwned()) {
 
160
 
 
161
        DOMDocument* ownerDoc = fOwnerNode->getOwnerDocument();
 
162
 
 
163
        if (!ownerDoc) {
 
164
 
 
165
            assert (fOwnerNode->getNodeType() == DOMNode::DOCUMENT_NODE);
 
166
            return  (DOMDocument *)fOwnerNode;
 
167
        }
 
168
        else {
 
169
            return ownerDoc;
 
170
        }
 
171
    } else {
 
172
        assert (fOwnerNode->getNodeType() == DOMNode::DOCUMENT_NODE);
 
173
        return  (DOMDocument *)fOwnerNode;
 
174
    }
 
175
}
 
176
 
 
177
 
 
178
void DOMNodeImpl::setOwnerDocument(DOMDocument *doc) {
 
179
    // if we have an owner we rely on it to have it right
 
180
    // otherwise fOwnerNode is our ownerDocument
 
181
    if (!isOwned()) {
 
182
        // revisit.  Problem with storage for doctype nodes that were created
 
183
        //                on the system heap in advance of having a document.
 
184
        fOwnerNode = doc;
 
185
    }
 
186
}
 
187
 
 
188
DOMNode * DOMNodeImpl::getParentNode() const
 
189
{
 
190
    return 0;                // overridden in ChildNode
 
191
}
 
192
 
 
193
 
 
194
DOMNode*  DOMNodeImpl::getPreviousSibling() const
 
195
{
 
196
    return 0;                // overridden in ChildNode
 
197
}
 
198
 
 
199
bool DOMNodeImpl::hasChildNodes() const
 
200
{
 
201
    return false;
 
202
}
 
203
 
 
204
 
 
205
 
 
206
DOMNode *DOMNodeImpl::insertBefore(DOMNode *, DOMNode *) {
 
207
    throw DOMException(DOMException::HIERARCHY_REQUEST_ERR, 0, GetDOMNodeMemoryManager);
 
208
    return 0;
 
209
}
 
210
 
 
211
 
 
212
DOMNode *DOMNodeImpl::removeChild(DOMNode *)
 
213
{
 
214
    throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNodeMemoryManager);
 
215
    return 0;
 
216
}
 
217
 
 
218
 
 
219
DOMNode *DOMNodeImpl::replaceChild(DOMNode *, DOMNode *)
 
220
{
 
221
    throw DOMException(DOMException::HIERARCHY_REQUEST_ERR,0, GetDOMNodeMemoryManager);
 
222
    return 0;
 
223
}
 
224
 
 
225
 
 
226
 
 
227
void DOMNodeImpl::setNodeValue(const XMLCh *)
 
228
{
 
229
    // Default behavior is to do nothing, overridden in some subclasses
 
230
}
 
231
 
 
232
 
 
233
 
 
234
void DOMNodeImpl::setReadOnly(bool readOnl, bool deep)
 
235
{
 
236
    this->isReadOnly(readOnl);
 
237
 
 
238
    if (deep) {
 
239
        for (DOMNode *mykid = castToNode(this)->getFirstChild();
 
240
            mykid != 0;
 
241
            mykid = mykid->getNextSibling()) {
 
242
 
 
243
            short kidNodeType = mykid->getNodeType();
 
244
 
 
245
            switch (kidNodeType) {
 
246
            case DOMNode::ENTITY_REFERENCE_NODE:
 
247
                break;
 
248
            case DOMNode::ELEMENT_NODE:
 
249
                ((DOMElementImpl*) mykid)->setReadOnly(readOnl, true);
 
250
                break;
 
251
            case DOMNode::DOCUMENT_TYPE_NODE:
 
252
               ((DOMDocumentTypeImpl*) mykid)->setReadOnly(readOnl, true);
 
253
               break;
 
254
            default:
 
255
                castToNodeImpl(mykid)->setReadOnly(readOnl, true);
 
256
                break;
 
257
            }
 
258
        }
 
259
    }
 
260
}
 
261
 
 
262
 
 
263
//Introduced in DOM Level 2
 
264
 
 
265
void DOMNodeImpl::normalize()
 
266
{
 
267
    // does nothing by default, overridden by subclasses
 
268
}
 
269
 
 
270
 
 
271
bool DOMNodeImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
 
272
{
 
273
    return DOMImplementation::getImplementation()->hasFeature(feature, version);
 
274
}
 
275
 
 
276
const XMLCh *DOMNodeImpl::getNamespaceURI() const
 
277
{
 
278
    return 0;
 
279
}
 
280
 
 
281
const XMLCh *DOMNodeImpl::getPrefix() const
 
282
{
 
283
    return 0;
 
284
}
 
285
 
 
286
const XMLCh *DOMNodeImpl::getLocalName() const
 
287
{
 
288
    return 0;
 
289
}
 
290
 
 
291
 
 
292
void DOMNodeImpl::setPrefix(const XMLCh *)
 
293
{
 
294
    throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager);
 
295
}
 
296
 
 
297
 
 
298
bool DOMNodeImpl::hasAttributes() const {
 
299
    return 0;                   // overridden in ElementImpl
 
300
}
 
301
 
 
302
 
 
303
 
 
304
 
 
305
 
 
306
const XMLCh *DOMNodeImpl::getXmlString()      {return XMLUni::fgXMLString;}
 
307
const XMLCh *DOMNodeImpl::getXmlURIString()   {return XMLUni::fgXMLURIName;}
 
308
const XMLCh *DOMNodeImpl::getXmlnsString()    {return XMLUni::fgXMLNSString;}
 
309
const XMLCh *DOMNodeImpl::getXmlnsURIString() {return XMLUni::fgXMLNSURIName;}
 
310
 
 
311
//Return a URI mapped from the given prefix and namespaceURI as below
 
312
//    prefix   namespaceURI    output
 
313
//---------------------------------------------------
 
314
//    "xml"     xmlURI          xmlURI
 
315
//    "xml"     otherwise       NAMESPACE_ERR
 
316
//    "xmlns"   xmlnsURI        xmlnsURI (nType = ATTRIBUTE_NODE only)
 
317
//    "xmlns"   otherwise       NAMESPACE_ERR (nType = ATTRIBUTE_NODE only)
 
318
//    != null   null or ""      NAMESPACE_ERR
 
319
//    else      any             namesapceURI
 
320
const XMLCh* DOMNodeImpl::mapPrefix(const XMLCh *prefix,
 
321
                                     const XMLCh *namespaceURI, short nType)
 
322
{
 
323
    if (prefix == 0)
 
324
        return namespaceURI;
 
325
 
 
326
    if (XMLString::equals(prefix, XMLUni::fgXMLString))  {
 
327
        if (XMLString::equals(namespaceURI, XMLUni::fgXMLURIName))
 
328
            return XMLUni::fgXMLURIName;
 
329
        throw DOMException(DOMException::NAMESPACE_ERR, 0);
 
330
    } else if (nType == DOMNode::ATTRIBUTE_NODE && XMLString::equals(prefix, XMLUni::fgXMLNSString)) {
 
331
        if (XMLString::equals(namespaceURI, XMLUni::fgXMLNSURIName))
 
332
            return XMLUni::fgXMLNSURIName;
 
333
        throw DOMException(DOMException::NAMESPACE_ERR, 0);
 
334
    } else if (namespaceURI == 0 || *namespaceURI == 0)
 
335
        throw DOMException(DOMException::NAMESPACE_ERR, 0);
 
336
    return namespaceURI;
 
337
}
 
338
 
 
339
//Introduced in DOM Level 3
 
340
void* DOMNodeImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler)
 
341
{
 
342
   if (!data && !hasUserData())
 
343
       return 0;
 
344
 
 
345
    hasUserData(true);
 
346
    return ((DOMDocumentImpl*)getOwnerDocument())->setUserData(this, key, data, handler);
 
347
}
 
348
 
 
349
void* DOMNodeImpl::getUserData(const XMLCh* key) const
 
350
{
 
351
   if (hasUserData())
 
352
       return ((DOMDocumentImpl*)getOwnerDocument())->getUserData(this, key);
 
353
    return 0;
 
354
}
 
355
 
 
356
void DOMNodeImpl::callUserDataHandlers(DOMUserDataHandler::DOMOperationType operation,
 
357
                                       const DOMNode* src,
 
358
                                       DOMNode* dst) const
 
359
{
 
360
    DOMDocumentImpl* doc=(DOMDocumentImpl*)getOwnerDocument();
 
361
    if (doc)
 
362
        doc->callUserDataHandlers(this, operation, src, dst);
 
363
}
 
364
 
 
365
bool DOMNodeImpl::isSameNode(const DOMNode* other) const
 
366
{
 
367
    return (castToNode(this) == other);
 
368
}
 
369
 
 
370
bool DOMNodeImpl::isEqualNode(const DOMNode* arg) const
 
371
{
 
372
    if (!arg)
 
373
        return false;
 
374
 
 
375
    if (isSameNode(arg)) {
 
376
        return true;
 
377
    }
 
378
 
 
379
    DOMNode* thisNode = castToNode(this);
 
380
 
 
381
    if (arg->getNodeType() != thisNode->getNodeType()) {
 
382
        return false;
 
383
    }
 
384
 
 
385
    // the compareString will check null string as well
 
386
    if (!XMLString::equals(thisNode->getNodeName(), arg->getNodeName())) {
 
387
        return false;
 
388
    }
 
389
 
 
390
    if (!XMLString::equals(thisNode->getLocalName(),arg->getLocalName())) {
 
391
        return false;
 
392
    }
 
393
 
 
394
    if (!XMLString::equals(thisNode->getNamespaceURI(), arg->getNamespaceURI())) {
 
395
        return false;
 
396
    }
 
397
 
 
398
    if (!XMLString::equals(thisNode->getPrefix(), arg->getPrefix())) {
 
399
        return false;
 
400
    }
 
401
 
 
402
    if (!XMLString::equals(thisNode->getNodeValue(), arg->getNodeValue())) {
 
403
        return false;
 
404
    }
 
405
 
 
406
    return true;
 
407
}
 
408
 
 
409
const XMLCh* DOMNodeImpl::lookupPrefix(const XMLCh* namespaceURI) const {
 
410
    // REVISIT: When Namespaces 1.1 comes out this may not be true
 
411
    // Prefix can't be bound to null namespace
 
412
    if (namespaceURI == 0) {
 
413
        return 0;
 
414
    }
 
415
 
 
416
    DOMNode *thisNode = castToNode(this);
 
417
 
 
418
    short type = thisNode->getNodeType();
 
419
 
 
420
    switch (type) {
 
421
    case DOMNode::ELEMENT_NODE: {
 
422
        return lookupPrefix(namespaceURI, (DOMElement*)thisNode);
 
423
    }
 
424
    case DOMNode::DOCUMENT_NODE:{
 
425
        return ((DOMDocument*)thisNode)->getDocumentElement()->lookupPrefix(namespaceURI);
 
426
    }
 
427
 
 
428
    case DOMNode::ENTITY_NODE :
 
429
    case DOMNode::NOTATION_NODE:
 
430
    case DOMNode::DOCUMENT_FRAGMENT_NODE:
 
431
    case DOMNode::DOCUMENT_TYPE_NODE:
 
432
        // type is unknown
 
433
        return 0;
 
434
    case DOMNode::ATTRIBUTE_NODE:{
 
435
        if (fOwnerNode->getNodeType() == DOMNode::ELEMENT_NODE) {
 
436
            return fOwnerNode->lookupPrefix(namespaceURI);
 
437
        }
 
438
        return 0;
 
439
    }
 
440
    default:{
 
441
        DOMNode *ancestor = getElementAncestor(thisNode);
 
442
        if (ancestor != 0) {
 
443
            return ancestor->lookupPrefix(namespaceURI);
 
444
        }
 
445
        return 0;
 
446
    }
 
447
    }
 
448
}
 
449
 
 
450
 
 
451
DOMNode* DOMNodeImpl::getElementAncestor (const DOMNode* currentNode) const {
 
452
    DOMNode* parent = currentNode->getParentNode();
 
453
    while(parent != 0) {
 
454
        short type = parent->getNodeType();
 
455
        if (type == DOMNode::ELEMENT_NODE) {
 
456
            return parent;
 
457
        }
 
458
        parent=parent->getParentNode();
 
459
    }
 
460
    return 0;
 
461
}
 
462
 
 
463
 
 
464
const XMLCh* DOMNodeImpl::lookupPrefix(const XMLCh* const namespaceURI, DOMElement *originalElement) const {
 
465
    DOMNode *thisNode = castToNode(this);
 
466
 
 
467
    const XMLCh* ns = thisNode->getNamespaceURI();
 
468
    // REVISIT: if no prefix is available is it null or empty string, or
 
469
    //          could be both?
 
470
    const XMLCh* prefix = thisNode->getPrefix();
 
471
 
 
472
    if (ns != 0 && XMLString::equals(ns,namespaceURI) && prefix != 0) {
 
473
        const XMLCh* foundNamespace =  originalElement->lookupNamespaceURI(prefix);
 
474
        if (foundNamespace != 0 && XMLString::equals(foundNamespace, namespaceURI)) {
 
475
            return prefix;
 
476
        }
 
477
    }
 
478
    if (thisNode->hasAttributes()) {
 
479
        DOMNamedNodeMap *nodeMap = thisNode->getAttributes();
 
480
 
 
481
        if(nodeMap != 0) {
 
482
            XMLSize_t length = nodeMap->getLength();
 
483
 
 
484
            for (XMLSize_t i = 0;i < length;i++) {
 
485
                DOMNode *attr = nodeMap->item(i);
 
486
                const XMLCh* attrPrefix = attr->getPrefix();
 
487
                const XMLCh* value = attr->getNodeValue();
 
488
 
 
489
                ns = attr->getNamespaceURI();
 
490
 
 
491
                if (ns != 0 && XMLString::equals(ns, XMLUni::fgXMLNSURIName)) {
 
492
                    // DOM Level 2 nodes
 
493
                    if ((attrPrefix != 0 && XMLString::equals(attrPrefix, XMLUni::fgXMLNSString)) &&
 
494
                        XMLString::equals(value, namespaceURI)) {
 
495
                        const XMLCh* localname= attr->getLocalName();
 
496
                        const XMLCh* foundNamespace = originalElement->lookupNamespaceURI(localname);
 
497
                        if (foundNamespace != 0 && XMLString::equals(foundNamespace, namespaceURI)) {
 
498
                            return localname;
 
499
                        }
 
500
                    }
 
501
                }
 
502
            }
 
503
        }
 
504
    }
 
505
    DOMNode *ancestor = getElementAncestor(thisNode);
 
506
    if (ancestor != 0) {
 
507
        return castToNodeImpl(ancestor)->lookupPrefix(namespaceURI, originalElement);
 
508
    }
 
509
    return 0;
 
510
}
 
511
 
 
512
const XMLCh* DOMNodeImpl::lookupNamespaceURI(const XMLCh* specifiedPrefix) const  {
 
513
    DOMNode *thisNode = castToNode(this);
 
514
 
 
515
    short type = thisNode->getNodeType();
 
516
    switch (type) {
 
517
    case DOMNode::ELEMENT_NODE : {
 
518
        const XMLCh* ns = thisNode->getNamespaceURI();
 
519
        const XMLCh* prefix = thisNode->getPrefix();
 
520
        if (ns != 0) {
 
521
            // REVISIT: is it possible that prefix is empty string?
 
522
            if (specifiedPrefix == 0 && prefix == specifiedPrefix) {
 
523
                // looking for default namespace
 
524
                return ns;
 
525
            } else if (prefix != 0 && XMLString::equals(prefix, specifiedPrefix)) {
 
526
                // non default namespace
 
527
                return ns;
 
528
            }
 
529
        }
 
530
        if (thisNode->hasAttributes()) {
 
531
            DOMNamedNodeMap *nodeMap = thisNode->getAttributes();
 
532
            if(nodeMap != 0) {
 
533
                XMLSize_t length = nodeMap->getLength();
 
534
                for (XMLSize_t i = 0;i < length;i++) {
 
535
                    DOMNode *attr = nodeMap->item(i);
 
536
                    const XMLCh *attrPrefix = attr->getPrefix();
 
537
                    const XMLCh *value = attr->getNodeValue();
 
538
                    ns = attr->getNamespaceURI();
 
539
 
 
540
                    if (ns != 0 && XMLString::equals(ns, XMLUni::fgXMLNSURIName)) {
 
541
                        // at this point we are dealing with DOM Level 2 nodes only
 
542
                        if (specifiedPrefix == 0 &&
 
543
                            XMLString::equals(attr->getNodeName(), XMLUni::fgXMLNSString)) {
 
544
                            // default namespace
 
545
                            return value;
 
546
                        } else if (attrPrefix != 0 &&
 
547
                                   XMLString::equals(attrPrefix, XMLUni::fgXMLNSString) &&
 
548
                                   XMLString::equals(attr->getLocalName(), specifiedPrefix)) {
 
549
                            // non default namespace
 
550
                            return value;
 
551
                        }
 
552
                    }
 
553
                }
 
554
            }
 
555
        }
 
556
        DOMNode *ancestor = getElementAncestor(thisNode);
 
557
        if (ancestor != 0) {
 
558
            return ancestor->lookupNamespaceURI(specifiedPrefix);
 
559
        }
 
560
        return 0;
 
561
    }
 
562
    case DOMNode::DOCUMENT_NODE : {
 
563
        return((DOMDocument*)thisNode)->getDocumentElement()->lookupNamespaceURI(specifiedPrefix);
 
564
    }
 
565
    case DOMNode::ENTITY_NODE :
 
566
    case DOMNode::NOTATION_NODE:
 
567
    case DOMNode::DOCUMENT_FRAGMENT_NODE:
 
568
    case DOMNode::DOCUMENT_TYPE_NODE:
 
569
        // type is unknown
 
570
        return 0;
 
571
    case DOMNode::ATTRIBUTE_NODE:{
 
572
        if (fOwnerNode->getNodeType() == DOMNode::ELEMENT_NODE) {
 
573
            return fOwnerNode->lookupNamespaceURI(specifiedPrefix);
 
574
        }
 
575
        return 0;
 
576
    }
 
577
    default:{
 
578
        DOMNode *ancestor = getElementAncestor(castToNode(this));
 
579
        if (ancestor != 0) {
 
580
            return ancestor->lookupNamespaceURI(specifiedPrefix);
 
581
        }
 
582
        return 0;
 
583
    }
 
584
    }
 
585
}
 
586
 
 
587
 
 
588
const XMLCh*     DOMNodeImpl::getBaseURI() const{
 
589
    DOMNode *thisNode = castToNode(this);
 
590
    DOMNode* parent = thisNode->getParentNode();
 
591
    if (parent)
 
592
        return parent->getBaseURI();
 
593
    else
 
594
        return 0;
 
595
}
 
596
 
 
597
const DOMNode*   DOMNodeImpl::getTreeParentNode(const DOMNode* node) const {
 
598
    const DOMNode* parent=node->getParentNode();
 
599
    if(parent)
 
600
        return parent;
 
601
    short nodeType=node->getNodeType();
 
602
    switch(nodeType)
 
603
    {
 
604
    case DOMNode::ATTRIBUTE_NODE: return ((const DOMAttr*)node)->getOwnerElement();
 
605
    case DOMNode::NOTATION_NODE:
 
606
    case DOMNode::ENTITY_NODE:    return node->getOwnerDocument()->getDoctype();
 
607
    }
 
608
    return 0;
 
609
}
 
610
 
 
611
short            DOMNodeImpl::compareDocumentPosition(const DOMNode* other) const {
 
612
    DOMNode* thisNode = castToNode(this);
 
613
 
 
614
    // If the two nodes being compared are the same node, then no flags are set on the return.
 
615
    if (thisNode == other)
 
616
        return 0;
 
617
 
 
618
    //if this is a custom node, we don't really know what to do, just return
 
619
    //user should provide its own compareDocumentPosition logic, and shouldn't reach here
 
620
    if(thisNode->getNodeType() > 12) {
 
621
        return 0;
 
622
    }
 
623
 
 
624
    //if it is a custom node we must ask it for the order
 
625
    if(other->getNodeType() > 12) {
 
626
        return reverseTreeOrderBitPattern(other->compareDocumentPosition(thisNode));
 
627
    }
 
628
 
 
629
    // Otherwise, the order of two nodes is determined by looking for common containers --
 
630
    // containers which contain both. A node directly contains any child nodes.
 
631
    // A node also directly contains any other nodes attached to it such as attributes
 
632
    // contained in an element or entities and notations contained in a document type.
 
633
    // Nodes contained in contained nodes are also contained, but less-directly as
 
634
    // the number of intervening containers increases.
 
635
 
 
636
    // If one of the nodes being compared contains the other node, then the container precedes
 
637
    // the contained node, and reversely the contained node follows the container. For example,
 
638
    // when comparing an element against its own attribute or child, the element node precedes
 
639
    // its attribute node and its child node, which both follow it.
 
640
 
 
641
    const DOMNode* tmpNode;
 
642
    const DOMNode* myRoot = castToNode(this);
 
643
    int myDepth=0;
 
644
    while((tmpNode=getTreeParentNode(myRoot))!=0)
 
645
    {
 
646
        myRoot=tmpNode;
 
647
        if(myRoot==other)
 
648
            return DOMNode::DOCUMENT_POSITION_CONTAINS | DOMNode::DOCUMENT_POSITION_PRECEDING;
 
649
        myDepth++;
 
650
    }
 
651
 
 
652
    const DOMNode* hisRoot = other;
 
653
    int hisDepth=0;
 
654
    while((tmpNode=getTreeParentNode(hisRoot))!=0)
 
655
    {
 
656
        hisRoot=tmpNode;
 
657
        if(hisRoot==thisNode)
 
658
            return DOMNode::DOCUMENT_POSITION_CONTAINED_BY | DOMNode::DOCUMENT_POSITION_FOLLOWING;
 
659
        hisDepth++;
 
660
    }
 
661
 
 
662
    // If there is no common container node, then the order is based upon order between the
 
663
    // root container of each node that is in no container. In this case, the result is
 
664
    // disconnected and implementation-specific. This result is stable as long as these
 
665
    // outer-most containing nodes remain in memory and are not inserted into some other
 
666
    // containing node. This would be the case when the nodes belong to different documents
 
667
    // or fragments, and cloning the document or inserting a fragment might change the order.
 
668
 
 
669
    if(myRoot!=hisRoot)
 
670
        return DOMNode::DOCUMENT_POSITION_DISCONNECTED | DOMNode::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC |
 
671
              (myRoot<hisRoot?DOMNode::DOCUMENT_POSITION_PRECEDING:DOMNode::DOCUMENT_POSITION_FOLLOWING);
 
672
 
 
673
    // If neither of the previous cases apply, then there exists a most-direct container common
 
674
    // to both nodes being compared. In this case, the order is determined based upon the two
 
675
    // determining nodes directly contained in this most-direct common container that either
 
676
    // are or contain the corresponding nodes being compared.
 
677
 
 
678
    // if the two depths are different, go to the same one
 
679
    myRoot = castToNode(this);
 
680
    hisRoot = other;
 
681
    if (myDepth > hisDepth) {
 
682
        for (int i= 0 ; i < myDepth - hisDepth; i++)
 
683
            myRoot = getTreeParentNode(myRoot);
 
684
    }
 
685
    else {
 
686
        for (int i = 0; i < hisDepth - myDepth; i++)
 
687
            hisRoot = getTreeParentNode(hisRoot);
 
688
    }
 
689
 
 
690
    // We now have nodes at the same depth in the tree.  Find a common ancestor.
 
691
    const DOMNode *myNodeP=myRoot;
 
692
        const DOMNode *hisNodeP=hisRoot;
 
693
    while(myRoot!=hisRoot)
 
694
    {
 
695
        myNodeP = myRoot;
 
696
        hisNodeP = hisRoot;
 
697
        myRoot = getTreeParentNode(myRoot);
 
698
        hisRoot = getTreeParentNode(hisRoot);
 
699
    }
 
700
 
 
701
    short myNodeType=myNodeP->getNodeType();
 
702
    short hisNodeType=hisNodeP->getNodeType();
 
703
    bool bMyNodeIsChild=(myNodeType!=DOMNode::ATTRIBUTE_NODE && myNodeType!=DOMNode::ENTITY_NODE && myNodeType!=DOMNode::NOTATION_NODE);
 
704
    bool bHisNodeIsChild=(hisNodeType!=DOMNode::ATTRIBUTE_NODE && hisNodeType!=DOMNode::ENTITY_NODE && hisNodeType!=DOMNode::NOTATION_NODE);
 
705
 
 
706
    // If these two determining nodes are both child nodes, then the natural DOM order of these
 
707
    // determining nodes within the containing node is returned as the order of the corresponding nodes.
 
708
    // This would be the case, for example, when comparing two child elements of the same element.
 
709
    if(bMyNodeIsChild && bHisNodeIsChild)
 
710
    {
 
711
        while(myNodeP != 0)
 
712
        {
 
713
            myNodeP = myNodeP->getNextSibling();
 
714
            if(myNodeP == hisNodeP)
 
715
                return DOMNode::DOCUMENT_POSITION_FOLLOWING;
 
716
        }
 
717
        return DOMNode::DOCUMENT_POSITION_PRECEDING;
 
718
    }
 
719
 
 
720
    // If one of the two determining nodes is a child node and the other is not, then the corresponding
 
721
    // node of the child node follows the corresponding node of the non-child node. This would be the case,
 
722
    // for example, when comparing an attribute of an element with a child element of the same element.
 
723
    else if(!bMyNodeIsChild && bHisNodeIsChild)
 
724
        return DOMNode::DOCUMENT_POSITION_FOLLOWING;
 
725
    else if(bMyNodeIsChild && !bHisNodeIsChild)
 
726
        return DOMNode::DOCUMENT_POSITION_PRECEDING;
 
727
 
 
728
    else
 
729
    {
 
730
        // If neither of the two determining node is a child node and one determining node has a greater value
 
731
        // of nodeType than the other, then the corresponding node precedes the other. This would be the case,
 
732
        // for example, when comparing an entity of a document type against a notation of the same document type.
 
733
        if(myNodeType!=hisNodeType)
 
734
            return (myNodeType<hisNodeType)?DOMNode::DOCUMENT_POSITION_FOLLOWING:DOMNode::DOCUMENT_POSITION_PRECEDING;
 
735
 
 
736
        // If neither of the two determining node is a child node and nodeType is the same for both determining
 
737
        // nodes, then an implementation-dependent order between the determining nodes is returned. This order
 
738
        // is stable as long as no nodes of the same nodeType are inserted into or removed from the direct container.
 
739
        // This would be the case, for example, when comparing two attributes of the same element, and inserting
 
740
        // or removing additional attributes might change the order between existing attributes.
 
741
        return DOMNode::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | ((myNodeP<hisNodeP)?DOMNode::DOCUMENT_POSITION_FOLLOWING:DOMNode::DOCUMENT_POSITION_PRECEDING);
 
742
    }
 
743
    // REVISIT:  shouldn't get here.   Should probably throw an
 
744
    // exception
 
745
    return 0;
 
746
}
 
747
 
 
748
short DOMNodeImpl::reverseTreeOrderBitPattern(short pattern) const {
 
749
 
 
750
    if(pattern & DOMNode::DOCUMENT_POSITION_PRECEDING) {
 
751
        pattern &= !DOMNode::DOCUMENT_POSITION_PRECEDING;
 
752
        pattern |= DOMNode::DOCUMENT_POSITION_FOLLOWING;
 
753
    }
 
754
    else if(pattern & DOMNode::DOCUMENT_POSITION_FOLLOWING) {
 
755
        pattern &= !DOMNode::DOCUMENT_POSITION_FOLLOWING;
 
756
        pattern |= DOMNode::DOCUMENT_POSITION_PRECEDING;
 
757
    }
 
758
 
 
759
    if(pattern & DOMNode::DOCUMENT_POSITION_CONTAINED_BY) {
 
760
        pattern &= !DOMNode::DOCUMENT_POSITION_CONTAINED_BY;
 
761
        pattern |= DOMNode::DOCUMENT_POSITION_CONTAINS;
 
762
    }
 
763
    else if(pattern & DOMNode::DOCUMENT_POSITION_CONTAINS) {
 
764
        pattern &= !DOMNode::DOCUMENT_POSITION_CONTAINS;
 
765
        pattern |= DOMNode::DOCUMENT_POSITION_CONTAINED_BY;
 
766
    }
 
767
 
 
768
    return pattern;
 
769
}
 
770
 
 
771
/***
 
772
 *
 
773
 *   Excerpt from http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/core.html#Node3-textContent
 
774
 *
 
775
 *   textContent of type DOMString, introduced in DOM Level 3
 
776
 *
 
777
 *   This attribute returns the text content of this node and its descendants. When it is defined
 
778
 *   to be null, setting it has no effect.
 
779
 *
 
780
 *   When set, any possible children this node may have are removed and replaced by a single Text node
 
781
 *   containing the string this attribute is set to.
 
782
 *
 
783
 *   On getting, no serialization is performed, the returned string does not contain any markup.
 
784
 *   No whitespace normalization is performed, the returned string does not contain the element content
 
785
 *   whitespaces Fundamental Interfaces.
 
786
 *
 
787
 *   Similarly, on setting, no parsing is performed either, the input string is taken as pure textual content.
 
788
 *
 
789
 *   The string returned is made of the text content of this node depending on its type,
 
790
 *   as defined below:
 
791
 *
 
792
 *       Node type                                           Content
 
793
 *   ====================       ========================================================================
 
794
 *     ELEMENT_NODE               concatenation of the textContent attribute value of every child node,
 
795
 *     ENTITY_NODE                            excluding COMMENT_NODE and PROCESSING_INSTRUCTION_NODE nodes.
 
796
 *     ENTITY_REFERENCE_NODE      This is the empty string if the node has no children.
 
797
 *     DOCUMENT_FRAGMENT_NODE
 
798
 *    --------------------------------------------------------------------------------------------------
 
799
 *     ATTRIBUTE_NODE
 
800
 *     TEXT_NODE
 
801
 *     CDATA_SECTION_NODE
 
802
 *     COMMENT_NODE,
 
803
 *     PROCESSING_INSTRUCTION_NODE   nodeValue
 
804
 *    --------------------------------------------------------------------------------------------------
 
805
 *     DOCUMENT_NODE,
 
806
 *     DOCUMENT_TYPE_NODE,
 
807
 *     NOTATION_NODE                 null
 
808
 *
 
809
 ***/
 
810
 
 
811
const XMLCh*     DOMNodeImpl::getTextContent() const
 
812
{
 
813
        XMLSize_t nBufferLength = 0;
 
814
 
 
815
        getTextContent(NULL, nBufferLength);
 
816
        XMLCh* pzBuffer = (XMLCh*)((DOMDocumentImpl*)getOwnerDocument())->allocate((nBufferLength+1) * sizeof(XMLCh));
 
817
        getTextContent(pzBuffer, nBufferLength);
 
818
        pzBuffer[nBufferLength] = 0;
 
819
 
 
820
        return pzBuffer;
 
821
 
 
822
}
 
823
 
 
824
const XMLCh*    DOMNodeImpl::getTextContent(XMLCh* pzBuffer, XMLSize_t& rnBufferLength) const
 
825
{
 
826
        XMLSize_t nRemainingBuffer = rnBufferLength;
 
827
        rnBufferLength = 0;
 
828
 
 
829
        if (pzBuffer)
 
830
                *pzBuffer = 0;
 
831
 
 
832
        DOMNode *thisNode = castToNode(this);
 
833
 
 
834
        switch (thisNode->getNodeType())
 
835
        {
 
836
        case DOMNode::ELEMENT_NODE:
 
837
    case DOMNode::ENTITY_NODE:
 
838
    case DOMNode::ENTITY_REFERENCE_NODE:
 
839
    case DOMNode::DOCUMENT_FRAGMENT_NODE:
 
840
    {
 
841
                DOMNode* current = thisNode->getFirstChild();
 
842
 
 
843
                while (current != NULL)
 
844
                {
 
845
                        if (current->getNodeType() != DOMNode::COMMENT_NODE &&
 
846
                                current->getNodeType() != DOMNode::PROCESSING_INSTRUCTION_NODE)
 
847
                        {
 
848
 
 
849
                                if (pzBuffer)
 
850
                                {
 
851
                                        XMLSize_t nContentLength = nRemainingBuffer;
 
852
                                        castToNodeImpl(current)->getTextContent(pzBuffer + rnBufferLength, nContentLength);
 
853
                                        rnBufferLength += nContentLength;
 
854
                                        nRemainingBuffer -= nContentLength;
 
855
                                }
 
856
                                else
 
857
                                {
 
858
                                        XMLSize_t nContentLength = 0;
 
859
                                        castToNodeImpl(current)->getTextContent(NULL, nContentLength);
 
860
                                        rnBufferLength += nContentLength;
 
861
                                }
 
862
                        }
 
863
 
 
864
                        current = current->getNextSibling();
 
865
 
 
866
                }
 
867
    }
 
868
 
 
869
    break;
 
870
 
 
871
    case DOMNode::ATTRIBUTE_NODE:
 
872
    case DOMNode::TEXT_NODE:
 
873
    case DOMNode::CDATA_SECTION_NODE:
 
874
    case DOMNode::COMMENT_NODE:
 
875
    case DOMNode::PROCESSING_INSTRUCTION_NODE:
 
876
    {
 
877
                const XMLCh* pzValue = thisNode->getNodeValue();
 
878
                XMLSize_t nStrLen = XMLString::stringLen(pzValue);
 
879
 
 
880
                if (pzBuffer)
 
881
                {
 
882
                        XMLSize_t nContentLength = (nRemainingBuffer >= nStrLen) ? nStrLen : nRemainingBuffer;
 
883
                        XMLString::copyNString(pzBuffer + rnBufferLength, pzValue, nContentLength);
 
884
                        rnBufferLength += nContentLength;
 
885
                        nRemainingBuffer -= nContentLength;
 
886
                }
 
887
                else
 
888
                {
 
889
                        rnBufferLength += nStrLen;
 
890
                }
 
891
 
 
892
    }
 
893
 
 
894
    break;
 
895
 
 
896
        /***
 
897
         DOCUMENT_NODE
 
898
                 DOCUMENT_TYPE_NODE
 
899
                 NOTATION_NODE
 
900
        ***/
 
901
        default:
 
902
 
 
903
                break;
 
904
        }
 
905
 
 
906
        return pzBuffer;
 
907
 
 
908
}
 
909
 
 
910
void DOMNodeImpl::setTextContent(const XMLCh* textContent){
 
911
    DOMNode *thisNode = castToNode(this);
 
912
    switch (thisNode->getNodeType())
 
913
    {
 
914
        case DOMNode::ELEMENT_NODE:
 
915
        case DOMNode::ENTITY_NODE:
 
916
        case DOMNode::ENTITY_REFERENCE_NODE:
 
917
        case DOMNode::DOCUMENT_FRAGMENT_NODE:
 
918
            {
 
919
                if (isReadOnly())
 
920
                  throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
 
921
 
 
922
                // Remove all childs
 
923
                DOMNode* current = thisNode->getFirstChild();
 
924
                while (current != NULL)
 
925
                {
 
926
                    thisNode->removeChild(current);
 
927
                    current = thisNode->getFirstChild();
 
928
                }
 
929
                if (textContent != NULL)
 
930
                {
 
931
                    // Add textnode containing data
 
932
                    current = ((DOMDocumentImpl*)thisNode->getOwnerDocument())->createTextNode(textContent);
 
933
                    thisNode->appendChild(current);
 
934
                }
 
935
            }
 
936
            break;
 
937
 
 
938
        case DOMNode::ATTRIBUTE_NODE:
 
939
        case DOMNode::TEXT_NODE:
 
940
        case DOMNode::CDATA_SECTION_NODE:
 
941
        case DOMNode::COMMENT_NODE:
 
942
        case DOMNode::PROCESSING_INSTRUCTION_NODE:
 
943
            if (isReadOnly())
 
944
                throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
 
945
 
 
946
            thisNode->setNodeValue(textContent);
 
947
            break;
 
948
 
 
949
        case DOMNode::DOCUMENT_NODE:
 
950
        case DOMNode::DOCUMENT_TYPE_NODE:
 
951
        case DOMNode::NOTATION_NODE:
 
952
            break;
 
953
 
 
954
        default:
 
955
            throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, GetDOMNodeMemoryManager);
 
956
    }
 
957
}
 
958
 
 
959
 
 
960
bool DOMNodeImpl::isDefaultNamespace(const XMLCh* namespaceURI) const{
 
961
        DOMNode *thisNode = castToNode(this);
 
962
    short type = thisNode->getNodeType();
 
963
    switch (type) {
 
964
    case DOMNode::ELEMENT_NODE: {
 
965
        const XMLCh *prefix = thisNode->getPrefix();
 
966
 
 
967
        // REVISIT: is it possible that prefix is empty string?
 
968
        if (prefix == 0 || !*prefix) {
 
969
            return XMLString::equals(namespaceURI, thisNode->getNamespaceURI());
 
970
        }
 
971
 
 
972
        if (thisNode->hasAttributes()) {
 
973
            DOMElement *elem = (DOMElement *)thisNode;
 
974
            DOMNode *attr = elem->getAttributeNodeNS(XMLUni::fgXMLNSURIName, XMLUni::fgXMLNSString);
 
975
            if (attr != 0) {
 
976
                const XMLCh *value = attr->getNodeValue();
 
977
                return XMLString::equals(namespaceURI, value);
 
978
            }
 
979
        }
 
980
        DOMNode *ancestor = getElementAncestor(thisNode);
 
981
        if (ancestor != 0) {
 
982
            return ancestor->isDefaultNamespace(namespaceURI);
 
983
        }
 
984
 
 
985
        return false;
 
986
    }
 
987
    case DOMNode::DOCUMENT_NODE:{
 
988
        return ((DOMDocument*)thisNode)->getDocumentElement()->isDefaultNamespace(namespaceURI);
 
989
    }
 
990
 
 
991
    case DOMNode::ENTITY_NODE :
 
992
    case DOMNode::NOTATION_NODE:
 
993
    case DOMNode::DOCUMENT_FRAGMENT_NODE:
 
994
    case DOMNode::DOCUMENT_TYPE_NODE:
 
995
        // type is unknown
 
996
        return false;
 
997
    case DOMNode::ATTRIBUTE_NODE:{
 
998
        if (fOwnerNode->getNodeType() == DOMNode::ELEMENT_NODE) {
 
999
            return fOwnerNode->isDefaultNamespace(namespaceURI);
 
1000
 
 
1001
        }
 
1002
        return false;
 
1003
    }
 
1004
    default:{
 
1005
        DOMNode *ancestor = getElementAncestor(thisNode);
 
1006
        if (ancestor != 0) {
 
1007
            return ancestor->isDefaultNamespace(namespaceURI);
 
1008
        }
 
1009
        return false;
 
1010
    }
 
1011
 
 
1012
    }
 
1013
}
 
1014
 
 
1015
void* DOMNodeImpl::getFeature(const XMLCh*, const XMLCh*) const {
 
1016
    return 0;
 
1017
}
 
1018
 
 
1019
 
 
1020
// non-standard extension
 
1021
void DOMNodeImpl::release()
 
1022
{
 
1023
    // shouldn't reach here
 
1024
    throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager);
 
1025
}
 
1026
 
 
1027
XERCES_CPP_NAMESPACE_END
 
1028