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 "DOMCDATASectionImpl.hpp"
#include "DOMNodeImpl.hpp"
#include "DOMRangeImpl.hpp"
#include "DOMCasts.hpp"
#include "DOMStringPool.hpp"
#include <xercesc/dom/DOMException.hpp>
#include <xercesc/dom/DOMNodeFilter.hpp>
#include <xercesc/dom/DOMTreeWalker.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
DOMCDATASectionImpl::DOMCDATASectionImpl(DOMDocument *ownerDoc,
const XMLCh *dat)
: fNode(ownerDoc), fCharacterData(ownerDoc, dat)
{
fNode.setIsLeafNode(true);
David Abram Cargill
committed
}
DOMCDATASectionImpl::DOMCDATASectionImpl(const DOMCDATASectionImpl &other, bool /*deep*/)
: DOMCDATASection(other),
fNode(*castToNodeImpl(&other)),
fChild(*castToChildImpl(&other)),
fCharacterData(other.fCharacterData)
{
David Abram Cargill
committed
}
DOMCDATASectionImpl::~DOMCDATASectionImpl()
{
David Abram Cargill
committed
}
DOMNode *DOMCDATASectionImpl::cloneNode(bool deep) const
{
Alberto Massari
committed
DOMNode* newNode = new (this->getOwnerDocument(), DOMMemoryManager::CDATA_SECTION_OBJECT) DOMCDATASectionImpl(*this, deep);
fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode);
return newNode;
David Abram Cargill
committed
}
const XMLCh * DOMCDATASectionImpl::getNodeName() const {
static const XMLCh gcdata_section[] = {chPound, chLatin_c, chLatin_d, chLatin_a, chLatin_t, chLatin_a,
chDash, chLatin_s, chLatin_e, chLatin_c, chLatin_t, chLatin_i, chLatin_o, chLatin_n, 0};
return gcdata_section;
David Abram Cargill
committed
}
short DOMCDATASectionImpl::getNodeType() const {
return DOMNode::CDATA_SECTION_NODE;
David Abram Cargill
committed
}
bool DOMCDATASectionImpl::isIgnorableWhitespace() const
{
return fNode.ignorableWhitespace();
}
//
// splitText. revist - factor into a common function for use
// here and in DOMTextImpl
//
DOMText *DOMCDATASectionImpl::splitText(XMLSize_t offset)
{
if (fNode.isReadOnly())
{
throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
}
XMLSize_t len = fCharacterData.fDataBuf->getLen();
throw DOMException(DOMException::INDEX_SIZE_ERR, 0, GetDOMNodeMemoryManager);
DOMText *newText =
getOwnerDocument()->createCDATASection(
this->substringData(offset, len - offset));
DOMNode *parent = getParentNode();
if (parent != 0)
parent->insertBefore(newText, getNextSibling());
fCharacterData.fDataBuf->chop(offset);
if (this->getOwnerDocument() != 0) {
Ranges* ranges = ((DOMDocumentImpl *)this->getOwnerDocument())->getRanges();
if (ranges != 0) {
XMLSize_t sz = ranges->size();
if (sz != 0) {
for (XMLSize_t i =0; i<sz; i++) {
ranges->elementAt(i)->updateSplitInfo( this, newText, offset);
}
}
}
}
return newText;
David Abram Cargill
committed
}
bool DOMCDATASectionImpl::getIsElementContentWhitespace() const
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
const XMLCh* DOMCDATASectionImpl::getWholeText() const
{
DOMTreeWalker* pWalker=getOwnerDocument()->createTreeWalker(getOwnerDocument()->getDocumentElement(), DOMNodeFilter::SHOW_ALL, NULL, true);
pWalker->setCurrentNode((DOMNode*)this);
// Logically-adjacent text nodes are Text or CDATASection nodes that can be visited sequentially in document order or in
// reversed document order without entering, exiting, or passing over Element, Comment, or ProcessingInstruction nodes.
while(true)
{
DOMNode* prevNode=pWalker->previousNode();
if(prevNode==NULL || prevNode->getNodeType()==ELEMENT_NODE || prevNode->getNodeType()==COMMENT_NODE || prevNode->getNodeType()==PROCESSING_INSTRUCTION_NODE)
break;
}
XMLBuffer buff(1023, GetDOMNodeMemoryManager);
while(true)
{
DOMNode* nextNode=pWalker->nextNode();
if(nextNode==NULL || nextNode->getNodeType()==ELEMENT_NODE || nextNode->getNodeType()==COMMENT_NODE || nextNode->getNodeType()==PROCESSING_INSTRUCTION_NODE)
break;
if(nextNode->getNodeType()==TEXT_NODE || nextNode->getNodeType()==CDATA_SECTION_NODE)
buff.append(nextNode->getNodeValue());
}
pWalker->release();
XMLCh* wholeString = (XMLCh*) (GetDOMNodeMemoryManager->allocate((buff.getLen()+1)*sizeof(XMLCh)));
XMLString::copyString(wholeString, buff.getRawBuffer());
return wholeString;
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
DOMText* DOMCDATASectionImpl::replaceWholeText(const XMLCh* newText)
{
DOMTreeWalker* pWalker=getOwnerDocument()->createTreeWalker(getOwnerDocument()->getDocumentElement(), DOMNodeFilter::SHOW_ALL, NULL, true);
pWalker->setCurrentNode((DOMNode*)this);
// Logically-adjacent text nodes are Text or CDATASection nodes that can be visited sequentially in document order or in
// reversed document order without entering, exiting, or passing over Element, Comment, or ProcessingInstruction nodes.
DOMNode* pFirstTextNode=this;
while(true)
{
DOMNode* prevNode=pWalker->previousNode();
if(prevNode==NULL || prevNode->getNodeType()==ELEMENT_NODE || prevNode->getNodeType()==COMMENT_NODE || prevNode->getNodeType()==PROCESSING_INSTRUCTION_NODE)
break;
pFirstTextNode=prevNode;
}
// before doing any change we need to check if we are going to remove an entity reference that doesn't contain just text
DOMNode* pCurrentNode=pWalker->getCurrentNode();
while(true)
{
DOMNode* nextNode=pWalker->nextNode();
if(nextNode==NULL || nextNode->getNodeType()==ELEMENT_NODE || nextNode->getNodeType()==COMMENT_NODE || nextNode->getNodeType()==PROCESSING_INSTRUCTION_NODE)
break;
if(nextNode->getNodeType()==ENTITY_REFERENCE_NODE)
{
DOMTreeWalker* pInnerWalker=getOwnerDocument()->createTreeWalker(nextNode, DOMNodeFilter::SHOW_ALL, NULL, true);
while(pInnerWalker->nextNode())
{
short nodeType=pInnerWalker->getCurrentNode()->getNodeType();
if(nodeType!=ENTITY_REFERENCE_NODE && nodeType!=TEXT_NODE && nodeType!=CDATA_SECTION_NODE)
throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
}
pInnerWalker->release();
}
}
DOMText* retVal=NULL;
// if the first node in the chain is a text node, replace its content, otherwise create a new node
if(newText && *newText)
{
if(!castToNodeImpl(pFirstTextNode)->isReadOnly() && (pFirstTextNode->getNodeType()==TEXT_NODE || pFirstTextNode->getNodeType()==CDATA_SECTION_NODE))
{
pFirstTextNode->setNodeValue(newText);
retVal=(DOMText*)pFirstTextNode;
}
else
{
if(getNodeType()==TEXT_NODE)
retVal=getOwnerDocument()->createTextNode(newText);
else
retVal=getOwnerDocument()->createCDATASection(newText);
pFirstTextNode->getParentNode()->insertBefore(retVal, pFirstTextNode);
}
}
// now delete all the following text nodes
pWalker->setCurrentNode(pCurrentNode);
while(true)
{
DOMNode* nextNode=pWalker->nextNode();
if(nextNode==NULL || nextNode->getNodeType()==ELEMENT_NODE || nextNode->getNodeType()==COMMENT_NODE || nextNode->getNodeType()==PROCESSING_INSTRUCTION_NODE)
break;
if(nextNode!=retVal)
{
// keep the tree walker valid
pWalker->previousNode();
nextNode->getParentNode()->removeChild(nextNode);
nextNode->release();
}
}
pWalker->release();
return retVal;
void DOMCDATASectionImpl::release()
{
if (fNode.isOwned() && !fNode.isToBeReleased())
throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager);
DOMDocumentImpl* doc = (DOMDocumentImpl*) getOwnerDocument();
fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0);
fCharacterData.releaseBuffer();
Alberto Massari
committed
doc->release(this, DOMMemoryManager::CDATA_SECTION_OBJECT);
throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager);
//
// Delegation stubs for other DOM_Node inherited functions.
//
DOMNode* DOMCDATASectionImpl::appendChild(DOMNode *newChild) {return fNode.appendChild (newChild); }
David Abram Cargill
committed
DOMNamedNodeMap* DOMCDATASectionImpl::getAttributes() const {return fNode.getAttributes (); }
DOMNodeList* DOMCDATASectionImpl::getChildNodes() const {return fNode.getChildNodes (); }
DOMNode* DOMCDATASectionImpl::getFirstChild() const {return fNode.getFirstChild (); }
DOMNode* DOMCDATASectionImpl::getLastChild() const {return fNode.getLastChild (); }
David Abram Cargill
committed
const XMLCh* DOMCDATASectionImpl::getLocalName() const {return fNode.getLocalName (); }
const XMLCh* DOMCDATASectionImpl::getNamespaceURI() const {return fNode.getNamespaceURI (); }
DOMNode* DOMCDATASectionImpl::getNextSibling() const {return fChild.getNextSibling (); }
const XMLCh* DOMCDATASectionImpl::getNodeValue() const {return fCharacterData.getNodeValue (); }
DOMDocument* DOMCDATASectionImpl::getOwnerDocument() const {return fNode.getOwnerDocument(); }
David Abram Cargill
committed
const XMLCh* DOMCDATASectionImpl::getPrefix() const {return fNode.getPrefix (); }
DOMNode* DOMCDATASectionImpl::getParentNode() const {return fChild.getParentNode (this); }
DOMNode* DOMCDATASectionImpl::getPreviousSibling() const {return fChild.getPreviousSibling (this); }
bool DOMCDATASectionImpl::hasChildNodes() const {return fNode.hasChildNodes (); }
DOMNode* DOMCDATASectionImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
{return fNode.insertBefore (newChild, refChild); }
David Abram Cargill
committed
void DOMCDATASectionImpl::normalize() {fNode.normalize (); }
DOMNode* DOMCDATASectionImpl::removeChild(DOMNode *oldChild) {return fNode.removeChild (oldChild); }
DOMNode* DOMCDATASectionImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
{return fNode.replaceChild (newChild, oldChild); }
bool DOMCDATASectionImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
David Abram Cargill
committed
{return fNode.isSupported (feature, version); }
void DOMCDATASectionImpl::setPrefix(const XMLCh *prefix) {fNode.setPrefix(prefix); }
bool DOMCDATASectionImpl::hasAttributes() const {return fNode.hasAttributes(); }
bool DOMCDATASectionImpl::isSameNode(const DOMNode* other) const {return fNode.isSameNode(other); }
bool DOMCDATASectionImpl::isEqualNode(const DOMNode* arg) const {return fNode.isEqualNode(arg); }
void* DOMCDATASectionImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler)
David Abram Cargill
committed
{return fNode.setUserData(key, data, handler); }
void* DOMCDATASectionImpl::getUserData(const XMLCh* key) const {return fNode.getUserData(key); }
const XMLCh* DOMCDATASectionImpl::getBaseURI() const {return fNode.getBaseURI(); }
short DOMCDATASectionImpl::compareDocumentPosition(const DOMNode* other) const {return fNode.compareDocumentPosition(other); }
David Abram Cargill
committed
const XMLCh* DOMCDATASectionImpl::getTextContent() const {return fNode.getTextContent(); }
void DOMCDATASectionImpl::setTextContent(const XMLCh* textContent){fNode.setTextContent(textContent); }
const XMLCh* DOMCDATASectionImpl::lookupPrefix(const XMLCh* namespaceURI) const {return fNode.lookupPrefix(namespaceURI); }
David Abram Cargill
committed
bool DOMCDATASectionImpl::isDefaultNamespace(const XMLCh* namespaceURI) const {return fNode.isDefaultNamespace(namespaceURI); }
const XMLCh* DOMCDATASectionImpl::lookupNamespaceURI(const XMLCh* prefix) const {return fNode.lookupNamespaceURI(prefix); }
void* DOMCDATASectionImpl::getFeature(const XMLCh* feature, const XMLCh* version) const {return fNode.getFeature(feature, version); }
//
// Delegation of CharacerData functions.
//
David Abram Cargill
committed
const XMLCh* DOMCDATASectionImpl::getData() const {return fCharacterData.getData();}
XMLSize_t DOMCDATASectionImpl::getLength() const {return fCharacterData.getLength();}
const XMLCh* DOMCDATASectionImpl::substringData(XMLSize_t offset, XMLSize_t count) const
David Abram Cargill
committed
{return fCharacterData.substringData(this, offset, count);}
void DOMCDATASectionImpl::appendData(const XMLCh *arg) {fCharacterData.appendData(this, arg);}
void DOMCDATASectionImpl::insertData(XMLSize_t offset, const XMLCh *arg)
David Abram Cargill
committed
{fCharacterData.insertData(this, offset, arg);}
void DOMCDATASectionImpl::deleteData(XMLSize_t offset, XMLSize_t count)
David Abram Cargill
committed
{fCharacterData.deleteData(this, offset, count);}
void DOMCDATASectionImpl::replaceData(XMLSize_t offset, XMLSize_t count, const XMLCh *arg)
David Abram Cargill
committed
{fCharacterData.replaceData(this, offset, count, arg);}
void DOMCDATASectionImpl::setData(const XMLCh *data) {fCharacterData.setData(this, data);}
void DOMCDATASectionImpl::setNodeValue(const XMLCh *nodeValue) {fCharacterData.setNodeValue (this, nodeValue); }