1//
2// Document.cpp
3//
4// Library: XML
5// Package: DOM
6// Module: DOM
7//
8// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
9// and Contributors.
10//
11// SPDX-License-Identifier: BSL-1.0
12//
13
14
15#include "Poco/DOM/Document.h"
16#include "Poco/DOM/DocumentType.h"
17#include "Poco/DOM/DOMImplementation.h"
18#include "Poco/DOM/Element.h"
19#include "Poco/DOM/Attr.h"
20#include "Poco/DOM/DocumentFragment.h"
21#include "Poco/DOM/Text.h"
22#include "Poco/DOM/Comment.h"
23#include "Poco/DOM/CDATASection.h"
24#include "Poco/DOM/ProcessingInstruction.h"
25#include "Poco/DOM/EntityReference.h"
26#include "Poco/DOM/DOMException.h"
27#include "Poco/DOM/ElementsByTagNameList.h"
28#include "Poco/DOM/Entity.h"
29#include "Poco/DOM/Notation.h"
30#include "Poco/XML/Name.h"
31#include "Poco/XML/NamePool.h"
32
33
34namespace Poco {
35namespace XML {
36
37
38const XMLString Document::NODE_NAME = toXMLString("#document");
39
40
41Document::Document(NamePool* pNamePool):
42 AbstractContainerNode(0),
43 _pDocumentType(0),
44 _eventSuspendLevel(0)
45{
46 if (pNamePool)
47 {
48 _pNamePool = pNamePool;
49 _pNamePool->duplicate();
50 }
51 else
52 {
53 _pNamePool = new NamePool;
54 }
55}
56
57
58Document::Document(unsigned long namePoolSize):
59 AbstractContainerNode(0),
60 _pDocumentType(0),
61 _pNamePool(new NamePool(namePoolSize)),
62 _eventSuspendLevel(0)
63{
64}
65
66
67Document::Document(DocumentType* pDocumentType, NamePool* pNamePool):
68 AbstractContainerNode(0),
69 _pDocumentType(pDocumentType),
70 _eventSuspendLevel(0)
71{
72 if (pNamePool)
73 {
74 _pNamePool = pNamePool;
75 _pNamePool->duplicate();
76 }
77 else
78 {
79 _pNamePool = new NamePool;
80 }
81 if (_pDocumentType)
82 {
83 _pDocumentType->duplicate();
84 _pDocumentType->setOwnerDocument(this);
85 }
86}
87
88
89Document::Document(DocumentType* pDocumentType, unsigned long namePoolSize):
90 AbstractContainerNode(0),
91 _pDocumentType(pDocumentType),
92 _pNamePool(new NamePool(namePoolSize)),
93 _eventSuspendLevel(0)
94{
95 if (_pDocumentType)
96 {
97 _pDocumentType->duplicate();
98 _pDocumentType->setOwnerDocument(this);
99 }
100}
101
102
103Document::~Document()
104{
105 if (_pDocumentType) _pDocumentType->release();
106 _pNamePool->release();
107}
108
109
110bool Document::dispatchEvent(Event* evt)
111{
112 return _eventSuspendLevel > 0 || AbstractContainerNode::dispatchEvent(evt);
113}
114
115
116void Document::collectGarbage()
117{
118 _autoReleasePool.release();
119}
120
121
122void Document::suspendEvents()
123{
124 ++_eventSuspendLevel;
125}
126
127
128void Document::resumeEvents()
129{
130 poco_assert_dbg (_eventSuspendLevel > 0);
131
132 --_eventSuspendLevel;
133}
134
135
136const DOMImplementation& Document::implementation() const
137{
138 return DOMImplementation::instance();
139}
140
141
142Element* Document::documentElement() const
143{
144 // Skip non-element nodes before the document element
145 Node* pCur = firstChild();
146 while (pCur)
147 {
148 if (dynamic_cast<Element*>(pCur))
149 return static_cast<Element*>(pCur);
150 pCur = pCur->nextSibling();
151 }
152 return 0;
153}
154
155
156Element* Document::createElement(const XMLString& tagName) const
157{
158 return new Element(const_cast<Document*>(this), EMPTY_STRING, EMPTY_STRING, tagName);
159}
160
161
162DocumentFragment* Document::createDocumentFragment() const
163{
164 return new DocumentFragment(const_cast<Document*>(this));
165}
166
167
168Text* Document::createTextNode(const XMLString& data) const
169{
170 return new Text(const_cast<Document*>(this), data);
171}
172
173
174Comment* Document::createComment(const XMLString& data) const
175{
176 return new Comment(const_cast<Document*>(this), data);
177}
178
179
180CDATASection* Document::createCDATASection(const XMLString& data) const
181{
182 return new CDATASection(const_cast<Document*>(this), data);
183}
184
185
186ProcessingInstruction* Document::createProcessingInstruction(const XMLString& target, const XMLString& data) const
187{
188 return new ProcessingInstruction(const_cast<Document*>(this), target, data);
189}
190
191
192Attr* Document::createAttribute(const XMLString& name) const
193{
194 return new Attr(const_cast<Document*>(this), 0, EMPTY_STRING, EMPTY_STRING, name, EMPTY_STRING);
195}
196
197
198EntityReference* Document::createEntityReference(const XMLString& name) const
199{
200 return new EntityReference(const_cast<Document*>(this), name);
201}
202
203
204NodeList* Document::getElementsByTagName(const XMLString& name) const
205{
206 return new ElementsByTagNameList(const_cast<Document*>(this), name);
207}
208
209
210const XMLString& Document::nodeName() const
211{
212 return NODE_NAME;
213}
214
215
216unsigned short Document::nodeType() const
217{
218 return Node::DOCUMENT_NODE;
219}
220
221
222Node* Document::importNode(Node* importedNode, bool deep)
223{
224 return static_cast<AbstractNode*>(importedNode)->copyNode(deep, this);
225}
226
227
228Element* Document::createElementNS(const XMLString& namespaceURI, const XMLString& qualifiedName) const
229{
230 return new Element(const_cast<Document*>(this), namespaceURI, Name::localName(qualifiedName), qualifiedName);
231}
232
233
234Attr* Document::createAttributeNS(const XMLString& namespaceURI, const XMLString& qualifiedName) const
235{
236 return new Attr(const_cast<Document*>(this), 0, namespaceURI, Name::localName(qualifiedName), qualifiedName, EMPTY_STRING);
237}
238
239
240NodeList* Document::getElementsByTagNameNS(const XMLString& namespaceURI, const XMLString& localName) const
241{
242 return new ElementsByTagNameListNS(const_cast<Document*>(this), namespaceURI, localName);
243}
244
245
246Element* Document::getElementById(const XMLString& /*elementId*/) const
247{
248 return 0;
249}
250
251
252Event* Document::createEvent(const XMLString& eventType) const
253{
254 if (eventType == MutationEvent::DOMSubtreeModified ||
255 eventType == MutationEvent::DOMNodeInserted ||
256 eventType == MutationEvent::DOMNodeRemoved ||
257 eventType == MutationEvent::DOMNodeRemovedFromDocument ||
258 eventType == MutationEvent::DOMNodeInsertedIntoDocument ||
259 eventType == MutationEvent::DOMAttrModified ||
260 eventType == MutationEvent::DOMCharacterDataModified)
261 {
262 return new MutationEvent(const_cast<Document*>(this), eventType);
263 }
264 throw DOMException(DOMException::NOT_SUPPORTED_ERR);
265}
266
267
268Node* Document::copyNode(bool /*deep*/, Document* /*pOwnerDocument*/) const
269{
270 throw DOMException(DOMException::NOT_SUPPORTED_ERR);
271}
272
273
274void Document::setDoctype(DocumentType* pDoctype)
275{
276 if (_pDocumentType) _pDocumentType->release();
277 _pDocumentType = pDoctype;
278 if (_pDocumentType)
279 {
280 _pDocumentType->duplicate();
281 _pDocumentType->setOwnerDocument(this);
282 }
283}
284
285
286bool Document::eventsSuspended() const
287{
288 return _eventSuspendLevel > 0;
289}
290
291
292bool Document::events() const
293{
294 return _eventSuspendLevel == 0;
295}
296
297
298Entity* Document::createEntity(const XMLString& name, const XMLString& publicId, const XMLString& systemId, const XMLString& notationName) const
299{
300 return new Entity(const_cast<Document*>(this), name, publicId, systemId, notationName);
301}
302
303
304Notation* Document::createNotation(const XMLString& name, const XMLString& publicId, const XMLString& systemId) const
305{
306 return new Notation(const_cast<Document*>(this), name, publicId, systemId);
307}
308
309
310Element* Document::getElementById(const XMLString& elementId, const XMLString& idAttribute) const
311{
312 Element* pElem = documentElement();
313 if (pElem) pElem = pElem->getElementById(elementId, idAttribute);
314 return pElem;
315}
316
317
318Element* Document::getElementByIdNS(const XMLString& elementId, const XMLString& idAttributeURI, const XMLString& idAttributeLocalName) const
319{
320 Element* pElem = documentElement();
321 if (pElem) pElem = pElem->getElementByIdNS(elementId, idAttributeURI, idAttributeLocalName);
322 return pElem;
323}
324
325
326} } // namespace Poco::XML
327