source: trunk/src/xml/dom/qdom.cpp@ 651

Last change on this file since 651 was 651, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.2 sources.

File size: 213.2 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtXml module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include <qplatformdefs.h>
43#include <qdom.h>
44#include "private/qxmlutils_p.h"
45
46#ifndef QT_NO_DOM
47
48#include <qatomic.h>
49#include <qbuffer.h>
50#include <qhash.h>
51#include <qiodevice.h>
52#include <qlist.h>
53#include <qregexp.h>
54#include <qtextcodec.h>
55#include <qtextstream.h>
56#include <qxml.h>
57#include <qvariant.h>
58#include <qmap.h>
59#include <qshareddata.h>
60#include <qdebug.h>
61#include <stdio.h>
62
63QT_BEGIN_NAMESPACE
64
65/*
66 ### old todo comments -- I don't know if they still apply...
67
68 If the document dies, remove all pointers to it from children
69 which can not be deleted at this time.
70
71 If a node dies and has direct children which can not be deleted,
72 then remove the pointer to the parent.
73
74 createElement and friends create double reference counts.
75*/
76
77/* ##### new TODOs:
78
79 Remove emtpy emthods in the *Private classes
80
81 Make a lot of the (mostly empty) methods in the public classes inline.
82 Specially constructors assignment operators and comparison operators are candidates.
83
84 The virtual isXxx functions in *Private can probably be replaced by inline methods checking the nodeType().
85*/
86
87/*
88 Reference counting:
89
90 Some simple rules:
91 1) If an intern object returns a pointer to another intern object
92 then the reference count of the returned object is not increased.
93 2) If an extern object is created and gets a pointer to some intern
94 object, then the extern object increases the intern objects reference count.
95 3) If an extern object is deleted, then it decreases the reference count
96 on its associated intern object and deletes it if nobody else hold references
97 on the intern object.
98*/
99
100
101/*
102 Helper to split a qualified name in the prefix and local name.
103*/
104static void qt_split_namespace(QString& prefix, QString& name, const QString& qName, bool hasURI)
105{
106 int i = qName.indexOf(QLatin1Char(':'));
107 if (i == -1) {
108 if (hasURI)
109 prefix = QLatin1String("");
110 else
111 prefix.clear();
112 name = qName;
113 } else {
114 prefix = qName.left(i);
115 name = qName.mid(i + 1);
116 }
117}
118
119/**************************************************************
120 *
121 * Private class declerations
122 *
123 **************************************************************/
124
125class QDomImplementationPrivate
126{
127public:
128 inline QDomImplementationPrivate() {}
129
130 QDomImplementationPrivate* clone();
131 QAtomicInt ref;
132 static QDomImplementation::InvalidDataPolicy invalidDataPolicy;
133};
134
135class QDomNodePrivate
136{
137public:
138 QDomNodePrivate(QDomDocumentPrivate*, QDomNodePrivate* parent = 0);
139 QDomNodePrivate(QDomNodePrivate* n, bool deep);
140 virtual ~QDomNodePrivate();
141
142 QString nodeName() const { return name; }
143 QString nodeValue() const { return value; }
144 virtual void setNodeValue(const QString& v) { value = v; }
145
146 QDomDocumentPrivate* ownerDocument();
147 void setOwnerDocument(QDomDocumentPrivate* doc);
148
149 virtual QDomNodePrivate* insertBefore(QDomNodePrivate* newChild, QDomNodePrivate* refChild);
150 virtual QDomNodePrivate* insertAfter(QDomNodePrivate* newChild, QDomNodePrivate* refChild);
151 virtual QDomNodePrivate* replaceChild(QDomNodePrivate* newChild, QDomNodePrivate* oldChild);
152 virtual QDomNodePrivate* removeChild(QDomNodePrivate* oldChild);
153 virtual QDomNodePrivate* appendChild(QDomNodePrivate* newChild);
154
155 QDomNodePrivate* namedItem(const QString& name);
156
157 virtual QDomNodePrivate* cloneNode(bool deep = true);
158 virtual void normalize();
159 virtual void clear();
160
161 inline QDomNodePrivate* parent() const { return hasParent ? ownerNode : 0; }
162 inline void setParent(QDomNodePrivate *p) { ownerNode = p; hasParent = true; }
163
164 void setNoParent() {
165 ownerNode = hasParent ? (QDomNodePrivate*)ownerDocument() : 0;
166 hasParent = false;
167 }
168
169 // Dynamic cast
170 virtual bool isAttr() const { return false; }
171 virtual bool isCDATASection() const { return false; }
172 virtual bool isDocumentFragment() const { return false; }
173 virtual bool isDocument() const { return false; }
174 virtual bool isDocumentType() const { return false; }
175 virtual bool isElement() const { return false; }
176 virtual bool isEntityReference() const { return false; }
177 virtual bool isText() const { return false; }
178 virtual bool isEntity() const { return false; }
179 virtual bool isNotation() const { return false; }
180 virtual bool isProcessingInstruction() const { return false; }
181 virtual bool isCharacterData() const { return false; }
182 virtual bool isComment() const { return false; }
183
184 virtual QDomNode::NodeType nodeType() const { return QDomNode::BaseNode; }
185
186 virtual void save(QTextStream&, int, int) const;
187
188 void setLocation(int lineNumber, int columnNumber);
189
190 // Variables
191 QAtomicInt ref;
192 QDomNodePrivate* prev;
193 QDomNodePrivate* next;
194 QDomNodePrivate* ownerNode; // either the node's parent or the node's owner document
195 QDomNodePrivate* first;
196 QDomNodePrivate* last;
197
198 QString name; // this is the local name if prefix != null
199 QString value;
200 QString prefix; // set this only for ElementNode and AttributeNode
201 QString namespaceURI; // set this only for ElementNode and AttributeNode
202 bool createdWithDom1Interface : 1;
203 bool hasParent : 1;
204
205 int lineNumber;
206 int columnNumber;
207};
208
209class QDomNodeListPrivate
210{
211public:
212 QDomNodeListPrivate(QDomNodePrivate*);
213 QDomNodeListPrivate(QDomNodePrivate*, const QString& );
214 QDomNodeListPrivate(QDomNodePrivate*, const QString&, const QString& );
215 ~QDomNodeListPrivate();
216
217 bool operator== (const QDomNodeListPrivate&) const;
218 bool operator!= (const QDomNodeListPrivate&) const;
219
220 void createList();
221 QDomNodePrivate* item(int index);
222 uint length() const;
223
224 QAtomicInt ref;
225 /*
226 This list contains the children of this node.
227 */
228 QDomNodePrivate* node_impl;
229 QString tagname;
230 QString nsURI;
231 QList<QDomNodePrivate*> list;
232 long timestamp;
233};
234
235class QDomNamedNodeMapPrivate
236{
237public:
238 QDomNamedNodeMapPrivate(QDomNodePrivate*);
239 ~QDomNamedNodeMapPrivate();
240
241 QDomNodePrivate* namedItem(const QString& name) const;
242 QDomNodePrivate* namedItemNS(const QString& nsURI, const QString& localName) const;
243 QDomNodePrivate* setNamedItem(QDomNodePrivate* arg);
244 QDomNodePrivate* setNamedItemNS(QDomNodePrivate* arg);
245 QDomNodePrivate* removeNamedItem(const QString& name);
246 QDomNodePrivate* item(int index) const;
247 uint length() const;
248 bool contains(const QString& name) const;
249 bool containsNS(const QString& nsURI, const QString & localName) const;
250
251 /**
252 * Remove all children from the map.
253 */
254 void clearMap();
255 bool isReadOnly() { return readonly; }
256 void setReadOnly(bool r) { readonly = r; }
257 bool isAppendToParent() { return appendToParent; }
258 /**
259 * If true, then the node will redirect insert/remove calls
260 * to its parent by calling QDomNodePrivate::appendChild or removeChild.
261 * In addition the map wont increase or decrease the reference count
262 * of the nodes it contains.
263 *
264 * By default this value is false and the map will handle reference counting
265 * by itself.
266 */
267 void setAppendToParent(bool b) { appendToParent = b; }
268
269 /**
270 * Creates a copy of the map. It is a deep copy
271 * that means that all children are cloned.
272 */
273 QDomNamedNodeMapPrivate* clone(QDomNodePrivate* parent);
274
275 // Variables
276 QAtomicInt ref;
277 QHash<QString, QDomNodePrivate *> map;
278 QDomNodePrivate* parent;
279 bool readonly;
280 bool appendToParent;
281};
282
283class QDomDocumentTypePrivate : public QDomNodePrivate
284{
285public:
286 QDomDocumentTypePrivate(QDomDocumentPrivate*, QDomNodePrivate* parent = 0);
287 QDomDocumentTypePrivate(QDomDocumentTypePrivate* n, bool deep);
288 ~QDomDocumentTypePrivate();
289 void init();
290
291 // Reimplemented from QDomNodePrivate
292 QDomNodePrivate* cloneNode(bool deep = true);
293 QDomNodePrivate* insertBefore(QDomNodePrivate* newChild, QDomNodePrivate* refChild);
294 QDomNodePrivate* insertAfter(QDomNodePrivate* newChild, QDomNodePrivate* refChild);
295 QDomNodePrivate* replaceChild(QDomNodePrivate* newChild, QDomNodePrivate* oldChild);
296 QDomNodePrivate* removeChild(QDomNodePrivate* oldChild);
297 QDomNodePrivate* appendChild(QDomNodePrivate* newChild);
298
299 virtual bool isDocumentType() const { return true; }
300 QDomNode::NodeType nodeType() const { return QDomNode::DocumentTypeNode; }
301
302 void save(QTextStream& s, int, int) const;
303
304 // Variables
305 QDomNamedNodeMapPrivate* entities;
306 QDomNamedNodeMapPrivate* notations;
307 QString publicId;
308 QString systemId;
309 QString internalSubset;
310};
311
312class QDomDocumentFragmentPrivate : public QDomNodePrivate
313{
314public:
315 QDomDocumentFragmentPrivate(QDomDocumentPrivate*, QDomNodePrivate* parent = 0);
316 QDomDocumentFragmentPrivate(QDomNodePrivate* n, bool deep);
317
318 // Reimplemented from QDomNodePrivate
319 virtual QDomNodePrivate* cloneNode(bool deep = true);
320 virtual bool isDocumentFragment() const { return true; }
321 QDomNode::NodeType nodeType() const { return QDomNode::DocumentFragmentNode; }
322};
323
324class QDomCharacterDataPrivate : public QDomNodePrivate
325{
326public:
327 QDomCharacterDataPrivate(QDomDocumentPrivate*, QDomNodePrivate* parent, const QString& data);
328 QDomCharacterDataPrivate(QDomCharacterDataPrivate* n, bool deep);
329
330 uint dataLength() const;
331 QString substringData(unsigned long offset, unsigned long count) const;
332 void appendData(const QString& arg);
333 void insertData(unsigned long offset, const QString& arg);
334 void deleteData(unsigned long offset, unsigned long count);
335 void replaceData(unsigned long offset, unsigned long count, const QString& arg);
336
337 // Reimplemented from QDomNodePrivate
338 virtual bool isCharacterData() const { return true; }
339 QDomNode::NodeType nodeType() const { return QDomNode::CharacterDataNode; }
340 QDomNodePrivate* cloneNode(bool deep = true);
341};
342
343class QDomTextPrivate : public QDomCharacterDataPrivate
344{
345public:
346 QDomTextPrivate(QDomDocumentPrivate*, QDomNodePrivate* parent, const QString& val);
347 QDomTextPrivate(QDomTextPrivate* n, bool deep);
348
349 QDomTextPrivate* splitText(int offset);
350
351 // Reimplemented from QDomNodePrivate
352 QDomNodePrivate* cloneNode(bool deep = true);
353 virtual bool isText() const { return true; }
354 QDomNode::NodeType nodeType() const { return QDomNode::TextNode; }
355 virtual void save(QTextStream& s, int, int) const;
356};
357
358class QDomAttrPrivate : public QDomNodePrivate
359{
360public:
361 QDomAttrPrivate(QDomDocumentPrivate*, QDomNodePrivate*, const QString& name);
362 QDomAttrPrivate(QDomDocumentPrivate*, QDomNodePrivate*, const QString& nsURI, const QString& qName);
363 QDomAttrPrivate(QDomAttrPrivate* n, bool deep);
364
365 bool specified() const;
366
367 // Reimplemented from QDomNodePrivate
368 void setNodeValue(const QString& v);
369 QDomNodePrivate* cloneNode(bool deep = true);
370 virtual bool isAttr() const { return true; }
371 QDomNode::NodeType nodeType() const { return QDomNode::AttributeNode; }
372 virtual void save(QTextStream& s, int, int) const;
373
374 // Variables
375 bool m_specified;
376};
377
378class QDomElementPrivate : public QDomNodePrivate
379{
380public:
381 QDomElementPrivate(QDomDocumentPrivate*, QDomNodePrivate* parent, const QString& name);
382 QDomElementPrivate(QDomDocumentPrivate*, QDomNodePrivate* parent, const QString& nsURI, const QString& qName);
383 QDomElementPrivate(QDomElementPrivate* n, bool deep);
384 ~QDomElementPrivate();
385
386 QString attribute(const QString& name, const QString& defValue) const;
387 QString attributeNS(const QString& nsURI, const QString& localName, const QString& defValue) const;
388 void setAttribute(const QString& name, const QString& value);
389 void setAttributeNS(const QString& nsURI, const QString& qName, const QString& newValue);
390 void removeAttribute(const QString& name);
391 QDomAttrPrivate* attributeNode(const QString& name);
392 QDomAttrPrivate* attributeNodeNS(const QString& nsURI, const QString& localName);
393 QDomAttrPrivate* setAttributeNode(QDomAttrPrivate* newAttr);
394 QDomAttrPrivate* setAttributeNodeNS(QDomAttrPrivate* newAttr);
395 QDomAttrPrivate* removeAttributeNode(QDomAttrPrivate* oldAttr);
396 bool hasAttribute(const QString& name);
397 bool hasAttributeNS(const QString& nsURI, const QString& localName);
398
399 QString text();
400
401 // Reimplemented from QDomNodePrivate
402 QDomNamedNodeMapPrivate* attributes() { return m_attr; }
403 bool hasAttributes() { return (m_attr->length() > 0); }
404 virtual bool isElement() const { return true; }
405 QDomNode::NodeType nodeType() const { return QDomNode::ElementNode; }
406 QDomNodePrivate* cloneNode(bool deep = true);
407 virtual void save(QTextStream& s, int, int) const;
408
409 // Variables
410 QDomNamedNodeMapPrivate* m_attr;
411};
412
413
414class QDomCommentPrivate : public QDomCharacterDataPrivate
415{
416public:
417 QDomCommentPrivate(QDomDocumentPrivate*, QDomNodePrivate* parent, const QString& val);
418 QDomCommentPrivate(QDomCommentPrivate* n, bool deep);
419
420 // Reimplemented from QDomNodePrivate
421 QDomNodePrivate* cloneNode(bool deep = true);
422 virtual bool isComment() const { return true; }
423 QDomNode::NodeType nodeType() const { return QDomNode::CommentNode; }
424 virtual void save(QTextStream& s, int, int) const;
425};
426
427class QDomCDATASectionPrivate : public QDomTextPrivate
428{
429public:
430 QDomCDATASectionPrivate(QDomDocumentPrivate*, QDomNodePrivate* parent, const QString& val);
431 QDomCDATASectionPrivate(QDomCDATASectionPrivate* n, bool deep);
432
433 // Reimplemented from QDomNodePrivate
434 QDomNodePrivate* cloneNode(bool deep = true);
435 virtual bool isCDATASection() const { return true; }
436 QDomNode::NodeType nodeType() const { return QDomNode::CDATASectionNode; }
437 virtual void save(QTextStream& s, int, int) const;
438};
439
440class QDomNotationPrivate : public QDomNodePrivate
441{
442public:
443 QDomNotationPrivate(QDomDocumentPrivate*, QDomNodePrivate* parent, const QString& name,
444 const QString& pub, const QString& sys);
445 QDomNotationPrivate(QDomNotationPrivate* n, bool deep);
446
447 // Reimplemented from QDomNodePrivate
448 QDomNodePrivate* cloneNode(bool deep = true);
449 virtual bool isNotation() const { return true; }
450 QDomNode::NodeType nodeType() const { return QDomNode::NotationNode; }
451 virtual void save(QTextStream& s, int, int) const;
452
453 // Variables
454 QString m_sys;
455 QString m_pub;
456};
457
458class QDomEntityPrivate : public QDomNodePrivate
459{
460public:
461 QDomEntityPrivate(QDomDocumentPrivate*, QDomNodePrivate* parent, const QString& name,
462 const QString& pub, const QString& sys, const QString& notation);
463 QDomEntityPrivate(QDomEntityPrivate* n, bool deep);
464
465 // Reimplemented from QDomNodePrivate
466 QDomNodePrivate* cloneNode(bool deep = true);
467 virtual bool isEntity() const { return true; }
468 QDomNode::NodeType nodeType() const { return QDomNode::EntityNode; }
469 virtual void save(QTextStream& s, int, int) const;
470
471 // Variables
472 QString m_sys;
473 QString m_pub;
474 QString m_notationName;
475};
476
477class QDomEntityReferencePrivate : public QDomNodePrivate
478{
479public:
480 QDomEntityReferencePrivate(QDomDocumentPrivate*, QDomNodePrivate* parent, const QString& name);
481 QDomEntityReferencePrivate(QDomNodePrivate* n, bool deep);
482
483 // Reimplemented from QDomNodePrivate
484 QDomNodePrivate* cloneNode(bool deep = true);
485 bool isEntityReference() const { return true; }
486 QDomNode::NodeType nodeType() const { return QDomNode::EntityReferenceNode; }
487 virtual void save(QTextStream& s, int, int) const;
488};
489
490class QDomProcessingInstructionPrivate : public QDomNodePrivate
491{
492public:
493 QDomProcessingInstructionPrivate(QDomDocumentPrivate*, QDomNodePrivate* parent, const QString& target,
494 const QString& data);
495 QDomProcessingInstructionPrivate(QDomProcessingInstructionPrivate* n, bool deep);
496
497 // Reimplemented from QDomNodePrivate
498 QDomNodePrivate* cloneNode(bool deep = true);
499 virtual bool isProcessingInstruction() const { return true; }
500 QDomNode::NodeType nodeType() const { return QDomNode::ProcessingInstructionNode; }
501 virtual void save(QTextStream& s, int, int) const;
502};
503
504class QDomDocumentPrivate : public QDomNodePrivate
505{
506public:
507 QDomDocumentPrivate();
508 QDomDocumentPrivate(const QString& name);
509 QDomDocumentPrivate(QDomDocumentTypePrivate* dt);
510 QDomDocumentPrivate(QDomDocumentPrivate* n, bool deep);
511 ~QDomDocumentPrivate();
512
513 bool setContent(QXmlInputSource *source, bool namespaceProcessing, QString *errorMsg, int *errorLine, int *errorColumn);
514 bool setContent(QXmlInputSource *source, QXmlReader *reader, QString *errorMsg, int *errorLine, int *errorColumn);
515
516 // Attributes
517 QDomDocumentTypePrivate* doctype() { return type.data(); }
518 QDomImplementationPrivate* implementation() { return impl.data(); }
519 QDomElementPrivate* documentElement();
520
521 // Factories
522 QDomElementPrivate* createElement(const QString& tagName);
523 QDomElementPrivate* createElementNS(const QString& nsURI, const QString& qName);
524 QDomDocumentFragmentPrivate* createDocumentFragment();
525 QDomTextPrivate* createTextNode(const QString& data);
526 QDomCommentPrivate* createComment(const QString& data);
527 QDomCDATASectionPrivate* createCDATASection(const QString& data);
528 QDomProcessingInstructionPrivate* createProcessingInstruction(const QString& target, const QString& data);
529 QDomAttrPrivate* createAttribute(const QString& name);
530 QDomAttrPrivate* createAttributeNS(const QString& nsURI, const QString& qName);
531 QDomEntityReferencePrivate* createEntityReference(const QString& name);
532
533 QDomNodePrivate* importNode(const QDomNodePrivate* importedNode, bool deep);
534
535 // Reimplemented from QDomNodePrivate
536 QDomNodePrivate* cloneNode(bool deep = true);
537 bool isDocument() const { return true; }
538 QDomNode::NodeType nodeType() const { return QDomNode::DocumentNode; }
539 void clear();
540
541 // Variables
542 QExplicitlySharedDataPointer<QDomImplementationPrivate> impl;
543 QExplicitlySharedDataPointer<QDomDocumentTypePrivate> type;
544
545 void saveDocument(QTextStream& stream, const int indent, QDomNode::EncodingPolicy encUsed) const;
546
547 /* \internal
548 Counter for the QDomNodeListPrivate timestamps.
549
550 This is a cache optimization, that might in some cases be effective. The
551 dilemma is that QDomNode::childNodes() returns a list, but the
552 implementation stores the children in a linked list. Hence, in order to
553 get the children out through childNodes(), a list must be populated each
554 time, which is O(N).
555
556 DOM has the requirement of node references being live, see DOM Core
557 Level 3, 1.1.1 The DOM Structure Model, which means that changes to the
558 underlying documents must be reflected in node lists.
559
560 This mechanism, nodeListTime, is a caching optimization that reduces the
561 amount of times the node list is rebuilt, by only doing so when the
562 document actually changes. However, a change to anywhere in any document
563 invalidate all lists, since no dependency tracking is done.
564
565 It functions by that all modifying functions(insertBefore() and so on)
566 increment the count; each QDomNodeListPrivate copies nodeListTime on
567 construction, and compares its own value to nodeListTime in order to
568 determine whether it needs to rebuild.
569
570 This is reentrant. The nodeListTime may overflow, but that's ok since we
571 check for equalness, not whether nodeListTime is smaller than the list's
572 stored timestamp.
573 */
574 long nodeListTime;
575};
576
577/**************************************************************
578 *
579 * QDomHandler
580 *
581 **************************************************************/
582
583class QDomHandler : public QXmlDefaultHandler
584{
585public:
586 QDomHandler(QDomDocumentPrivate* d, bool namespaceProcessing);
587 ~QDomHandler();
588
589 // content handler
590 bool endDocument();
591 bool startElement(const QString& nsURI, const QString& localName, const QString& qName, const QXmlAttributes& atts);
592 bool endElement(const QString& nsURI, const QString& localName, const QString& qName);
593 bool characters(const QString& ch);
594 bool processingInstruction(const QString& target, const QString& data);
595 bool skippedEntity(const QString& name);
596
597 // error handler
598 bool fatalError(const QXmlParseException& exception);
599
600 // lexical handler
601 bool startCDATA();
602 bool endCDATA();
603 bool startEntity(const QString &);
604 bool endEntity(const QString &);
605 bool startDTD(const QString& name, const QString& publicId, const QString& systemId);
606 bool comment(const QString& ch);
607
608 // decl handler
609 bool externalEntityDecl(const QString &name, const QString &publicId, const QString &systemId) ;
610
611 // DTD handler
612 bool notationDecl(const QString & name, const QString & publicId, const QString & systemId);
613 bool unparsedEntityDecl(const QString &name, const QString &publicId, const QString &systemId, const QString &notationName) ;
614
615 void setDocumentLocator(QXmlLocator *locator);
616
617 QString errorMsg;
618 int errorLine;
619 int errorColumn;
620
621private:
622 QDomDocumentPrivate *doc;
623 QDomNodePrivate *node;
624 QString entityName;
625 bool cdata;
626 bool nsProcessing;
627 QXmlLocator *locator;
628};
629
630/**************************************************************
631 *
632 * Functions for verifying legal data
633 *
634 **************************************************************/
635QDomImplementation::InvalidDataPolicy QDomImplementationPrivate::invalidDataPolicy
636 = QDomImplementation::AcceptInvalidChars;
637
638// [5] Name ::= (Letter | '_' | ':') (NameChar)*
639
640static QString fixedXmlName(const QString &_name, bool *ok, bool namespaces = false)
641{
642 QString name, prefix;
643 if (namespaces)
644 qt_split_namespace(prefix, name, _name, true);
645 else
646 name = _name;
647
648 if (name.isEmpty()) {
649 *ok = false;
650 return QString();
651 }
652
653 if (QDomImplementationPrivate::invalidDataPolicy == QDomImplementation::AcceptInvalidChars) {
654 *ok = true;
655 return _name;
656 }
657
658 QString result;
659 bool firstChar = true;
660 for (int i = 0; i < name.size(); ++i) {
661 QChar c = name.at(i);
662 if (firstChar) {
663 if (QXmlUtils::isLetter(c) || c.unicode() == '_' || c.unicode() == ':') {
664 result.append(c);
665 firstChar = false;
666 } else if (QDomImplementationPrivate::invalidDataPolicy == QDomImplementation::ReturnNullNode) {
667 *ok = false;
668 return QString();
669 }
670 } else {
671 if (QXmlUtils::isNameChar(c))
672 result.append(c);
673 else if (QDomImplementationPrivate::invalidDataPolicy == QDomImplementation::ReturnNullNode) {
674 *ok = false;
675 return QString();
676 }
677 }
678 }
679
680 if (result.isEmpty()) {
681 *ok = false;
682 return QString();
683 }
684
685 *ok = true;
686 if (namespaces && !prefix.isEmpty())
687 return prefix + QLatin1Char(':') + result;
688 return result;
689}
690
691// [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
692// '<', '&' and "]]>" will be escaped when writing
693
694static QString fixedCharData(const QString &data, bool *ok)
695{
696 if (QDomImplementationPrivate::invalidDataPolicy == QDomImplementation::AcceptInvalidChars) {
697 *ok = true;
698 return data;
699 }
700
701 QString result;
702 for (int i = 0; i < data.size(); ++i) {
703 QChar c = data.at(i);
704 if (QXmlUtils::isChar(c)) {
705 result.append(c);
706 } else if (QDomImplementationPrivate::invalidDataPolicy == QDomImplementation::ReturnNullNode) {
707 *ok = false;
708 return QString();
709 }
710 }
711
712 *ok = true;
713 return result;
714}
715
716// [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
717// can't escape "--", since entities are not recognised within comments
718
719static QString fixedComment(const QString &data, bool *ok)
720{
721 if (QDomImplementationPrivate::invalidDataPolicy == QDomImplementation::AcceptInvalidChars) {
722 *ok = true;
723 return data;
724 }
725
726 QString fixedData = fixedCharData(data, ok);
727 if (!*ok)
728 return QString();
729
730 for (;;) {
731 int idx = fixedData.indexOf(QLatin1String("--"));
732 if (idx == -1)
733 break;
734 if (QDomImplementationPrivate::invalidDataPolicy == QDomImplementation::ReturnNullNode) {
735 *ok = false;
736 return QString();
737 }
738 fixedData.remove(idx, 2);
739 }
740
741 *ok = true;
742 return fixedData;
743}
744
745// [20] CData ::= (Char* - (Char* ']]>' Char*))
746// can't escape "]]>", since entities are not recognised within comments
747
748static QString fixedCDataSection(const QString &data, bool *ok)
749{
750 if (QDomImplementationPrivate::invalidDataPolicy == QDomImplementation::AcceptInvalidChars) {
751 *ok = true;
752 return data;
753 }
754
755 QString fixedData = fixedCharData(data, ok);
756 if (!*ok)
757 return QString();
758
759 for (;;) {
760 int idx = fixedData.indexOf(QLatin1String("]]>"));
761 if (idx == -1)
762 break;
763 if (QDomImplementationPrivate::invalidDataPolicy == QDomImplementation::ReturnNullNode) {
764 *ok = false;
765 return QString();
766 }
767 fixedData.remove(idx, 3);
768 }
769
770 *ok = true;
771 return fixedData;
772}
773
774// [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
775
776static QString fixedPIData(const QString &data, bool *ok)
777{
778 if (QDomImplementationPrivate::invalidDataPolicy == QDomImplementation::AcceptInvalidChars) {
779 *ok = true;
780 return data;
781 }
782
783 QString fixedData = fixedCharData(data, ok);
784 if (!*ok)
785 return QString();
786
787 for (;;) {
788 int idx = fixedData.indexOf(QLatin1String("?>"));
789 if (idx == -1)
790 break;
791 if (QDomImplementationPrivate::invalidDataPolicy == QDomImplementation::ReturnNullNode) {
792 *ok = false;
793 return QString();
794 }
795 fixedData.remove(idx, 2);
796 }
797
798 *ok = true;
799 return fixedData;
800}
801
802// [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
803// The correct quote will be chosen when writing
804
805static QString fixedPubidLiteral(const QString &data, bool *ok)
806{
807 if (QDomImplementationPrivate::invalidDataPolicy == QDomImplementation::AcceptInvalidChars) {
808 *ok = true;
809 return data;
810 }
811
812 QString result;
813
814 if(QXmlUtils::isPublicID(data))
815 result = data;
816 else if (QDomImplementationPrivate::invalidDataPolicy == QDomImplementation::ReturnNullNode) {
817 *ok = false;
818 return QString();
819 }
820
821 if (result.indexOf(QLatin1Char('\'')) != -1
822 && result.indexOf(QLatin1Char('"')) != -1) {
823 if (QDomImplementationPrivate::invalidDataPolicy == QDomImplementation::ReturnNullNode) {
824 *ok = false;
825 return QString();
826 } else {
827 result.remove(QLatin1Char('\''));
828 }
829 }
830
831 *ok = true;
832 return result;
833}
834
835// [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
836// The correct quote will be chosen when writing
837
838static QString fixedSystemLiteral(const QString &data, bool *ok)
839{
840 if (QDomImplementationPrivate::invalidDataPolicy == QDomImplementation::AcceptInvalidChars) {
841 *ok = true;
842 return data;
843 }
844
845 QString result = data;
846
847 if (result.indexOf(QLatin1Char('\'')) != -1
848 && result.indexOf(QLatin1Char('"')) != -1) {
849 if (QDomImplementationPrivate::invalidDataPolicy == QDomImplementation::ReturnNullNode) {
850 *ok = false;
851 return QString();
852 } else {
853 result.remove(QLatin1Char('\''));
854 }
855 }
856
857 *ok = true;
858 return result;
859}
860
861/**************************************************************
862 *
863 * QDomImplementationPrivate
864 *
865 **************************************************************/
866
867QDomImplementationPrivate* QDomImplementationPrivate::clone()
868{
869 return new QDomImplementationPrivate;
870}
871
872/**************************************************************
873 *
874 * QDomImplementation
875 *
876 **************************************************************/
877
878/*!
879 \class QDomImplementation
880 \reentrant
881 \brief The QDomImplementation class provides information about the
882 features of the DOM implementation.
883
884 \inmodule QtXml
885 \ingroup xml-tools
886
887 This class describes the features that are supported by the DOM
888 implementation. Currently the XML subset of DOM Level 1 and DOM
889 Level 2 Core are supported.
890
891 Normally you will use the function QDomDocument::implementation()
892 to get the implementation object.
893
894 You can create a new document type with createDocumentType() and a
895 new document with createDocument().
896
897 For further information about the Document Object Model see
898 \l{http://www.w3.org/TR/REC-DOM-Level-1/}{Level 1} and
899 \l{http://www.w3.org/TR/DOM-Level-2-Core/}{Level 2 Core}. For a more
900 general introduction of the DOM implementation see the QDomDocument
901 documentation.
902
903 The QDom classes have a few issues of nonconformance with the XML
904 specifications that cannot be fixed in Qt 4 without breaking backward
905 compatibility. The QtXmlPatterns module and the QXmlStreamReader and
906 QXmlStreamWriter classes have a higher degree of a conformance.
907
908 \sa hasFeature()
909*/
910
911/*!
912 Constructs a QDomImplementation object.
913*/
914QDomImplementation::QDomImplementation()
915{
916 impl = 0;
917}
918
919/*!
920 Constructs a copy of \a x.
921*/
922QDomImplementation::QDomImplementation(const QDomImplementation &x)
923{
924 impl = x.impl;
925 if (impl)
926 impl->ref.ref();
927}
928
929QDomImplementation::QDomImplementation(QDomImplementationPrivate *p)
930{
931 // We want to be co-owners, so increase the reference count
932 impl = p;
933 if (impl)
934 impl->ref.ref();
935}
936
937/*!
938 Assigns \a x to this DOM implementation.
939*/
940QDomImplementation& QDomImplementation::operator=(const QDomImplementation &x)
941{
942 if (x.impl)
943 x.impl->ref.ref();
944 if (impl && !impl->ref.deref())
945 delete impl;
946 impl = x.impl;
947 return *this;
948}
949
950/*!
951 Returns true if \a x and this DOM implementation object were
952 created from the same QDomDocument; otherwise returns false.
953*/
954bool QDomImplementation::operator==(const QDomImplementation &x) const
955{
956 return (impl == x.impl);
957}
958
959/*!
960 Returns true if \a x and this DOM implementation object were
961 created from different QDomDocuments; otherwise returns false.
962*/
963bool QDomImplementation::operator!=(const QDomImplementation &x) const
964{
965 return (impl != x.impl);
966}
967
968/*!
969 Destroys the object and frees its resources.
970*/
971QDomImplementation::~QDomImplementation()
972{
973 if (impl && !impl->ref.deref())
974 delete impl;
975}
976
977/*!
978 The function returns true if QDom implements the requested \a
979 version of a \a feature; otherwise returns false.
980
981 The currently supported features and their versions:
982 \table
983 \header \i Feature \i Version
984 \row \i XML \i 1.0
985 \endtable
986*/
987bool QDomImplementation::hasFeature(const QString& feature, const QString& version) const
988{
989 if (feature == QLatin1String("XML")) {
990 if (version.isEmpty() || version == QLatin1String("1.0")) {
991 return true;
992 }
993 }
994 // ### add DOM level 2 features
995 return false;
996}
997
998/*!
999 Creates a document type node for the name \a qName.
1000
1001 \a publicId specifies the public identifier of the external
1002 subset. If you specify an empty string (QString()) as the \a
1003 publicId, this means that the document type has no public
1004 identifier.
1005
1006 \a systemId specifies the system identifier of the external
1007 subset. If you specify an empty string as the \a systemId, this
1008 means that the document type has no system identifier.
1009
1010 Since you cannot have a public identifier without a system
1011 identifier, the public identifier is set to an empty string if
1012 there is no system identifier.
1013
1014 DOM level 2 does not support any other document type declaration
1015 features.
1016
1017 The only way you can use a document type that was created this
1018 way, is in combination with the createDocument() function to
1019 create a QDomDocument with this document type.
1020
1021 In the DOM specification, this is the only way to create a non-null
1022 document. For historical reasons, Qt also allows to create the
1023 document using the default empty constructor. The resulting document
1024 is null, but becomes non-null when a factory function, for example
1025 QDomDocument::createElement(), is called. The document also becomes
1026 non-null when setContent() is called.
1027
1028 \sa createDocument()
1029*/
1030QDomDocumentType QDomImplementation::createDocumentType(const QString& qName, const QString& publicId, const QString& systemId)
1031{
1032 bool ok;
1033 QString fixedName = fixedXmlName(qName, &ok, true);
1034 if (!ok)
1035 return QDomDocumentType();
1036
1037 QString fixedPublicId = fixedPubidLiteral(publicId, &ok);
1038 if (!ok)
1039 return QDomDocumentType();
1040
1041 QString fixedSystemId = fixedSystemLiteral(systemId, &ok);
1042 if (!ok)
1043 return QDomDocumentType();
1044
1045 QDomDocumentTypePrivate *dt = new QDomDocumentTypePrivate(0);
1046 dt->name = fixedName;
1047 if (systemId.isNull()) {
1048 dt->publicId.clear();
1049 dt->systemId.clear();
1050 } else {
1051 dt->publicId = fixedPublicId;
1052 dt->systemId = fixedSystemId;
1053 }
1054 dt->ref.deref();
1055 return QDomDocumentType(dt);
1056}
1057
1058/*!
1059 Creates a DOM document with the document type \a doctype. This
1060 function also adds a root element node with the qualified name \a
1061 qName and the namespace URI \a nsURI.
1062*/
1063QDomDocument QDomImplementation::createDocument(const QString& nsURI, const QString& qName, const QDomDocumentType& doctype)
1064{
1065 QDomDocument doc(doctype);
1066 QDomElement root = doc.createElementNS(nsURI, qName);
1067 if (root.isNull())
1068 return QDomDocument();
1069 doc.appendChild(root);
1070 return doc;
1071}
1072
1073/*!
1074 Returns false if the object was created by
1075 QDomDocument::implementation(); otherwise returns true.
1076*/
1077bool QDomImplementation::isNull()
1078{
1079 return (impl == 0);
1080}
1081
1082/*!
1083 \enum QDomImplementation::InvalidDataPolicy
1084
1085 This enum specifies what should be done when a factory function
1086 in QDomDocument is called with invalid data.
1087 \value AcceptInvalidChars The data should be stored in the DOM object
1088 anyway. In this case the resulting XML document might not be well-formed.
1089 This is the default value and QDom's behavior in Qt < 4.1.
1090 \value DropInvalidChars The invalid characters should be removed from
1091 the data.
1092 \value ReturnNullNode The factory function should return a null node.
1093
1094 \sa setInvalidDataPolicy() invalidDataPolicy()
1095*/
1096
1097/*!
1098 \enum QDomNode::EncodingPolicy
1099 \since 4.3
1100
1101 This enum specifies how QDomNode::save() determines what encoding to use
1102 when serializing.
1103
1104 \value EncodingFromDocument The encoding is fetched from the document.
1105 \value EncodingFromTextStream The encoding is fetched from the QTextStream.
1106
1107 See also the overload of the save() function that takes an EncodingPolicy.
1108*/
1109
1110/*!
1111 \since 4.1
1112 \nonreentrant
1113
1114 Returns the invalid data policy, which specifies what should be done when
1115 a factory function in QDomDocument is passed invalid data.
1116
1117 \sa setInvalidDataPolicy() InvalidDataPolicy
1118*/
1119
1120QDomImplementation::InvalidDataPolicy QDomImplementation::invalidDataPolicy()
1121{
1122 return QDomImplementationPrivate::invalidDataPolicy;
1123}
1124
1125/*!
1126 \since 4.1
1127 \nonreentrant
1128
1129 Sets the invalid data policy, which specifies what should be done when
1130 a factory function in QDomDocument is passed invalid data.
1131
1132 The \a policy is set for all instances of QDomDocument which already
1133 exist and which will be created in the future.
1134
1135 \snippet doc/src/snippets/code/src_xml_dom_qdom.cpp 0
1136
1137 \sa invalidDataPolicy() InvalidDataPolicy
1138*/
1139
1140void QDomImplementation::setInvalidDataPolicy(InvalidDataPolicy policy)
1141{
1142 QDomImplementationPrivate::invalidDataPolicy = policy;
1143}
1144
1145/**************************************************************
1146 *
1147 * QDomNodeListPrivate
1148 *
1149 **************************************************************/
1150
1151QDomNodeListPrivate::QDomNodeListPrivate(QDomNodePrivate *n_impl)
1152{
1153 ref = 1;
1154 node_impl = n_impl;
1155 if (node_impl)
1156 node_impl->ref.ref();
1157 timestamp = 0;
1158}
1159
1160QDomNodeListPrivate::QDomNodeListPrivate(QDomNodePrivate *n_impl, const QString &name)
1161{
1162 ref = 1;
1163 node_impl = n_impl;
1164 if (node_impl)
1165 node_impl->ref.ref();
1166 tagname = name;
1167 timestamp = 0;
1168}
1169
1170QDomNodeListPrivate::QDomNodeListPrivate(QDomNodePrivate *n_impl, const QString &_nsURI, const QString &localName)
1171{
1172 ref = 1;
1173 node_impl = n_impl;
1174 if (node_impl)
1175 node_impl->ref.ref();
1176 tagname = localName;
1177 nsURI = _nsURI;
1178 timestamp = 0;
1179}
1180
1181QDomNodeListPrivate::~QDomNodeListPrivate()
1182{
1183 if (node_impl && !node_impl->ref.deref())
1184 delete node_impl;
1185}
1186
1187bool QDomNodeListPrivate::operator==(const QDomNodeListPrivate &other) const
1188{
1189 return (node_impl == other.node_impl) && (tagname == other.tagname);
1190}
1191
1192bool QDomNodeListPrivate::operator!=(const QDomNodeListPrivate &other) const
1193{
1194 return (node_impl != other.node_impl) || (tagname != other.tagname);
1195}
1196
1197void QDomNodeListPrivate::createList()
1198{
1199 if (!node_impl)
1200 return;
1201
1202 const QDomDocumentPrivate *const doc = node_impl->ownerDocument();
1203 if (doc && timestamp != doc->nodeListTime)
1204 timestamp = doc->nodeListTime;
1205
1206 QDomNodePrivate* p = node_impl->first;
1207
1208 list.clear();
1209 if (tagname.isNull()) {
1210 while (p) {
1211 list.append(p);
1212 p = p->next;
1213 }
1214 } else if (nsURI.isNull()) {
1215 while (p && p != node_impl) {
1216 if (p->isElement() && p->nodeName() == tagname) {
1217 list.append(p);
1218 }
1219 if (p->first)
1220 p = p->first;
1221 else if (p->next)
1222 p = p->next;
1223 else {
1224 p = p->parent();
1225 while (p && p != node_impl && !p->next)
1226 p = p->parent();
1227 if (p && p != node_impl)
1228 p = p->next;
1229 }
1230 }
1231 } else {
1232 while (p && p != node_impl) {
1233 if (p->isElement() && p->name==tagname && p->namespaceURI==nsURI) {
1234 list.append(p);
1235 }
1236 if (p->first)
1237 p = p->first;
1238 else if (p->next)
1239 p = p->next;
1240 else {
1241 p = p->parent();
1242 while (p && p != node_impl && !p->next)
1243 p = p->parent();
1244 if (p && p != node_impl)
1245 p = p->next;
1246 }
1247 }
1248 }
1249}
1250
1251QDomNodePrivate* QDomNodeListPrivate::item(int index)
1252{
1253 if (!node_impl)
1254 return 0;
1255
1256 const QDomDocumentPrivate *const doc = node_impl->ownerDocument();
1257 if (!doc || timestamp != doc->nodeListTime)
1258 createList();
1259
1260 if (index >= list.size())
1261 return 0;
1262
1263 return list.at(index);
1264}
1265
1266uint QDomNodeListPrivate::length() const
1267{
1268 if (!node_impl)
1269 return 0;
1270
1271 const QDomDocumentPrivate *const doc = node_impl->ownerDocument();
1272 if (!doc || timestamp != doc->nodeListTime) {
1273 QDomNodeListPrivate *that = const_cast<QDomNodeListPrivate *>(this);
1274 that->createList();
1275 }
1276
1277 return list.count();
1278}
1279
1280/**************************************************************
1281 *
1282 * QDomNodeList
1283 *
1284 **************************************************************/
1285
1286/*!
1287 \class QDomNodeList
1288 \reentrant
1289 \brief The QDomNodeList class is a list of QDomNode objects.
1290
1291 \inmodule QtXml
1292 \ingroup xml-tools
1293
1294 Lists can be obtained by QDomDocument::elementsByTagName() and
1295 QDomNode::childNodes(). The Document Object Model (DOM) requires
1296 these lists to be "live": whenever you change the underlying
1297 document, the contents of the list will get updated.
1298
1299 You can get a particular node from the list with item(). The
1300 number of items in the list is returned by length().
1301
1302 For further information about the Document Object Model see
1303 \l{http://www.w3.org/TR/REC-DOM-Level-1/}{Level 1} and
1304 \l{http://www.w3.org/TR/DOM-Level-2-Core/}{Level 2 Core}.
1305 For a more general introduction of the DOM implementation see the
1306 QDomDocument documentation.
1307
1308 \sa QDomNode::childNodes() QDomDocument::elementsByTagName()
1309*/
1310
1311/*!
1312 Creates an empty node list.
1313*/
1314QDomNodeList::QDomNodeList()
1315{
1316 impl = 0;
1317}
1318
1319QDomNodeList::QDomNodeList(QDomNodeListPrivate* p)
1320{
1321 impl = p;
1322}
1323
1324/*!
1325 Constructs a copy of \a n.
1326*/
1327QDomNodeList::QDomNodeList(const QDomNodeList& n)
1328{
1329 impl = n.impl;
1330 if (impl)
1331 impl->ref.ref();
1332}
1333
1334/*!
1335 Assigns \a n to this node list.
1336*/
1337QDomNodeList& QDomNodeList::operator=(const QDomNodeList &n)
1338{
1339 if (n.impl)
1340 n.impl->ref.ref();
1341 if (impl && !impl->ref.deref())
1342 delete impl;
1343 impl = n.impl;
1344 return *this;
1345}
1346
1347/*!
1348 Returns true if the node list \a n and this node list are equal;
1349 otherwise returns false.
1350*/
1351bool QDomNodeList::operator==(const QDomNodeList &n) const
1352{
1353 if (impl == n.impl)
1354 return true;
1355 if (!impl || !n.impl)
1356 return false;
1357 return (*impl == *n.impl);
1358}
1359
1360/*!
1361 Returns true the node list \a n and this node list are not equal;
1362 otherwise returns false.
1363*/
1364bool QDomNodeList::operator!=(const QDomNodeList &n) const
1365{
1366 return !operator==(n);
1367}
1368
1369/*!
1370 Destroys the object and frees its resources.
1371*/
1372QDomNodeList::~QDomNodeList()
1373{
1374 if (impl && !impl->ref.deref())
1375 delete impl;
1376}
1377
1378/*!
1379 Returns the node at position \a index.
1380
1381 If \a index is negative or if \a index >= length() then a null
1382 node is returned (i.e. a node for which QDomNode::isNull() returns
1383 true).
1384
1385 \sa length()
1386*/
1387QDomNode QDomNodeList::item(int index) const
1388{
1389 if (!impl)
1390 return QDomNode();
1391
1392 return QDomNode(impl->item(index));
1393}
1394
1395/*!
1396 Returns the number of nodes in the list.
1397*/
1398uint QDomNodeList::length() const
1399{
1400 if (!impl)
1401 return 0;
1402 return impl->length();
1403}
1404
1405/*!
1406 \fn bool QDomNodeList::isEmpty() const
1407
1408 Returns true if the list contains no items; otherwise returns false.
1409 This function is provided for Qt API consistency.
1410*/
1411
1412/*!
1413 \fn int QDomNodeList::count() const
1414
1415 This function is provided for Qt API consistency. It is equivalent to length().
1416*/
1417
1418/*!
1419 \fn int QDomNodeList::size() const
1420
1421 This function is provided for Qt API consistency. It is equivalent to length().
1422*/
1423
1424/*!
1425 \fn QDomNode QDomNodeList::at(int index) const
1426
1427 This function is provided for Qt API consistency. It is equivalent
1428 to item().
1429
1430 If \a index is negative or if \a index >= length() then a null
1431 node is returned (i.e. a node for which QDomNode::isNull() returns
1432 true).
1433*/
1434
1435/**************************************************************
1436 *
1437 * QDomNodePrivate
1438 *
1439 **************************************************************/
1440
1441inline void QDomNodePrivate::setOwnerDocument(QDomDocumentPrivate *doc)
1442{
1443 ownerNode = doc;
1444 hasParent = false;
1445}
1446
1447QDomNodePrivate::QDomNodePrivate(QDomDocumentPrivate *doc, QDomNodePrivate *par)
1448{
1449 ref = 1;
1450 if (par)
1451 setParent(par);
1452 else
1453 setOwnerDocument(doc);
1454 prev = 0;
1455 next = 0;
1456 first = 0;
1457 last = 0;
1458 createdWithDom1Interface = true;
1459 lineNumber = -1;
1460 columnNumber = -1;
1461}
1462
1463QDomNodePrivate::QDomNodePrivate(QDomNodePrivate *n, bool deep)
1464{
1465 ref = 1;
1466 setOwnerDocument(n->ownerDocument());
1467 prev = 0;
1468 next = 0;
1469 first = 0;
1470 last = 0;
1471
1472 name = n->name;
1473 value = n->value;
1474 prefix = n->prefix;
1475 namespaceURI = n->namespaceURI;
1476 createdWithDom1Interface = n->createdWithDom1Interface;
1477 lineNumber = -1;
1478 columnNumber = -1;
1479
1480 if (!deep)
1481 return;
1482
1483 for (QDomNodePrivate* x = n->first; x; x = x->next)
1484 appendChild(x->cloneNode(true));
1485}
1486
1487QDomNodePrivate::~QDomNodePrivate()
1488{
1489 QDomNodePrivate* p = first;
1490 QDomNodePrivate* n;
1491
1492 while (p) {
1493 n = p->next;
1494 if (!p->ref.deref())
1495 delete p;
1496 else
1497 p->setNoParent();
1498 p = n;
1499 }
1500 first = 0;
1501 last = 0;
1502}
1503
1504void QDomNodePrivate::clear()
1505{
1506 QDomNodePrivate* p = first;
1507 QDomNodePrivate* n;
1508
1509 while (p) {
1510 n = p->next;
1511 if (!p->ref.deref())
1512 delete p;
1513 p = n;
1514 }
1515 first = 0;
1516 last = 0;
1517}
1518
1519QDomNodePrivate* QDomNodePrivate::namedItem(const QString &n)
1520{
1521 QDomNodePrivate* p = first;
1522 while (p) {
1523 if (p->nodeName() == n)
1524 return p;
1525 p = p->next;
1526 }
1527 return 0;
1528}
1529
1530
1531QDomNodePrivate* QDomNodePrivate::insertBefore(QDomNodePrivate* newChild, QDomNodePrivate* refChild)
1532{
1533 // Error check
1534 if (!newChild)
1535 return 0;
1536
1537 // Error check
1538 if (newChild == refChild)
1539 return 0;
1540
1541 // Error check
1542 if (refChild && refChild->parent() != this)
1543 return 0;
1544
1545 // "mark lists as dirty"
1546 QDomDocumentPrivate *const doc = ownerDocument();
1547 if(doc)
1548 doc->nodeListTime++;
1549
1550 // Special handling for inserting a fragment. We just insert
1551 // all elements of the fragment instead of the fragment itself.
1552 if (newChild->isDocumentFragment()) {
1553 // Fragment is empty ?
1554 if (newChild->first == 0)
1555 return newChild;
1556
1557 // New parent
1558 QDomNodePrivate* n = newChild->first;
1559 while (n) {
1560 n->setParent(this);
1561 n = n->next;
1562 }
1563
1564 // Insert at the beginning ?
1565 if (!refChild || refChild->prev == 0) {
1566 if (first)
1567 first->prev = newChild->last;
1568 newChild->last->next = first;
1569 if (!last)
1570 last = newChild->last;
1571 first = newChild->first;
1572 } else {
1573 // Insert in the middle
1574 newChild->last->next = refChild;
1575 newChild->first->prev = refChild->prev;
1576 refChild->prev->next = newChild->first;
1577 refChild->prev = newChild->last;
1578 }
1579
1580 // No need to increase the reference since QDomDocumentFragment
1581 // does not decrease the reference.
1582
1583 // Remove the nodes from the fragment
1584 newChild->first = 0;
1585 newChild->last = 0;
1586 return newChild;
1587 }
1588
1589 // No more errors can occur now, so we take
1590 // ownership of the node.
1591 newChild->ref.ref();
1592
1593 if (newChild->parent())
1594 newChild->parent()->removeChild(newChild);
1595
1596 newChild->setParent(this);
1597
1598 if (!refChild) {
1599 if (first)
1600 first->prev = newChild;
1601 newChild->next = first;
1602 if (!last)
1603 last = newChild;
1604 first = newChild;
1605 return newChild;
1606 }
1607
1608 if (refChild->prev == 0) {
1609 if (first)
1610 first->prev = newChild;
1611 newChild->next = first;
1612 if (!last)
1613 last = newChild;
1614 first = newChild;
1615 return newChild;
1616 }
1617
1618 newChild->next = refChild;
1619 newChild->prev = refChild->prev;
1620 refChild->prev->next = newChild;
1621 refChild->prev = newChild;
1622
1623 return newChild;
1624}
1625
1626QDomNodePrivate* QDomNodePrivate::insertAfter(QDomNodePrivate* newChild, QDomNodePrivate* refChild)
1627{
1628 // Error check
1629 if (!newChild)
1630 return 0;
1631
1632 // Error check
1633 if (newChild == refChild)
1634 return 0;
1635
1636 // Error check
1637 if (refChild && refChild->parent() != this)
1638 return 0;
1639
1640 // "mark lists as dirty"
1641 QDomDocumentPrivate *const doc = ownerDocument();
1642 if(doc)
1643 doc->nodeListTime++;
1644
1645 // Special handling for inserting a fragment. We just insert
1646 // all elements of the fragment instead of the fragment itself.
1647 if (newChild->isDocumentFragment()) {
1648 // Fragment is empty ?
1649 if (newChild->first == 0)
1650 return newChild;
1651
1652 // New parent
1653 QDomNodePrivate* n = newChild->first;
1654 while (n) {
1655 n->setParent(this);
1656 n = n->next;
1657 }
1658
1659 // Insert at the end
1660 if (!refChild || refChild->next == 0) {
1661 if (last)
1662 last->next = newChild->first;
1663 newChild->first->prev = last;
1664 if (!first)
1665 first = newChild->first;
1666 last = newChild->last;
1667 } else { // Insert in the middle
1668 newChild->first->prev = refChild;
1669 newChild->last->next = refChild->next;
1670 refChild->next->prev = newChild->last;
1671 refChild->next = newChild->first;
1672 }
1673
1674 // No need to increase the reference since QDomDocumentFragment
1675 // does not decrease the reference.
1676
1677 // Remove the nodes from the fragment
1678 newChild->first = 0;
1679 newChild->last = 0;
1680 return newChild;
1681 }
1682
1683 // Release new node from its current parent
1684 if (newChild->parent())
1685 newChild->parent()->removeChild(newChild);
1686
1687 // No more errors can occur now, so we take
1688 // ownership of the node
1689 newChild->ref.ref();
1690
1691 newChild->setParent(this);
1692
1693 // Insert at the end
1694 if (!refChild) {
1695 if (last)
1696 last->next = newChild;
1697 newChild->prev = last;
1698 if (!first)
1699 first = newChild;
1700 last = newChild;
1701 return newChild;
1702 }
1703
1704 if (refChild->next == 0) {
1705 if (last)
1706 last->next = newChild;
1707 newChild->prev = last;
1708 if (!first)
1709 first = newChild;
1710 last = newChild;
1711 return newChild;
1712 }
1713
1714 newChild->prev = refChild;
1715 newChild->next = refChild->next;
1716 refChild->next->prev = newChild;
1717 refChild->next = newChild;
1718
1719 return newChild;
1720}
1721
1722QDomNodePrivate* QDomNodePrivate::replaceChild(QDomNodePrivate* newChild, QDomNodePrivate* oldChild)
1723{
1724 if (!newChild || !oldChild)
1725 return 0;
1726 if (oldChild->parent() != this)
1727 return 0;
1728 if (newChild == oldChild)
1729 return 0;
1730
1731 // mark lists as dirty
1732 QDomDocumentPrivate *const doc = ownerDocument();
1733 if(doc)
1734 doc->nodeListTime++;
1735
1736 // Special handling for inserting a fragment. We just insert
1737 // all elements of the fragment instead of the fragment itself.
1738 if (newChild->isDocumentFragment()) {
1739 // Fragment is empty ?
1740 if (newChild->first == 0)
1741 return newChild;
1742
1743 // New parent
1744 QDomNodePrivate* n = newChild->first;
1745 while (n) {
1746 n->setParent(this);
1747 n = n->next;
1748 }
1749
1750
1751 if (oldChild->next)
1752 oldChild->next->prev = newChild->last;
1753 if (oldChild->prev)
1754 oldChild->prev->next = newChild->first;
1755
1756 newChild->last->next = oldChild->next;
1757 newChild->first->prev = oldChild->prev;
1758
1759 if (first == oldChild)
1760 first = newChild->first;
1761 if (last == oldChild)
1762 last = newChild->last;
1763
1764 oldChild->setNoParent();
1765 oldChild->next = 0;
1766 oldChild->prev = 0;
1767
1768 // No need to increase the reference since QDomDocumentFragment
1769 // does not decrease the reference.
1770
1771 // Remove the nodes from the fragment
1772 newChild->first = 0;
1773 newChild->last = 0;
1774
1775 // We are no longer interested in the old node
1776 if (oldChild)
1777 oldChild->ref.deref();
1778
1779 return oldChild;
1780 }
1781
1782 // No more errors can occur now, so we take
1783 // ownership of the node
1784 newChild->ref.ref();
1785
1786 // Release new node from its current parent
1787 if (newChild->parent())
1788 newChild->parent()->removeChild(newChild);
1789
1790 newChild->setParent(this);
1791
1792 if (oldChild->next)
1793 oldChild->next->prev = newChild;
1794 if (oldChild->prev)
1795 oldChild->prev->next = newChild;
1796
1797 newChild->next = oldChild->next;
1798 newChild->prev = oldChild->prev;
1799
1800 if (first == oldChild)
1801 first = newChild;
1802 if (last == oldChild)
1803 last = newChild;
1804
1805 oldChild->setNoParent();
1806 oldChild->next = 0;
1807 oldChild->prev = 0;
1808
1809 // We are no longer interested in the old node
1810 if (oldChild)
1811 oldChild->ref.deref();
1812
1813 return oldChild;
1814}
1815
1816QDomNodePrivate* QDomNodePrivate::removeChild(QDomNodePrivate* oldChild)
1817{
1818 // Error check
1819 if (oldChild->parent() != this)
1820 return 0;
1821
1822 // "mark lists as dirty"
1823 QDomDocumentPrivate *const doc = ownerDocument();
1824 if(doc)
1825 doc->nodeListTime++;
1826
1827 // Perhaps oldChild was just created with "createElement" or that. In this case
1828 // its parent is QDomDocument but it is not part of the documents child list.
1829 if (oldChild->next == 0 && oldChild->prev == 0 && first != oldChild)
1830 return 0;
1831
1832 if (oldChild->next)
1833 oldChild->next->prev = oldChild->prev;
1834 if (oldChild->prev)
1835 oldChild->prev->next = oldChild->next;
1836
1837 if (last == oldChild)
1838 last = oldChild->prev;
1839 if (first == oldChild)
1840 first = oldChild->next;
1841
1842 oldChild->setNoParent();
1843 oldChild->next = 0;
1844 oldChild->prev = 0;
1845
1846 // We are no longer interested in the old node
1847 oldChild->ref.deref();
1848
1849 return oldChild;
1850}
1851
1852QDomNodePrivate* QDomNodePrivate::appendChild(QDomNodePrivate* newChild)
1853{
1854 // No reference manipulation needed. Done in insertAfter.
1855 return insertAfter(newChild, 0);
1856}
1857
1858QDomDocumentPrivate* QDomNodePrivate::ownerDocument()
1859{
1860 QDomNodePrivate* p = this;
1861 while (p && !p->isDocument()) {
1862 if (!p->hasParent)
1863 return (QDomDocumentPrivate*)p->ownerNode;
1864 p = p->parent();
1865 }
1866
1867 return static_cast<QDomDocumentPrivate *>(p);
1868}
1869
1870QDomNodePrivate* QDomNodePrivate::cloneNode(bool deep)
1871{
1872 QDomNodePrivate* p = new QDomNodePrivate(this, deep);
1873 // We are not interested in this node
1874 p->ref.deref();
1875 return p;
1876}
1877
1878static void qNormalizeNode(QDomNodePrivate* n)
1879{
1880 QDomNodePrivate* p = n->first;
1881 QDomTextPrivate* t = 0;
1882
1883 while (p) {
1884 if (p->isText()) {
1885 if (t) {
1886 QDomNodePrivate* tmp = p->next;
1887 t->appendData(p->nodeValue());
1888 n->removeChild(p);
1889 p = tmp;
1890 } else {
1891 t = (QDomTextPrivate*)p;
1892 p = p->next;
1893 }
1894 } else {
1895 p = p->next;
1896 t = 0;
1897 }
1898 }
1899}
1900void QDomNodePrivate::normalize()
1901{
1902 // ### This one has moved from QDomElementPrivate to this position. It is
1903 // not tested.
1904 qNormalizeNode(this);
1905}
1906
1907/*! \internal
1908 \a depth is used for indentation, it seems.
1909 */
1910void QDomNodePrivate::save(QTextStream& s, int depth, int indent) const
1911{
1912 const QDomNodePrivate* n = first;
1913 while (n) {
1914 n->save(s, depth, indent);
1915 n = n->next;
1916 }
1917}
1918
1919void QDomNodePrivate::setLocation(int lineNumber, int columnNumber)
1920{
1921 this->lineNumber = lineNumber;
1922 this->columnNumber = columnNumber;
1923}
1924
1925/**************************************************************
1926 *
1927 * QDomNode
1928 *
1929 **************************************************************/
1930
1931#define IMPL ((QDomNodePrivate*)impl)
1932
1933/*!
1934 \class QDomNode
1935 \reentrant
1936 \brief The QDomNode class is the base class for all the nodes in a DOM tree.
1937
1938 \inmodule QtXml
1939 \ingroup xml-tools
1940
1941
1942 Many functions in the DOM return a QDomNode.
1943
1944 You can find out the type of a node using isAttr(),
1945 isCDATASection(), isDocumentFragment(), isDocument(),
1946 isDocumentType(), isElement(), isEntityReference(), isText(),
1947 isEntity(), isNotation(), isProcessingInstruction(),
1948 isCharacterData() and isComment().
1949
1950 A QDomNode can be converted into one of its subclasses using
1951 toAttr(), toCDATASection(), toDocumentFragment(), toDocument(),
1952 toDocumentType(), toElement(), toEntityReference(), toText(),
1953 toEntity(), toNotation(), toProcessingInstruction(),
1954 toCharacterData() or toComment(). You can convert a node to a null
1955 node with clear().
1956
1957 Copies of the QDomNode class share their data using explicit
1958 sharing. This means that modifying one node will change all
1959 copies. This is especially useful in combination with functions
1960 which return a QDomNode, e.g. firstChild(). You can make an
1961 independent (deep) copy of the node with cloneNode().
1962
1963 A QDomNode can be null, much like a null pointer. Creating a copy
1964 of a null node results in another null node. It is not
1965 possible to modify a null node, but it is possible to assign another,
1966 possibly non-null node to it. In this case, the copy of the null node
1967 will remain null. You can check if a QDomNode is null by calling isNull().
1968 The empty constructor of a QDomNode (or any of the derived classes) creates
1969 a null node.
1970
1971 Nodes are inserted with insertBefore(), insertAfter() or
1972 appendChild(). You can replace one node with another using
1973 replaceChild() and remove a node with removeChild().
1974
1975 To traverse nodes use firstChild() to get a node's first child (if
1976 any), and nextSibling() to traverse. QDomNode also provides
1977 lastChild(), previousSibling() and parentNode(). To find the first
1978 child node with a particular node name use namedItem().
1979
1980 To find out if a node has children use hasChildNodes() and to get
1981 a list of all of a node's children use childNodes().
1982
1983 The node's name and value (the meaning of which varies depending
1984 on its type) is returned by nodeName() and nodeValue()
1985 respectively. The node's type is returned by nodeType(). The
1986 node's value can be set with setNodeValue().
1987
1988 The document to which the node belongs is returned by
1989 ownerDocument().
1990
1991 Adjacent QDomText nodes can be merged into a single node with
1992 normalize().
1993
1994 \l QDomElement nodes have attributes which can be retrieved with
1995 attributes().
1996
1997 QDomElement and QDomAttr nodes can have namespaces which can be
1998 retrieved with namespaceURI(). Their local name is retrieved with
1999 localName(), and their prefix with prefix(). The prefix can be set
2000 with setPrefix().
2001
2002 You can write the XML representation of the node to a text stream
2003 with save().
2004
2005 The following example looks for the first element in an XML document and
2006 prints the names of all the elements that are its direct children.
2007 \snippet doc/src/snippets/code/src_xml_dom_qdom.cpp 1
2008
2009 For further information about the Document Object Model see
2010 \l{http://www.w3.org/TR/REC-DOM-Level-1/}{Level 1} and
2011 \l{http://www.w3.org/TR/DOM-Level-2-Core/}{Level 2 Core}.
2012 For a more general introduction of the DOM implementation see the
2013 QDomDocument documentation.
2014*/
2015
2016/*!
2017 Constructs a \link isNull() null\endlink node.
2018*/
2019QDomNode::QDomNode()
2020{
2021 impl = 0;
2022}
2023
2024/*!
2025 Constructs a copy of \a n.
2026
2027 The data of the copy is shared (shallow copy): modifying one node
2028 will also change the other. If you want to make a deep copy, use
2029 cloneNode().
2030*/
2031QDomNode::QDomNode(const QDomNode &n)
2032{
2033 impl = n.impl;
2034 if (impl)
2035 impl->ref.ref();
2036}
2037
2038/*! \internal
2039 Constructs a new node for the data \a n.
2040*/
2041QDomNode::QDomNode(QDomNodePrivate *n)
2042{
2043 impl = n;
2044 if (impl)
2045 impl->ref.ref();
2046}
2047
2048/*!
2049 Assigns a copy of \a n to this DOM node.
2050
2051 The data of the copy is shared (shallow copy): modifying one node
2052 will also change the other. If you want to make a deep copy, use
2053 cloneNode().
2054*/
2055QDomNode& QDomNode::operator=(const QDomNode &n)
2056{
2057 if (n.impl)
2058 n.impl->ref.ref();
2059 if (impl && !impl->ref.deref())
2060 delete impl;
2061 impl = n.impl;
2062 return *this;
2063}
2064
2065/*!
2066 Returns true if \a n and this DOM node are equal; otherwise
2067 returns false.
2068
2069 Any instance of QDomNode acts as a reference to an underlying data
2070 structure in QDomDocument. The test for equality checks if the two
2071 references point to the same underlying node. For example:
2072
2073 \snippet doc/src/snippets/code/src_xml_dom_qdom.cpp 2
2074
2075 The two nodes (QDomElement is a QDomNode subclass) both refer to
2076 the document's root element, and \c {element1 == element2} will
2077 return true. On the other hand:
2078
2079 \snippet doc/src/snippets/code/src_xml_dom_qdom.cpp 3
2080
2081 Even though both nodes are empty elements carrying the same name,
2082 \c {element3 == element4} will return false because they refer to
2083 two different nodes in the underlying data structure.
2084*/
2085bool QDomNode::operator== (const QDomNode& n) const
2086{
2087 return (impl == n.impl);
2088}
2089
2090/*!
2091 Returns true if \a n and this DOM node are not equal; otherwise
2092 returns false.
2093*/
2094bool QDomNode::operator!= (const QDomNode& n) const
2095{
2096 return (impl != n.impl);
2097}
2098
2099/*!
2100 Destroys the object and frees its resources.
2101*/
2102QDomNode::~QDomNode()
2103{
2104 if (impl && !impl->ref.deref())
2105 delete impl;
2106}
2107
2108/*!
2109 Returns the name of the node.
2110
2111 The meaning of the name depends on the subclass:
2112
2113 \table
2114 \header \i Name \i Meaning
2115 \row \i QDomAttr \i The name of the attribute
2116 \row \i QDomCDATASection \i The string "#cdata-section"
2117 \row \i QDomComment \i The string "#comment"
2118 \row \i QDomDocument \i The string "#document"
2119 \row \i QDomDocumentFragment \i The string "#document-fragment"
2120 \row \i QDomDocumentType \i The name of the document type
2121 \row \i QDomElement \i The tag name
2122 \row \i QDomEntity \i The name of the entity
2123 \row \i QDomEntityReference \i The name of the referenced entity
2124 \row \i QDomNotation \i The name of the notation
2125 \row \i QDomProcessingInstruction \i The target of the processing instruction
2126 \row \i QDomText \i The string "#text"
2127 \endtable
2128
2129 \bold{Note:} This function does not take the presence of namespaces into account
2130 when processing the names of element and attribute nodes. As a result, the
2131 returned name can contain any namespace prefix that may be present.
2132 To obtain the node name of an element or attribute, use localName(); to
2133 obtain the namespace prefix, use namespaceURI().
2134
2135 \sa nodeValue()
2136*/
2137QString QDomNode::nodeName() const
2138{
2139 if (!impl)
2140 return QString();
2141
2142 if (!IMPL->prefix.isEmpty())
2143 return IMPL->prefix + QLatin1Char(':') + IMPL->name;
2144 return IMPL->name;
2145}
2146
2147/*!
2148 Returns the value of the node.
2149
2150 The meaning of the value depends on the subclass:
2151 \table
2152 \header \i Name \i Meaning
2153 \row \i QDomAttr \i The attribute value
2154 \row \i QDomCDATASection \i The content of the CDATA section
2155 \row \i QDomComment \i The comment
2156 \row \i QDomProcessingInstruction \i The data of the processing instruction
2157 \row \i QDomText \i The text
2158 \endtable
2159
2160 All the other subclasses do not have a node value and will return
2161 an empty string.
2162
2163 \sa setNodeValue() nodeName()
2164*/
2165QString QDomNode::nodeValue() const
2166{
2167 if (!impl)
2168 return QString();
2169 return IMPL->value;
2170}
2171
2172/*!
2173 Sets the node's value to \a v.
2174
2175 \sa nodeValue()
2176*/
2177void QDomNode::setNodeValue(const QString& v)
2178{
2179 if (!impl)
2180 return;
2181 IMPL->setNodeValue(v);
2182}
2183
2184/*!
2185 \enum QDomNode::NodeType
2186
2187 This enum defines the type of the node:
2188 \value ElementNode
2189 \value AttributeNode
2190 \value TextNode
2191 \value CDATASectionNode
2192 \value EntityReferenceNode
2193 \value EntityNode
2194 \value ProcessingInstructionNode
2195 \value CommentNode
2196 \value DocumentNode
2197 \value DocumentTypeNode
2198 \value DocumentFragmentNode
2199 \value NotationNode
2200 \value BaseNode A QDomNode object, i.e. not a QDomNode subclass.
2201 \value CharacterDataNode
2202*/
2203
2204/*!
2205 Returns the type of the node.
2206
2207 \sa toAttr(), toCDATASection(), toDocumentFragment(),
2208 toDocument() toDocumentType(), toElement(), toEntityReference(),
2209 toText(), toEntity() toNotation(), toProcessingInstruction(),
2210 toCharacterData(), toComment()
2211*/
2212QDomNode::NodeType QDomNode::nodeType() const
2213{
2214 if (!impl)
2215 return QDomNode::BaseNode;
2216 return IMPL->nodeType();
2217}
2218
2219/*!
2220 Returns the parent node. If this node has no parent, a null node
2221 is returned (i.e. a node for which isNull() returns true).
2222*/
2223QDomNode QDomNode::parentNode() const
2224{
2225 if (!impl)
2226 return QDomNode();
2227 return QDomNode(IMPL->parent());
2228}
2229
2230/*!
2231 Returns a list of all direct child nodes.
2232
2233 Most often you will call this function on a QDomElement object.
2234
2235 For example, if the XML document looks like this:
2236 \snippet doc/src/snippets/code/src_xml_dom_qdom.cpp 4
2237 Then the list of child nodes for the "body"-element will contain
2238 the node created by the &lt;h1&gt; tag and the node created by the
2239 &lt;p&gt; tag.
2240
2241 The nodes in the list are not copied; so changing the nodes in the
2242 list will also change the children of this node.
2243
2244 \sa firstChild() lastChild()
2245*/
2246QDomNodeList QDomNode::childNodes() const
2247{
2248 if (!impl)
2249 return QDomNodeList();
2250 return QDomNodeList(new QDomNodeListPrivate(impl));
2251}
2252
2253/*!
2254 Returns the first child of the node. If there is no child node, a
2255 \link isNull() null node\endlink is returned. Changing the
2256 returned node will also change the node in the document tree.
2257
2258 \sa lastChild() childNodes()
2259*/
2260QDomNode QDomNode::firstChild() const
2261{
2262 if (!impl)
2263 return QDomNode();
2264 return QDomNode(IMPL->first);
2265}
2266
2267/*!
2268 Returns the last child of the node. If there is no child node, a
2269 \link isNull() null node\endlink is returned. Changing the
2270 returned node will also change the node in the document tree.
2271
2272 \sa firstChild() childNodes()
2273*/
2274QDomNode QDomNode::lastChild() const
2275{
2276 if (!impl)
2277 return QDomNode();
2278 return QDomNode(IMPL->last);
2279}
2280
2281/*!
2282 Returns the previous sibling in the document tree. Changing the
2283 returned node will also change the node in the document tree.
2284
2285 For example, if you have XML like this:
2286 \snippet doc/src/snippets/code/src_xml_dom_qdom.cpp 5
2287 and this QDomNode represents the &lt;p&gt; tag, previousSibling()
2288 will return the node representing the &lt;h1&gt; tag.
2289
2290 \sa nextSibling()
2291*/
2292QDomNode QDomNode::previousSibling() const
2293{
2294 if (!impl)
2295 return QDomNode();
2296 return QDomNode(IMPL->prev);
2297}
2298
2299/*!
2300 Returns the next sibling in the document tree. Changing the
2301 returned node will also change the node in the document tree.
2302
2303 If you have XML like this:
2304 \snippet doc/src/snippets/code/src_xml_dom_qdom.cpp 6
2305 and this QDomNode represents the <p> tag, nextSibling() will
2306 return the node representing the <h2> tag.
2307
2308 \sa previousSibling()
2309*/
2310QDomNode QDomNode::nextSibling() const
2311{
2312 if (!impl)
2313 return QDomNode();
2314 return QDomNode(IMPL->next);
2315}
2316
2317
2318// ###### don't think this is part of the DOM and
2319/*!
2320 Returns a named node map of all attributes. Attributes are only
2321 provided for \l{QDomElement}s.
2322
2323 Changing the attributes in the map will also change the attributes
2324 of this QDomNode.
2325*/
2326QDomNamedNodeMap QDomNode::attributes() const
2327{
2328 if (!impl || !impl->isElement())
2329 return QDomNamedNodeMap();
2330
2331 return QDomNamedNodeMap(static_cast<QDomElementPrivate *>(impl)->attributes());
2332}
2333
2334/*!
2335 Returns the document to which this node belongs.
2336*/
2337QDomDocument QDomNode::ownerDocument() const
2338{
2339 if (!impl)
2340 return QDomDocument();
2341 return QDomDocument(IMPL->ownerDocument());
2342}
2343
2344/*!
2345 Creates a deep (not shallow) copy of the QDomNode.
2346
2347 If \a deep is true, then the cloning is done recursively which
2348 means that all the node's children are deep copied too. If \a deep
2349 is false only the node itself is copied and the copy will have no
2350 child nodes.
2351*/
2352QDomNode QDomNode::cloneNode(bool deep) const
2353{
2354 if (!impl)
2355 return QDomNode();
2356 return QDomNode(IMPL->cloneNode(deep));
2357}
2358
2359/*!
2360 Calling normalize() on an element converts all its children into a
2361 standard form. This means that adjacent QDomText objects will be
2362 merged into a single text object (QDomCDATASection nodes are not
2363 merged).
2364*/
2365void QDomNode::normalize()
2366{
2367 if (!impl)
2368 return;
2369 IMPL->normalize();
2370}
2371
2372/*!
2373 Returns true if the DOM implementation implements the feature \a
2374 feature and this feature is supported by this node in the version
2375 \a version; otherwise returns false.
2376
2377 \sa QDomImplementation::hasFeature()
2378*/
2379bool QDomNode::isSupported(const QString& feature, const QString& version) const
2380{
2381 QDomImplementation i;
2382 return i.hasFeature(feature, version);
2383}
2384
2385/*!
2386 Returns the namespace URI of this node or an empty string if the
2387 node has no namespace URI.
2388
2389 Only nodes of type \link QDomNode::NodeType ElementNode\endlink or
2390 \link QDomNode::NodeType AttributeNode\endlink can have
2391 namespaces. A namespace URI must be specified at creation time and
2392 cannot be changed later.
2393
2394 \sa prefix() localName() QDomDocument::createElementNS()
2395 QDomDocument::createAttributeNS()
2396*/
2397QString QDomNode::namespaceURI() const
2398{
2399 if (!impl)
2400 return QString();
2401 return IMPL->namespaceURI;
2402}
2403
2404/*!
2405 Returns the namespace prefix of the node or an empty string if the
2406 node has no namespace prefix.
2407
2408 Only nodes of type \link QDomNode::NodeType ElementNode\endlink or
2409 \link QDomNode::NodeType AttributeNode\endlink can have
2410 namespaces. A namespace prefix must be specified at creation time.
2411 If a node was created with a namespace prefix, you can change it
2412 later with setPrefix().
2413
2414 If you create an element or attribute with
2415 QDomDocument::createElement() or QDomDocument::createAttribute(),
2416 the prefix will be an empty string. If you use
2417 QDomDocument::createElementNS() or
2418 QDomDocument::createAttributeNS() instead, the prefix will not be
2419 an empty string; but it might be an empty string if the name does
2420 not have a prefix.
2421
2422 \sa setPrefix() localName() namespaceURI()
2423 QDomDocument::createElementNS() QDomDocument::createAttributeNS()
2424*/
2425QString QDomNode::prefix() const
2426{
2427 if (!impl)
2428 return QString();
2429 return IMPL->prefix;
2430}
2431
2432/*!
2433 If the node has a namespace prefix, this function changes the
2434 namespace prefix of the node to \a pre. Otherwise this function
2435 does nothing.
2436
2437 Only nodes of type \link QDomNode::NodeType ElementNode\endlink or
2438 \link QDomNode::NodeType AttributeNode\endlink can have
2439 namespaces. A namespace prefix must have be specified at creation
2440 time; it is not possible to add a namespace prefix afterwards.
2441
2442 \sa prefix() localName() namespaceURI()
2443 QDomDocument::createElementNS() QDomDocument::createAttributeNS()
2444*/
2445void QDomNode::setPrefix(const QString& pre)
2446{
2447 if (!impl || IMPL->prefix.isNull())
2448 return;
2449 if (isAttr() || isElement())
2450 IMPL->prefix = pre;
2451}
2452
2453/*!
2454 If the node uses namespaces, this function returns the local name
2455 of the node; otherwise it returns an empty string.
2456
2457 Only nodes of type \link QDomNode::NodeType ElementNode\endlink or
2458 \link QDomNode::NodeType AttributeNode\endlink can have
2459 namespaces. A namespace must have been specified at creation time;
2460 it is not possible to add a namespace afterwards.
2461
2462 \sa prefix() namespaceURI() QDomDocument::createElementNS()
2463 QDomDocument::createAttributeNS()
2464*/
2465QString QDomNode::localName() const
2466{
2467 if (!impl || IMPL->createdWithDom1Interface)
2468 return QString();
2469 return IMPL->name;
2470}
2471
2472/*!
2473 Returns true if the node has attributes; otherwise returns false.
2474
2475 \sa attributes()
2476*/
2477bool QDomNode::hasAttributes() const
2478{
2479 if (!impl || !impl->isElement())
2480 return false;
2481 return static_cast<QDomElementPrivate *>(impl)->hasAttributes();
2482}
2483
2484/*!
2485 Inserts the node \a newChild before the child node \a refChild.
2486 \a refChild must be a direct child of this node. If \a refChild is
2487 \link isNull() null\endlink then \a newChild is inserted as the
2488 node's first child.
2489
2490 If \a newChild is the child of another node, it is reparented to
2491 this node. If \a newChild is a child of this node, then its
2492 position in the list of children is changed.
2493
2494 If \a newChild is a QDomDocumentFragment, then the children of the
2495 fragment are removed from the fragment and inserted before \a
2496 refChild.
2497
2498 Returns a new reference to \a newChild on success or a \link
2499 isNull() null node\endlink on failure.
2500
2501 The DOM specification disallow inserting attribute nodes, but due
2502 to historical reasons QDom accept them nevertheless.
2503
2504 \sa insertAfter() replaceChild() removeChild() appendChild()
2505*/
2506QDomNode QDomNode::insertBefore(const QDomNode& newChild, const QDomNode& refChild)
2507{
2508 if (!impl)
2509 return QDomNode();
2510 return QDomNode(IMPL->insertBefore(newChild.impl, refChild.impl));
2511}
2512
2513/*!
2514 Inserts the node \a newChild after the child node \a refChild. \a
2515 refChild must be a direct child of this node. If \a refChild is
2516 \link isNull() null\endlink then \a newChild is appended as this
2517 node's last child.
2518
2519 If \a newChild is the child of another node, it is reparented to
2520 this node. If \a newChild is a child of this node, then its
2521 position in the list of children is changed.
2522
2523 If \a newChild is a QDomDocumentFragment, then the children of the
2524 fragment are removed from the fragment and inserted after \a
2525 refChild.
2526
2527 Returns a new reference to \a newChild on success or a \link
2528 isNull() null node\endlink on failure.
2529
2530 The DOM specification disallow inserting attribute nodes, but due
2531 to historical reasons QDom accept them nevertheless.
2532
2533 \sa insertBefore() replaceChild() removeChild() appendChild()
2534*/
2535QDomNode QDomNode::insertAfter(const QDomNode& newChild, const QDomNode& refChild)
2536{
2537 if (!impl)
2538 return QDomNode();
2539 return QDomNode(IMPL->insertAfter(newChild.impl, refChild.impl));
2540}
2541
2542/*!
2543 Replaces \a oldChild with \a newChild. \a oldChild must be a
2544 direct child of this node.
2545
2546 If \a newChild is the child of another node, it is reparented to
2547 this node. If \a newChild is a child of this node, then its
2548 position in the list of children is changed.
2549
2550 If \a newChild is a QDomDocumentFragment, then \a oldChild is
2551 replaced by all of the children of the fragment.
2552
2553 Returns a new reference to \a oldChild on success or a \link
2554 isNull() null node\endlink an failure.
2555
2556 \sa insertBefore() insertAfter() removeChild() appendChild()
2557*/
2558QDomNode QDomNode::replaceChild(const QDomNode& newChild, const QDomNode& oldChild)
2559{
2560 if (!impl || !newChild.impl || !oldChild.impl)
2561 return QDomNode();
2562 return QDomNode(IMPL->replaceChild(newChild.impl, oldChild.impl));
2563}
2564
2565/*!
2566 Removes \a oldChild from the list of children. \a oldChild must be
2567 a direct child of this node.
2568
2569 Returns a new reference to \a oldChild on success or a \link
2570 isNull() null node\endlink on failure.
2571
2572 \sa insertBefore() insertAfter() replaceChild() appendChild()
2573*/
2574QDomNode QDomNode::removeChild(const QDomNode& oldChild)
2575{
2576 if (!impl)
2577 return QDomNode();
2578
2579 if (oldChild.isNull())
2580 return QDomNode();
2581
2582 return QDomNode(IMPL->removeChild(oldChild.impl));
2583}
2584
2585/*!
2586 Appends \a newChild as the node's last child.
2587
2588 If \a newChild is the child of another node, it is reparented to
2589 this node. If \a newChild is a child of this node, then its
2590 position in the list of children is changed.
2591
2592 If \a newChild is a QDomDocumentFragment, then the children of the
2593 fragment are removed from the fragment and appended.
2594
2595 If \a newChild is a QDomElement and this node is a QDomDocument that
2596 already has an element node as a child, \a newChild is not added as
2597 a child and a null node is returned.
2598
2599 Returns a new reference to \a newChild on success or a \link
2600 isNull() null node\endlink on failure.
2601
2602 Calling this function on a null node(created, for example, with
2603 the default constructor) does nothing and returns a \link isNull()
2604 null node\endlink.
2605
2606 The DOM specification disallow inserting attribute nodes, but for
2607 historical reasons, QDom accepts them anyway.
2608
2609 \sa insertBefore() insertAfter() replaceChild() removeChild()
2610*/
2611QDomNode QDomNode::appendChild(const QDomNode& newChild)
2612{
2613 if (!impl) {
2614 qWarning("Calling appendChild() on a null node does nothing.");
2615 return QDomNode();
2616 }
2617 return QDomNode(IMPL->appendChild(newChild.impl));
2618}
2619
2620/*!
2621 Returns true if the node has one or more children; otherwise
2622 returns false.
2623*/
2624bool QDomNode::hasChildNodes() const
2625{
2626 if (!impl)
2627 return false;
2628 return IMPL->first != 0;
2629}
2630
2631/*!
2632 Returns true if this node is null (i.e. if it has no type or
2633 contents); otherwise returns false.
2634*/
2635bool QDomNode::isNull() const
2636{
2637 return (impl == 0);
2638}
2639
2640/*!
2641 Converts the node into a null node; if it was not a null node
2642 before, its type and contents are deleted.
2643
2644 \sa isNull()
2645*/
2646void QDomNode::clear()
2647{
2648 if (impl && !impl->ref.deref())
2649 delete impl;
2650 impl = 0;
2651}
2652
2653/*!
2654 Returns the first direct child node for which nodeName() equals \a
2655 name.
2656
2657 If no such direct child exists, a \link isNull() null node\endlink
2658 is returned.
2659
2660 \sa nodeName()
2661*/
2662QDomNode QDomNode::namedItem(const QString& name) const
2663{
2664 if (!impl)
2665 return QDomNode();
2666 return QDomNode(impl->namedItem(name));
2667}
2668
2669/*!
2670 Writes the XML representation of the node and all its children to
2671 the stream \a str. This function uses \a indent as the amount of
2672 space to indent the node.
2673
2674 If this node is a document node, the encoding of text stream \a str's encoding is
2675 set by treating a processing instruction by name "xml" as an XML declaration, if such a one exists,
2676 and otherwise defaults to UTF-8. XML declarations are not processing instructions, but this
2677 behavior exists for historical reasons. If this node is not a document node,
2678 the text stream's encoding is used.
2679
2680 If the document contains invalid XML characters or characters that cannot be
2681 encoded in the given encoding, the result and behavior is undefined.
2682
2683*/
2684void QDomNode::save(QTextStream& str, int indent) const
2685{
2686 save(str, indent, QDomNode::EncodingFromDocument);
2687}
2688
2689/*!
2690 If \a encodingPolicy is QDomNode::EncodingFromDocument, this function behaves as save(QTextStream &str, int indent).
2691
2692 If \a encodingPolicy is EncodingFromTextStream and this node is a document node, this
2693 function behaves as save(QTextStream &str, int indent) with the exception that the encoding
2694 specified in the text stream \a str is used.
2695
2696 If the document contains invalid XML characters or characters that cannot be
2697 encoded in the given encoding, the result and behavior is undefined.
2698
2699 \since 4.2
2700 */
2701void QDomNode::save(QTextStream& str, int indent, EncodingPolicy encodingPolicy) const
2702{
2703 if (!impl)
2704 return;
2705
2706 if(isDocument())
2707 static_cast<const QDomDocumentPrivate *>(impl)->saveDocument(str, indent, encodingPolicy);
2708 else
2709 IMPL->save(str, 1, indent);
2710}
2711
2712/*!
2713 \relates QDomNode
2714
2715 Writes the XML representation of the node \a node and all its
2716 children to the stream \a str.
2717*/
2718QTextStream& operator<<(QTextStream& str, const QDomNode& node)
2719{
2720 node.save(str, 1);
2721
2722 return str;
2723}
2724
2725/*!
2726 Returns true if the node is an attribute; otherwise returns false.
2727
2728 If this function returns true, it does not imply that this object
2729 is a QDomAttribute; you can get the QDomAttribute with
2730 toAttribute().
2731
2732 \sa toAttr()
2733*/
2734bool QDomNode::isAttr() const
2735{
2736 if(impl)
2737 return impl->isAttr();
2738 return false;
2739}
2740
2741/*!
2742 Returns true if the node is a CDATA section; otherwise returns
2743 false.
2744
2745 If this function returns true, it does not imply that this object
2746 is a QDomCDATASection; you can get the QDomCDATASection with
2747 toCDATASection().
2748
2749 \sa toCDATASection()
2750*/
2751bool QDomNode::isCDATASection() const
2752{
2753 if(impl)
2754 return impl->isCDATASection();
2755 return false;
2756}
2757
2758/*!
2759 Returns true if the node is a document fragment; otherwise returns
2760 false.
2761
2762 If this function returns true, it does not imply that this object
2763 is a QDomDocumentFragment; you can get the QDomDocumentFragment
2764 with toDocumentFragment().
2765
2766 \sa toDocumentFragment()
2767*/
2768bool QDomNode::isDocumentFragment() const
2769{
2770 if(impl)
2771 return impl->isDocumentFragment();
2772 return false;
2773}
2774
2775/*!
2776 Returns true if the node is a document; otherwise returns false.
2777
2778 If this function returns true, it does not imply that this object
2779 is a QDomDocument; you can get the QDomDocument with toDocument().
2780
2781 \sa toDocument()
2782*/
2783bool QDomNode::isDocument() const
2784{
2785 if(impl)
2786 return impl->isDocument();
2787 return false;
2788}
2789
2790/*!
2791 Returns true if the node is a document type; otherwise returns
2792 false.
2793
2794 If this function returns true, it does not imply that this object
2795 is a QDomDocumentType; you can get the QDomDocumentType with
2796 toDocumentType().
2797
2798 \sa toDocumentType()
2799*/
2800bool QDomNode::isDocumentType() const
2801{
2802 if(impl)
2803 return impl->isDocumentType();
2804 return false;
2805}
2806
2807/*!
2808 Returns true if the node is an element; otherwise returns false.
2809
2810 If this function returns true, it does not imply that this object
2811 is a QDomElement; you can get the QDomElement with toElement().
2812
2813 \sa toElement()
2814*/
2815bool QDomNode::isElement() const
2816{
2817 if(impl)
2818 return impl->isElement();
2819 return false;
2820}
2821
2822/*!
2823 Returns true if the node is an entity reference; otherwise returns
2824 false.
2825
2826 If this function returns true, it does not imply that this object
2827 is a QDomEntityReference; you can get the QDomEntityReference with
2828 toEntityReference().
2829
2830 \sa toEntityReference()
2831*/
2832bool QDomNode::isEntityReference() const
2833{
2834 if(impl)
2835 return impl->isEntityReference();
2836 return false;
2837}
2838
2839/*!
2840 Returns true if the node is a text node; otherwise returns false.
2841
2842 If this function returns true, it does not imply that this object
2843 is a QDomText; you can get the QDomText with toText().
2844
2845 \sa toText()
2846*/
2847bool QDomNode::isText() const
2848{
2849 if(impl)
2850 return impl->isText();
2851 return false;
2852}
2853
2854/*!
2855 Returns true if the node is an entity; otherwise returns false.
2856
2857 If this function returns true, it does not imply that this object
2858 is a QDomEntity; you can get the QDomEntity with toEntity().
2859
2860 \sa toEntity()
2861*/
2862bool QDomNode::isEntity() const
2863{
2864 if(impl)
2865 return impl->isEntity();
2866 return false;
2867}
2868
2869/*!
2870 Returns true if the node is a notation; otherwise returns false.
2871
2872 If this function returns true, it does not imply that this object
2873 is a QDomNotation; you can get the QDomNotation with toNotation().
2874
2875 \sa toNotation()
2876*/
2877bool QDomNode::isNotation() const
2878{
2879 if(impl)
2880 return impl->isNotation();
2881 return false;
2882}
2883
2884/*!
2885 Returns true if the node is a processing instruction; otherwise
2886 returns false.
2887
2888 If this function returns true, it does not imply that this object
2889 is a QDomProcessingInstruction; you can get the
2890 QProcessingInstruction with toProcessingInstruction().
2891
2892 \sa toProcessingInstruction()
2893*/
2894bool QDomNode::isProcessingInstruction() const
2895{
2896 if(impl)
2897 return impl->isProcessingInstruction();
2898 return false;
2899}
2900
2901/*!
2902 Returns true if the node is a character data node; otherwise
2903 returns false.
2904
2905 If this function returns true, it does not imply that this object
2906 is a QDomCharacterData; you can get the QDomCharacterData with
2907 toCharacterData().
2908
2909 \sa toCharacterData()
2910*/
2911bool QDomNode::isCharacterData() const
2912{
2913 if (impl)
2914 return impl->isCharacterData();
2915 return false;
2916}
2917
2918/*!
2919 Returns true if the node is a comment; otherwise returns false.
2920
2921 If this function returns true, it does not imply that this object
2922 is a QDomComment; you can get the QDomComment with toComment().
2923
2924 \sa toComment()
2925*/
2926bool QDomNode::isComment() const
2927{
2928 if (impl)
2929 return impl->isComment();
2930 return false;
2931}
2932
2933#undef IMPL
2934
2935/*!
2936 Returns the first child element with tag name \a tagName if tagName is non-empty;
2937 otherwise returns the first child element. Returns a null element if no
2938 such child exists.
2939
2940 \sa lastChildElement() previousSiblingElement() nextSiblingElement()
2941*/
2942
2943QDomElement QDomNode::firstChildElement(const QString &tagName) const
2944{
2945 for (QDomNode child = firstChild(); !child.isNull(); child = child.nextSibling()) {
2946 if (child.isElement()) {
2947 QDomElement elt = child.toElement();
2948 if (tagName.isEmpty() || elt.tagName() == tagName)
2949 return elt;
2950 }
2951 }
2952 return QDomElement();
2953}
2954
2955/*!
2956 Returns the last child element with tag name \a tagName if tagName is non-empty;
2957 otherwise returns the first child element. Returns a null element if no
2958 such child exists.
2959
2960 \sa firstChildElement() previousSiblingElement() nextSiblingElement()
2961*/
2962
2963QDomElement QDomNode::lastChildElement(const QString &tagName) const
2964{
2965 for (QDomNode child = lastChild(); !child.isNull(); child = child.previousSibling()) {
2966 if (child.isElement()) {
2967 QDomElement elt = child.toElement();
2968 if (tagName.isEmpty() || elt.tagName() == tagName)
2969 return elt;
2970 }
2971 }
2972 return QDomElement();
2973}
2974
2975/*!
2976 Returns the next sibilng element with tag name \a tagName if \a tagName
2977 is non-empty; otherwise returns any next sibling element.
2978 Returns a null element if no such sibling exists.
2979
2980 \sa firstChildElement() previousSiblingElement() lastChildElement()
2981*/
2982
2983QDomElement QDomNode::nextSiblingElement(const QString &tagName) const
2984{
2985 for (QDomNode sib = nextSibling(); !sib.isNull(); sib = sib.nextSibling()) {
2986 if (sib.isElement()) {
2987 QDomElement elt = sib.toElement();
2988 if (tagName.isEmpty() || elt.tagName() == tagName)
2989 return elt;
2990 }
2991 }
2992 return QDomElement();
2993}
2994
2995/*!
2996 Returns the previous sibilng element with tag name \a tagName if \a tagName
2997 is non-empty; otherwise returns any previous sibling element.
2998 Returns a null element if no such sibling exists.
2999
3000 \sa firstChildElement(), nextSiblingElement(), lastChildElement()
3001*/
3002
3003QDomElement QDomNode::previousSiblingElement(const QString &tagName) const
3004{
3005 for (QDomNode sib = previousSibling(); !sib.isNull(); sib = sib.previousSibling()) {
3006 if (sib.isElement()) {
3007 QDomElement elt = sib.toElement();
3008 if (tagName.isEmpty() || elt.tagName() == tagName)
3009 return elt;
3010 }
3011 }
3012 return QDomElement();
3013}
3014
3015/*!
3016 \since 4.1
3017
3018 For nodes created by QDomDocument::setContent(), this function
3019 returns the line number in the XML document where the node was parsed.
3020 Otherwise, -1 is returned.
3021
3022 \sa columnNumber(), QDomDocument::setContent()
3023*/
3024int QDomNode::lineNumber() const
3025{
3026 return impl ? impl->lineNumber : -1;
3027}
3028
3029/*!
3030 \since 4.1
3031
3032 For nodes created by QDomDocument::setContent(), this function
3033 returns the column number in the XML document where the node was parsed.
3034 Otherwise, -1 is returned.
3035
3036 \sa lineNumber(), QDomDocument::setContent()
3037*/
3038int QDomNode::columnNumber() const
3039{
3040 return impl ? impl->columnNumber : -1;
3041}
3042
3043
3044/**************************************************************
3045 *
3046 * QDomNamedNodeMapPrivate
3047 *
3048 **************************************************************/
3049
3050QDomNamedNodeMapPrivate::QDomNamedNodeMapPrivate(QDomNodePrivate* n)
3051{
3052 ref = 1;
3053 readonly = false;
3054 parent = n;
3055 appendToParent = false;
3056}
3057
3058QDomNamedNodeMapPrivate::~QDomNamedNodeMapPrivate()
3059{
3060 clearMap();
3061}
3062
3063QDomNamedNodeMapPrivate* QDomNamedNodeMapPrivate::clone(QDomNodePrivate* p)
3064{
3065 QScopedPointer<QDomNamedNodeMapPrivate> m(new QDomNamedNodeMapPrivate(p));
3066 m->readonly = readonly;
3067 m->appendToParent = appendToParent;
3068
3069 QHash<QString, QDomNodePrivate*>::const_iterator it = map.constBegin();
3070 for (; it != map.constEnd(); ++it) {
3071 QDomNodePrivate *new_node = (*it)->cloneNode();
3072 new_node->setParent(p);
3073 m->setNamedItem(new_node);
3074 }
3075
3076 // we are no longer interested in ownership
3077 m->ref.deref();
3078 return m.take();
3079}
3080
3081void QDomNamedNodeMapPrivate::clearMap()
3082{
3083 // Dereference all of our children if we took references
3084 if (!appendToParent) {
3085 QHash<QString, QDomNodePrivate *>::const_iterator it = map.constBegin();
3086 for (; it != map.constEnd(); ++it)
3087 if (!(*it)->ref.deref())
3088 delete *it;
3089 }
3090 map.clear();
3091}
3092
3093QDomNodePrivate* QDomNamedNodeMapPrivate::namedItem(const QString& name) const
3094{
3095 QDomNodePrivate* p = map[name];
3096 return p;
3097}
3098
3099QDomNodePrivate* QDomNamedNodeMapPrivate::namedItemNS(const QString& nsURI, const QString& localName) const
3100{
3101 QHash<QString, QDomNodePrivate *>::const_iterator it = map.constBegin();
3102 QDomNodePrivate *n;
3103 for (; it != map.constEnd(); ++it) {
3104 n = *it;
3105 if (!n->prefix.isNull()) {
3106 // node has a namespace
3107 if (n->namespaceURI == nsURI && n->name == localName)
3108 return n;
3109 }
3110 }
3111 return 0;
3112}
3113
3114QDomNodePrivate* QDomNamedNodeMapPrivate::setNamedItem(QDomNodePrivate* arg)
3115{
3116 if (readonly || !arg)
3117 return 0;
3118
3119 if (appendToParent)
3120 return parent->appendChild(arg);
3121
3122 QDomNodePrivate *n = map.value(arg->nodeName());
3123 // We take a reference
3124 arg->ref.ref();
3125 map.insertMulti(arg->nodeName(), arg);
3126 return n;
3127}
3128
3129QDomNodePrivate* QDomNamedNodeMapPrivate::setNamedItemNS(QDomNodePrivate* arg)
3130{
3131 if (readonly || !arg)
3132 return 0;
3133
3134 if (appendToParent)
3135 return parent->appendChild(arg);
3136
3137 if (!arg->prefix.isNull()) {
3138 // node has a namespace
3139 QDomNodePrivate *n = namedItemNS(arg->namespaceURI, arg->name);
3140 // We take a reference
3141 arg->ref.ref();
3142 map.insertMulti(arg->nodeName(), arg);
3143 return n;
3144 } else {
3145 // ### check the following code if it is ok
3146 return setNamedItem(arg);
3147 }
3148}
3149
3150QDomNodePrivate* QDomNamedNodeMapPrivate::removeNamedItem(const QString& name)
3151{
3152 if (readonly)
3153 return 0;
3154
3155 QDomNodePrivate* p = namedItem(name);
3156 if (p == 0)
3157 return 0;
3158 if (appendToParent)
3159 return parent->removeChild(p);
3160
3161 map.remove(p->nodeName());
3162 // We took a reference, so we have to free one here
3163 p->ref.deref();
3164 return p;
3165}
3166
3167QDomNodePrivate* QDomNamedNodeMapPrivate::item(int index) const
3168{
3169 if ((uint)index >= length())
3170 return 0;
3171 return *(map.constBegin() + index);
3172}
3173
3174// ### Qt 5: convert all length/size() functions in QDom to use int instead of uint.
3175uint QDomNamedNodeMapPrivate::length() const
3176{
3177 return map.count();
3178}
3179
3180bool QDomNamedNodeMapPrivate::contains(const QString& name) const
3181{
3182 return map.value(name) != 0;
3183}
3184
3185bool QDomNamedNodeMapPrivate::containsNS(const QString& nsURI, const QString & localName) const
3186{
3187 return namedItemNS(nsURI, localName) != 0;
3188}
3189
3190/**************************************************************
3191 *
3192 * QDomNamedNodeMap
3193 *
3194 **************************************************************/
3195
3196#define IMPL ((QDomNamedNodeMapPrivate*)impl)
3197
3198/*!
3199 \class QDomNamedNodeMap
3200 \reentrant
3201 \brief The QDomNamedNodeMap class contains a collection of nodes
3202 that can be accessed by name.
3203
3204 \inmodule QtXml
3205 \ingroup xml-tools
3206
3207 Note that QDomNamedNodeMap does not inherit from QDomNodeList.
3208 QDomNamedNodeMaps do not provide any specific node ordering.
3209 Although nodes in a QDomNamedNodeMap may be accessed by an ordinal
3210 index, this is simply to allow a convenient enumeration of the
3211 contents of a QDomNamedNodeMap, and does not imply that the DOM
3212 specifies an ordering of the nodes.
3213
3214 The QDomNamedNodeMap is used in three places:
3215 \list 1
3216 \i QDomDocumentType::entities() returns a map of all entities
3217 described in the DTD.
3218 \i QDomDocumentType::notations() returns a map of all notations
3219 described in the DTD.
3220 \i QDomNode::attributes() returns a map of all attributes of an
3221 element.
3222 \endlist
3223
3224 Items in the map are identified by the name which QDomNode::name()
3225 returns. Nodes are retrieved using namedItem(), namedItemNS() or
3226 item(). New nodes are inserted with setNamedItem() or
3227 setNamedItemNS() and removed with removeNamedItem() or
3228 removeNamedItemNS(). Use contains() to see if an item with the
3229 given name is in the named node map. The number of items is
3230 returned by length().
3231
3232 Terminology: in this class we use "item" and "node"
3233 interchangeably.
3234*/
3235
3236/*!
3237 Constructs an empty named node map.
3238*/
3239QDomNamedNodeMap::QDomNamedNodeMap()
3240{
3241 impl = 0;
3242}
3243
3244/*!
3245 Constructs a copy of \a n.
3246*/
3247QDomNamedNodeMap::QDomNamedNodeMap(const QDomNamedNodeMap &n)
3248{
3249 impl = n.impl;
3250 if (impl)
3251 impl->ref.ref();
3252}
3253
3254QDomNamedNodeMap::QDomNamedNodeMap(QDomNamedNodeMapPrivate *n)
3255{
3256 impl = n;
3257 if (impl)
3258 impl->ref.ref();
3259}
3260
3261/*!
3262 Assigns \a n to this named node map.
3263*/
3264QDomNamedNodeMap& QDomNamedNodeMap::operator=(const QDomNamedNodeMap &n)
3265{
3266 if (n.impl)
3267 n.impl->ref.ref();
3268 if (impl && !impl->ref.deref())
3269 delete impl;
3270 impl = n.impl;
3271 return *this;
3272}
3273
3274/*!
3275 Returns true if \a n and this named node map are equal; otherwise
3276 returns false.
3277*/
3278bool QDomNamedNodeMap::operator== (const QDomNamedNodeMap& n) const
3279{
3280 return (impl == n.impl);
3281}
3282
3283/*!
3284 Returns true if \a n and this named node map are not equal;
3285 otherwise returns false.
3286*/
3287bool QDomNamedNodeMap::operator!= (const QDomNamedNodeMap& n) const
3288{
3289 return (impl != n.impl);
3290}
3291
3292/*!
3293 Destroys the object and frees its resources.
3294*/
3295QDomNamedNodeMap::~QDomNamedNodeMap()
3296{
3297 if (impl && !impl->ref.deref())
3298 delete impl;
3299}
3300
3301/*!
3302 Returns the node called \a name.
3303
3304 If the named node map does not contain such a node, a \link
3305 QDomNode::isNull() null node\endlink is returned. A node's name is
3306 the name returned by QDomNode::nodeName().
3307
3308 \sa setNamedItem() namedItemNS()
3309*/
3310QDomNode QDomNamedNodeMap::namedItem(const QString& name) const
3311{
3312 if (!impl)
3313 return QDomNode();
3314 return QDomNode(IMPL->namedItem(name));
3315}
3316
3317/*!
3318 Inserts the node \a newNode into the named node map. The name used
3319 by the map is the node name of \a newNode as returned by
3320 QDomNode::nodeName().
3321
3322 If the new node replaces an existing node, i.e. the map contains a
3323 node with the same name, the replaced node is returned.
3324
3325 \sa namedItem() removeNamedItem() setNamedItemNS()
3326*/
3327QDomNode QDomNamedNodeMap::setNamedItem(const QDomNode& newNode)
3328{
3329 if (!impl)
3330 return QDomNode();
3331 return QDomNode(IMPL->setNamedItem((QDomNodePrivate*)newNode.impl));
3332}
3333
3334/*!
3335 Removes the node called \a name from the map.
3336
3337 The function returns the removed node or a \link
3338 QDomNode::isNull() null node\endlink if the map did not contain a
3339 node called \a name.
3340
3341 \sa setNamedItem() namedItem() removeNamedItemNS()
3342*/
3343QDomNode QDomNamedNodeMap::removeNamedItem(const QString& name)
3344{
3345 if (!impl)
3346 return QDomNode();
3347 return QDomNode(IMPL->removeNamedItem(name));
3348}
3349
3350/*!
3351 Retrieves the node at position \a index.
3352
3353 This can be used to iterate over the map. Note that the nodes in
3354 the map are ordered arbitrarily.
3355
3356 \sa length()
3357*/
3358QDomNode QDomNamedNodeMap::item(int index) const
3359{
3360 if (!impl)
3361 return QDomNode();
3362 return QDomNode(IMPL->item(index));
3363}
3364
3365/*!
3366 Returns the node associated with the local name \a localName and
3367 the namespace URI \a nsURI.
3368
3369 If the map does not contain such a node, a \link
3370 QDomNode::isNull() null node\endlink is returned.
3371
3372 \sa setNamedItemNS() namedItem()
3373*/
3374QDomNode QDomNamedNodeMap::namedItemNS(const QString& nsURI, const QString& localName) const
3375{
3376 if (!impl)
3377 return QDomNode();
3378 return QDomNode(IMPL->namedItemNS(nsURI, localName));
3379}
3380
3381/*!
3382 Inserts the node \a newNode in the map. If a node with the same
3383 namespace URI and the same local name already exists in the map,
3384 it is replaced by \a newNode. If the new node replaces an existing
3385 node, the replaced node is returned.
3386
3387 \sa namedItemNS() removeNamedItemNS() setNamedItem()
3388*/
3389QDomNode QDomNamedNodeMap::setNamedItemNS(const QDomNode& newNode)
3390{
3391 if (!impl)
3392 return QDomNode();
3393 return QDomNode(IMPL->setNamedItemNS((QDomNodePrivate*)newNode.impl));
3394}
3395
3396/*!
3397 Removes the node with the local name \a localName and the
3398 namespace URI \a nsURI from the map.
3399
3400 The function returns the removed node or a \link
3401 QDomNode::isNull() null node\endlink if the map did not contain a
3402 node with the local name \a localName and the namespace URI \a
3403 nsURI.
3404
3405 \sa setNamedItemNS() namedItemNS() removeNamedItem()
3406*/
3407QDomNode QDomNamedNodeMap::removeNamedItemNS(const QString& nsURI, const QString& localName)
3408{
3409 if (!impl)
3410 return QDomNode();
3411 QDomNodePrivate *n = IMPL->namedItemNS(nsURI, localName);
3412 if (!n)
3413 return QDomNode();
3414 return QDomNode(IMPL->removeNamedItem(n->name));
3415}
3416
3417/*!
3418 Returns the number of nodes in the map.
3419
3420 \sa item()
3421*/
3422uint QDomNamedNodeMap::length() const
3423{
3424 if (!impl)
3425 return 0;
3426 return IMPL->length();
3427}
3428
3429/*!
3430 \fn bool QDomNamedNodeMap::isEmpty() const
3431
3432 Returns true if the map is empty; otherwise returns false. This function is
3433 provided for Qt API consistency.
3434*/
3435
3436/*!
3437 \fn int QDomNamedNodeMap::count() const
3438
3439 This function is provided for Qt API consistency. It is equivalent to length().
3440*/
3441
3442/*!
3443 \fn int QDomNamedNodeMap::size() const
3444
3445 This function is provided for Qt API consistency. It is equivalent to length().
3446*/
3447
3448/*!
3449 Returns true if the map contains a node called \a name; otherwise
3450 returns false.
3451
3452 \bold{Note:} This function does not take the presence of namespaces into account.
3453 Use namedItemNS() to test whether the map contains a node with a specific namespace
3454 URI and name.
3455*/
3456bool QDomNamedNodeMap::contains(const QString& name) const
3457{
3458 if (!impl)
3459 return false;
3460 return IMPL->contains(name);
3461}
3462
3463#undef IMPL
3464
3465/**************************************************************
3466 *
3467 * QDomDocumentTypePrivate
3468 *
3469 **************************************************************/
3470
3471QDomDocumentTypePrivate::QDomDocumentTypePrivate(QDomDocumentPrivate* doc, QDomNodePrivate* parent)
3472 : QDomNodePrivate(doc, parent)
3473{
3474 init();
3475}
3476
3477QDomDocumentTypePrivate::QDomDocumentTypePrivate(QDomDocumentTypePrivate* n, bool deep)
3478 : QDomNodePrivate(n, deep)
3479{
3480 init();
3481 // Refill the maps with our new children
3482 QDomNodePrivate* p = first;
3483 while (p) {
3484 if (p->isEntity())
3485 // Dont use normal insert function since we would create infinite recursion
3486 entities->map.insertMulti(p->nodeName(), p);
3487 if (p->isNotation())
3488 // Dont use normal insert function since we would create infinite recursion
3489 notations->map.insertMulti(p->nodeName(), p);
3490 }
3491}
3492
3493QDomDocumentTypePrivate::~QDomDocumentTypePrivate()
3494{
3495 if (!entities->ref.deref())
3496 delete entities;
3497 if (!notations->ref.deref())
3498 delete notations;
3499}
3500
3501void QDomDocumentTypePrivate::init()
3502{
3503 entities = new QDomNamedNodeMapPrivate(this);
3504 QT_TRY {
3505 notations = new QDomNamedNodeMapPrivate(this);
3506 publicId.clear();
3507 systemId.clear();
3508 internalSubset.clear();
3509
3510 entities->setAppendToParent(true);
3511 notations->setAppendToParent(true);
3512 } QT_CATCH(...) {
3513 delete entities;
3514 QT_RETHROW;
3515 }
3516}
3517
3518QDomNodePrivate* QDomDocumentTypePrivate::cloneNode(bool deep)
3519{
3520 QDomNodePrivate* p = new QDomDocumentTypePrivate(this, deep);
3521 // We are not interested in this node
3522 p->ref.deref();
3523 return p;
3524}
3525
3526QDomNodePrivate* QDomDocumentTypePrivate::insertBefore(QDomNodePrivate* newChild, QDomNodePrivate* refChild)
3527{
3528 // Call the origianl implementation
3529 QDomNodePrivate* p = QDomNodePrivate::insertBefore(newChild, refChild);
3530 // Update the maps
3531 if (p && p->isEntity())
3532 entities->map.insertMulti(p->nodeName(), p);
3533 else if (p && p->isNotation())
3534 notations->map.insertMulti(p->nodeName(), p);
3535
3536 return p;
3537}
3538
3539QDomNodePrivate* QDomDocumentTypePrivate::insertAfter(QDomNodePrivate* newChild, QDomNodePrivate* refChild)
3540{
3541 // Call the origianl implementation
3542 QDomNodePrivate* p = QDomNodePrivate::insertAfter(newChild, refChild);
3543 // Update the maps
3544 if (p && p->isEntity())
3545 entities->map.insertMulti(p->nodeName(), p);
3546 else if (p && p->isNotation())
3547 notations->map.insertMulti(p->nodeName(), p);
3548
3549 return p;
3550}
3551
3552QDomNodePrivate* QDomDocumentTypePrivate::replaceChild(QDomNodePrivate* newChild, QDomNodePrivate* oldChild)
3553{
3554 // Call the origianl implementation
3555 QDomNodePrivate* p = QDomNodePrivate::replaceChild(newChild, oldChild);
3556 // Update the maps
3557 if (p) {
3558 if (oldChild && oldChild->isEntity())
3559 entities->map.remove(oldChild->nodeName());
3560 else if (oldChild && oldChild->isNotation())
3561 notations->map.remove(oldChild->nodeName());
3562
3563 if (p->isEntity())
3564 entities->map.insertMulti(p->nodeName(), p);
3565 else if (p->isNotation())
3566 notations->map.insertMulti(p->nodeName(), p);
3567 }
3568
3569 return p;
3570}
3571
3572QDomNodePrivate* QDomDocumentTypePrivate::removeChild(QDomNodePrivate* oldChild)
3573{
3574 // Call the origianl implementation
3575 QDomNodePrivate* p = QDomNodePrivate::removeChild( oldChild);
3576 // Update the maps
3577 if (p && p->isEntity())
3578 entities->map.remove(p->nodeName());
3579 else if (p && p->isNotation())
3580 notations->map.remove(p ->nodeName());
3581
3582 return p;
3583}
3584
3585QDomNodePrivate* QDomDocumentTypePrivate::appendChild(QDomNodePrivate* newChild)
3586{
3587 return insertAfter(newChild, 0);
3588}
3589
3590static QString quotedValue(const QString &data)
3591{
3592 QChar quote = data.indexOf(QLatin1Char('\'')) == -1
3593 ? QLatin1Char('\'')
3594 : QLatin1Char('"');
3595 return quote + data + quote;
3596}
3597
3598void QDomDocumentTypePrivate::save(QTextStream& s, int, int indent) const
3599{
3600 if (name.isEmpty())
3601 return;
3602
3603 s << "<!DOCTYPE " << name;
3604
3605 if (!publicId.isNull()) {
3606 s << " PUBLIC " << quotedValue(publicId);
3607 if (!systemId.isNull()) {
3608 s << ' ' << quotedValue(systemId);
3609 }
3610 } else if (!systemId.isNull()) {
3611 s << " SYSTEM " << quotedValue(systemId);
3612 }
3613
3614 if (entities->length()>0 || notations->length()>0) {
3615 s << " [" << endl;
3616
3617 QHash<QString, QDomNodePrivate *>::const_iterator it2 = notations->map.constBegin();
3618 for (; it2 != notations->map.constEnd(); ++it2)
3619 (*it2)->save(s, 0, indent);
3620
3621 QHash<QString, QDomNodePrivate *>::const_iterator it = entities->map.constBegin();
3622 for (; it != entities->map.constEnd(); ++it)
3623 (*it)->save(s, 0, indent);
3624
3625 s << ']';
3626 }
3627
3628 s << '>' << endl;
3629}
3630
3631/**************************************************************
3632 *
3633 * QDomDocumentType
3634 *
3635 **************************************************************/
3636
3637#define IMPL ((QDomDocumentTypePrivate*)impl)
3638
3639/*!
3640 \class QDomDocumentType
3641 \reentrant
3642 \brief The QDomDocumentType class is the representation of the DTD
3643 in the document tree.
3644
3645 \inmodule QtXml
3646 \ingroup xml-tools
3647
3648 The QDomDocumentType class allows read-only access to some of the
3649 data structures in the DTD: it can return a map of all entities()
3650 and notations(). In addition the function name() returns the name
3651 of the document type as specified in the &lt;!DOCTYPE name&gt;
3652 tag. This class also provides the publicId(), systemId() and
3653 internalSubset() functions.
3654
3655 \sa QDomDocument
3656*/
3657
3658/*!
3659 Creates an empty QDomDocumentType object.
3660*/
3661QDomDocumentType::QDomDocumentType() : QDomNode()
3662{
3663}
3664
3665/*!
3666 Constructs a copy of \a n.
3667
3668 The data of the copy is shared (shallow copy): modifying one node
3669 will also change the other. If you want to make a deep copy, use
3670 cloneNode().
3671*/
3672QDomDocumentType::QDomDocumentType(const QDomDocumentType& n)
3673 : QDomNode(n)
3674{
3675}
3676
3677QDomDocumentType::QDomDocumentType(QDomDocumentTypePrivate* n)
3678 : QDomNode(n)
3679{
3680}
3681
3682/*!
3683 Assigns \a n to this document type.
3684
3685 The data of the copy is shared (shallow copy): modifying one node
3686 will also change the other. If you want to make a deep copy, use
3687 cloneNode().
3688*/
3689QDomDocumentType& QDomDocumentType::operator= (const QDomDocumentType& n)
3690{
3691 return (QDomDocumentType&) QDomNode::operator=(n);
3692}
3693
3694/*!
3695 Returns the name of the document type as specified in the
3696 &lt;!DOCTYPE name&gt; tag.
3697
3698 \sa nodeName()
3699*/
3700QString QDomDocumentType::name() const
3701{
3702 if (!impl)
3703 return QString();
3704 return IMPL->nodeName();
3705}
3706
3707/*!
3708 Returns a map of all entities described in the DTD.
3709*/
3710QDomNamedNodeMap QDomDocumentType::entities() const
3711{
3712 if (!impl)
3713 return QDomNamedNodeMap();
3714 return QDomNamedNodeMap(IMPL->entities);
3715}
3716
3717/*!
3718 Returns a map of all notations described in the DTD.
3719*/
3720QDomNamedNodeMap QDomDocumentType::notations() const
3721{
3722 if (!impl)
3723 return QDomNamedNodeMap();
3724 return QDomNamedNodeMap(IMPL->notations);
3725}
3726
3727/*!
3728 Returns the public identifier of the external DTD subset or
3729 an empty string if there is no public identifier.
3730
3731 \sa systemId() internalSubset() QDomImplementation::createDocumentType()
3732*/
3733QString QDomDocumentType::publicId() const
3734{
3735 if (!impl)
3736 return QString();
3737 return IMPL->publicId;
3738}
3739
3740/*!
3741 Returns the system identifier of the external DTD subset or
3742 an empty string if there is no system identifier.
3743
3744 \sa publicId() internalSubset() QDomImplementation::createDocumentType()
3745*/
3746QString QDomDocumentType::systemId() const
3747{
3748 if (!impl)
3749 return QString();
3750 return IMPL->systemId;
3751}
3752
3753/*!
3754 Returns the internal subset of the document type or an empty
3755 string if there is no internal subset.
3756
3757 \sa publicId() systemId()
3758*/
3759QString QDomDocumentType::internalSubset() const
3760{
3761 if (!impl)
3762 return QString();
3763 return IMPL->internalSubset;
3764}
3765
3766/*
3767 Are these needed at all? The only difference when removing these
3768 two methods in all subclasses is that we'd get a different type
3769 for null nodes.
3770*/
3771
3772/*!
3773 \fn QDomNode::NodeType QDomDocumentType::nodeType() const
3774
3775 Returns \c DocumentTypeNode.
3776
3777 \sa isDocumentType() QDomNode::toDocumentType()
3778*/
3779
3780#undef IMPL
3781
3782/**************************************************************
3783 *
3784 * QDomDocumentFragmentPrivate
3785 *
3786 **************************************************************/
3787
3788QDomDocumentFragmentPrivate::QDomDocumentFragmentPrivate(QDomDocumentPrivate* doc, QDomNodePrivate* parent)
3789 : QDomNodePrivate(doc, parent)
3790{
3791 name = QLatin1String("#document-fragment");
3792}
3793
3794QDomDocumentFragmentPrivate::QDomDocumentFragmentPrivate(QDomNodePrivate* n, bool deep)
3795 : QDomNodePrivate(n, deep)
3796{
3797}
3798
3799QDomNodePrivate* QDomDocumentFragmentPrivate::cloneNode(bool deep)
3800{
3801 QDomNodePrivate* p = new QDomDocumentFragmentPrivate(this, deep);
3802 // We are not interested in this node
3803 p->ref.deref();
3804 return p;
3805}
3806
3807/**************************************************************
3808 *
3809 * QDomDocumentFragment
3810 *
3811 **************************************************************/
3812
3813/*!
3814 \class QDomDocumentFragment
3815 \reentrant
3816 \brief The QDomDocumentFragment class is a tree of QDomNodes which is not usually a complete QDomDocument.
3817
3818 \inmodule QtXml
3819 \ingroup xml-tools
3820
3821 If you want to do complex tree operations it is useful to have a
3822 lightweight class to store nodes and their relations.
3823 QDomDocumentFragment stores a subtree of a document which does not
3824 necessarily represent a well-formed XML document.
3825
3826 QDomDocumentFragment is also useful if you want to group several
3827 nodes in a list and insert them all together as children of some
3828 node. In these cases QDomDocumentFragment can be used as a
3829 temporary container for this list of children.
3830
3831 The most important feature of QDomDocumentFragment is that it is
3832 treated in a special way by QDomNode::insertAfter(),
3833 QDomNode::insertBefore(), QDomNode::replaceChild() and
3834 QDomNode::appendChild(): instead of inserting the fragment itself, all
3835 the fragment's children are inserted.
3836*/
3837
3838/*!
3839 Constructs an empty document fragment.
3840*/
3841QDomDocumentFragment::QDomDocumentFragment()
3842{
3843}
3844
3845QDomDocumentFragment::QDomDocumentFragment(QDomDocumentFragmentPrivate* n)
3846 : QDomNode(n)
3847{
3848}
3849
3850/*!
3851 Constructs a copy of \a x.
3852
3853 The data of the copy is shared (shallow copy): modifying one node
3854 will also change the other. If you want to make a deep copy, use
3855 cloneNode().
3856*/
3857QDomDocumentFragment::QDomDocumentFragment(const QDomDocumentFragment& x)
3858 : QDomNode(x)
3859{
3860}
3861
3862/*!
3863 Assigns \a x to this DOM document fragment.
3864
3865 The data of the copy is shared (shallow copy): modifying one node
3866 will also change the other. If you want to make a deep copy, use
3867 cloneNode().
3868*/
3869QDomDocumentFragment& QDomDocumentFragment::operator= (const QDomDocumentFragment& x)
3870{
3871 return (QDomDocumentFragment&) QDomNode::operator=(x);
3872}
3873
3874/*!
3875 \fn QDomNode::NodeType QDomDocumentFragment::nodeType() const
3876
3877 Returns \c DocumentFragment.
3878
3879 \sa isDocumentFragment() QDomNode::toDocumentFragment()
3880*/
3881
3882/**************************************************************
3883 *
3884 * QDomCharacterDataPrivate
3885 *
3886 **************************************************************/
3887
3888QDomCharacterDataPrivate::QDomCharacterDataPrivate(QDomDocumentPrivate* d, QDomNodePrivate* p,
3889 const QString& data)
3890 : QDomNodePrivate(d, p)
3891{
3892 value = data;
3893 name = QLatin1String("#character-data");
3894}
3895
3896QDomCharacterDataPrivate::QDomCharacterDataPrivate(QDomCharacterDataPrivate* n, bool deep)
3897 : QDomNodePrivate(n, deep)
3898{
3899}
3900
3901QDomNodePrivate* QDomCharacterDataPrivate::cloneNode(bool deep)
3902{
3903 QDomNodePrivate* p = new QDomCharacterDataPrivate(this, deep);
3904 // We are not interested in this node
3905 p->ref.deref();
3906 return p;
3907}
3908
3909uint QDomCharacterDataPrivate::dataLength() const
3910{
3911 return value.length();
3912}
3913
3914QString QDomCharacterDataPrivate::substringData(unsigned long offset, unsigned long n) const
3915{
3916 return value.mid(offset, n);
3917}
3918
3919void QDomCharacterDataPrivate::insertData(unsigned long offset, const QString& arg)
3920{
3921 value.insert(offset, arg);
3922}
3923
3924void QDomCharacterDataPrivate::deleteData(unsigned long offset, unsigned long n)
3925{
3926 value.remove(offset, n);
3927}
3928
3929void QDomCharacterDataPrivate::replaceData(unsigned long offset, unsigned long n, const QString& arg)
3930{
3931 value.replace(offset, n, arg);
3932}
3933
3934void QDomCharacterDataPrivate::appendData(const QString& arg)
3935{
3936 value += arg;
3937}
3938
3939/**************************************************************
3940 *
3941 * QDomCharacterData
3942 *
3943 **************************************************************/
3944
3945#define IMPL ((QDomCharacterDataPrivate*)impl)
3946
3947/*!
3948 \class QDomCharacterData
3949 \reentrant
3950 \brief The QDomCharacterData class represents a generic string in the DOM.
3951
3952 \inmodule QtXml
3953 \ingroup xml-tools
3954
3955 Character data as used in XML specifies a generic data string.
3956 More specialized versions of this class are QDomText, QDomComment
3957 and QDomCDATASection.
3958
3959 The data string is set with setData() and retrieved with data().
3960 You can retrieve a portion of the data string using
3961 substringData(). Extra data can be appended with appendData(), or
3962 inserted with insertData(). Portions of the data string can be
3963 deleted with deleteData() or replaced with replaceData(). The
3964 length of the data string is returned by length().
3965
3966 The node type of the node containing this character data is
3967 returned by nodeType().
3968
3969 \sa QDomText QDomComment QDomCDATASection
3970*/
3971
3972/*!
3973 Constructs an empty character data object.
3974*/
3975QDomCharacterData::QDomCharacterData()
3976{
3977}
3978
3979/*!
3980 Constructs a copy of \a x.
3981
3982 The data of the copy is shared (shallow copy): modifying one node
3983 will also change the other. If you want to make a deep copy, use
3984 cloneNode().
3985*/
3986QDomCharacterData::QDomCharacterData(const QDomCharacterData& x)
3987 : QDomNode(x)
3988{
3989}
3990
3991QDomCharacterData::QDomCharacterData(QDomCharacterDataPrivate* n)
3992 : QDomNode(n)
3993{
3994}
3995
3996/*!
3997 Assigns \a x to this character data.
3998
3999 The data of the copy is shared (shallow copy): modifying one node
4000 will also change the other. If you want to make a deep copy, use
4001 cloneNode().
4002*/
4003QDomCharacterData& QDomCharacterData::operator= (const QDomCharacterData& x)
4004{
4005 return (QDomCharacterData&) QDomNode::operator=(x);
4006}
4007
4008/*!
4009 Returns the string stored in this object.
4010
4011 If the node is a \link isNull() null node\endlink, it will return
4012 an empty string.
4013*/
4014QString QDomCharacterData::data() const
4015{
4016 if (!impl)
4017 return QString();
4018 return impl->nodeValue();
4019}
4020
4021/*!
4022 Sets this object's string to \a v.
4023*/
4024void QDomCharacterData::setData(const QString& v)
4025{
4026 if (impl)
4027 impl->setNodeValue(v);
4028}
4029
4030/*!
4031 Returns the length of the stored string.
4032*/
4033uint QDomCharacterData::length() const
4034{
4035 if (impl)
4036 return IMPL->dataLength();
4037 return 0;
4038}
4039
4040/*!
4041 Returns the substring of length \a count from position \a offset.
4042*/
4043QString QDomCharacterData::substringData(unsigned long offset, unsigned long count)
4044{
4045 if (!impl)
4046 return QString();
4047 return IMPL->substringData(offset, count);
4048}
4049
4050/*!
4051 Appends the string \a arg to the stored string.
4052*/
4053void QDomCharacterData::appendData(const QString& arg)
4054{
4055 if (impl)
4056 IMPL->appendData(arg);
4057}
4058
4059/*!
4060 Inserts the string \a arg into the stored string at position \a offset.
4061*/
4062void QDomCharacterData::insertData(unsigned long offset, const QString& arg)
4063{
4064 if (impl)
4065 IMPL->insertData(offset, arg);
4066}
4067
4068/*!
4069 Deletes a substring of length \a count from position \a offset.
4070*/
4071void QDomCharacterData::deleteData(unsigned long offset, unsigned long count)
4072{
4073 if (impl)
4074 IMPL->deleteData(offset, count);
4075}
4076
4077/*!
4078 Replaces the substring of length \a count starting at position \a
4079 offset with the string \a arg.
4080*/
4081void QDomCharacterData::replaceData(unsigned long offset, unsigned long count, const QString& arg)
4082{
4083 if (impl)
4084 IMPL->replaceData(offset, count, arg);
4085}
4086
4087/*!
4088 Returns the type of node this object refers to (i.e. \c TextNode,
4089 \c CDATASectionNode, \c CommentNode or \c CharacterDataNode). For
4090 a \link isNull() null node\endlink, returns \c CharacterDataNode.
4091*/
4092QDomNode::NodeType QDomCharacterData::nodeType() const
4093{
4094 if (!impl)
4095 return CharacterDataNode;
4096 return QDomNode::nodeType();
4097}
4098
4099#undef IMPL
4100
4101/**************************************************************
4102 *
4103 * QDomAttrPrivate
4104 *
4105 **************************************************************/
4106
4107QDomAttrPrivate::QDomAttrPrivate(QDomDocumentPrivate* d, QDomNodePrivate* parent, const QString& name_)
4108 : QDomNodePrivate(d, parent)
4109{
4110 name = name_;
4111 m_specified = false;
4112}
4113
4114QDomAttrPrivate::QDomAttrPrivate(QDomDocumentPrivate* d, QDomNodePrivate* p, const QString& nsURI, const QString& qName)
4115 : QDomNodePrivate(d, p)
4116{
4117 qt_split_namespace(prefix, name, qName, !nsURI.isNull());
4118 namespaceURI = nsURI;
4119 createdWithDom1Interface = false;
4120 m_specified = false;
4121}
4122
4123QDomAttrPrivate::QDomAttrPrivate(QDomAttrPrivate* n, bool deep)
4124 : QDomNodePrivate(n, deep)
4125{
4126 m_specified = n->specified();
4127}
4128
4129void QDomAttrPrivate::setNodeValue(const QString& v)
4130{
4131 value = v;
4132 QDomTextPrivate *t = new QDomTextPrivate(0, this, v);
4133 // keep the refcount balanced: appendChild() does a ref anyway.
4134 t->ref.deref();
4135 if (first) {
4136 delete removeChild(first);
4137 }
4138 appendChild(t);
4139}
4140
4141QDomNodePrivate* QDomAttrPrivate::cloneNode(bool deep)
4142{
4143 QDomNodePrivate* p = new QDomAttrPrivate(this, deep);
4144 // We are not interested in this node
4145 p->ref.deref();
4146 return p;
4147}
4148
4149bool QDomAttrPrivate::specified() const
4150{
4151 return m_specified;
4152}
4153
4154/* \internal
4155 Encode & escape \a str. Yes, it makes no sense to return a QString,
4156 but is so for legacy reasons.
4157
4158 Remember that content produced should be able to roundtrip with 2.11 End-of-Line Handling
4159 and 3.3.3 Attribute-Value Normalization.
4160
4161 If \a performAVN is true, characters will be escaped to survive Attribute Value Normalization.
4162 If \a encodeEOLs is true, characters will be escaped to survive End-of-Line Handling.
4163*/
4164static QString encodeText(const QString &str,
4165 QTextStream &s,
4166 const bool encodeQuotes = true,
4167 const bool performAVN = false,
4168 const bool encodeEOLs = false)
4169{
4170#ifdef QT_NO_TEXTCODEC
4171 Q_UNUSED(s);
4172#else
4173 const QTextCodec *const codec = s.codec();
4174 Q_ASSERT(codec);
4175#endif
4176 QString retval(str);
4177 int len = retval.length();
4178 int i = 0;
4179
4180 while (i < len) {
4181 const QChar ati(retval.at(i));
4182
4183 if (ati == QLatin1Char('<')) {
4184 retval.replace(i, 1, QLatin1String("&lt;"));
4185 len += 3;
4186 i += 4;
4187 } else if (encodeQuotes && (ati == QLatin1Char('"'))) {
4188 retval.replace(i, 1, QLatin1String("&quot;"));
4189 len += 5;
4190 i += 6;
4191 } else if (ati == QLatin1Char('&')) {
4192 retval.replace(i, 1, QLatin1String("&amp;"));
4193 len += 4;
4194 i += 5;
4195 } else if (ati == QLatin1Char('>') && i >= 2 && retval[i - 1] == QLatin1Char(']') && retval[i - 2] == QLatin1Char(']')) {
4196 retval.replace(i, 1, QLatin1String("&gt;"));
4197 len += 3;
4198 i += 4;
4199 } else if (performAVN &&
4200 (ati == QChar(0xA) ||
4201 ati == QChar(0xD) ||
4202 ati == QChar(0x9))) {
4203 const QString replacement(QLatin1String("&#x") + QString::number(ati.unicode(), 16) + QLatin1Char(';'));
4204 retval.replace(i, 1, replacement);
4205 i += replacement.length();
4206 len += replacement.length() - 1;
4207 } else if (encodeEOLs && ati == QChar(0xD)) {
4208 retval.replace(i, 1, QLatin1String("&#xd;")); // Replace a single 0xD with a ref for 0xD
4209 len += 4;
4210 i += 5;
4211 } else {
4212#ifndef QT_NO_TEXTCODEC
4213 if(codec->canEncode(ati))
4214 ++i;
4215 else
4216#endif
4217 {
4218 // We have to use a character reference to get it through.
4219 const ushort codepoint(ati.unicode());
4220 const QString replacement(QLatin1String("&#x") + QString::number(codepoint, 16) + QLatin1Char(';'));
4221 retval.replace(i, 1, replacement);
4222 i += replacement.length();
4223 len += replacement.length() - 1;
4224 }
4225 }
4226 }
4227
4228 return retval;
4229}
4230
4231void QDomAttrPrivate::save(QTextStream& s, int, int) const
4232{
4233 if (namespaceURI.isNull()) {
4234 s << name << "=\"" << encodeText(value, s, true, true) << '\"';
4235 } else {
4236 s << prefix << ':' << name << "=\"" << encodeText(value, s, true, true) << '\"';
4237 /* This is a fix for 138243, as good as it gets.
4238 *
4239 * QDomElementPrivate::save() output a namespace declaration if
4240 * the element is in a namespace, no matter what. This function do as well, meaning
4241 * that we get two identical namespace declaration if we don't have the if-
4242 * statement below.
4243 *
4244 * This doesn't work when the parent element has the same prefix as us but
4245 * a different namespace. However, this can only occur by the user modifying the element,
4246 * and we don't do fixups by that anyway, and hence it's the user responsibility to not
4247 * arrive in those situations. */
4248 if(!ownerNode ||
4249 ownerNode->prefix != prefix) {
4250 s << " xmlns:" << prefix << "=\"" << encodeText(namespaceURI, s, true, true) << '\"';
4251 }
4252 }
4253}
4254
4255/**************************************************************
4256 *
4257 * QDomAttr
4258 *
4259 **************************************************************/
4260
4261#define IMPL ((QDomAttrPrivate*)impl)
4262
4263/*!
4264 \class QDomAttr
4265 \reentrant
4266 \brief The QDomAttr class represents one attribute of a QDomElement.
4267
4268 \inmodule QtXml
4269 \ingroup xml-tools
4270
4271 For example, the following piece of XML produces an element with
4272 no children, but two attributes:
4273
4274 \snippet doc/src/snippets/code/src_xml_dom_qdom.cpp 7
4275
4276 You can access the attributes of an element with code like this:
4277
4278 \snippet doc/src/snippets/code/src_xml_dom_qdom.cpp 8
4279
4280 This example also shows that changing an attribute received from
4281 an element changes the attribute of the element. If you do not
4282 want to change the value of the element's attribute you must
4283 use cloneNode() to get an independent copy of the attribute.
4284
4285 QDomAttr can return the name() and value() of an attribute. An
4286 attribute's value is set with setValue(). If specified() returns
4287 true the value was set with setValue(). The node this
4288 attribute is attached to (if any) is returned by ownerElement().
4289
4290 For further information about the Document Object Model see
4291 \l{http://www.w3.org/TR/REC-DOM-Level-1/} and
4292 \l{http://www.w3.org/TR/DOM-Level-2-Core/}.
4293 For a more general introduction of the DOM implementation see the
4294 QDomDocument documentation.
4295*/
4296
4297
4298/*!
4299 Constructs an empty attribute.
4300*/
4301QDomAttr::QDomAttr()
4302{
4303}
4304
4305/*!
4306 Constructs a copy of \a x.
4307
4308 The data of the copy is shared (shallow copy): modifying one node
4309 will also change the other. If you want to make a deep copy, use
4310 cloneNode().
4311*/
4312QDomAttr::QDomAttr(const QDomAttr& x)
4313 : QDomNode(x)
4314{
4315}
4316
4317QDomAttr::QDomAttr(QDomAttrPrivate* n)
4318 : QDomNode(n)
4319{
4320}
4321
4322/*!
4323 Assigns \a x to this DOM attribute.
4324
4325 The data of the copy is shared (shallow copy): modifying one node
4326 will also change the other. If you want to make a deep copy, use
4327 cloneNode().
4328*/
4329QDomAttr& QDomAttr::operator= (const QDomAttr& x)
4330{
4331 return (QDomAttr&) QDomNode::operator=(x);
4332}
4333
4334/*!
4335 Returns the attribute's name.
4336*/
4337QString QDomAttr::name() const
4338{
4339 if (!impl)
4340 return QString();
4341 return impl->nodeName();
4342}
4343
4344/*!
4345 Returns true if the attribute has been set by the user with setValue().
4346 Returns false if the value hasn't been specified or set.
4347
4348 \sa setValue()
4349*/
4350bool QDomAttr::specified() const
4351{
4352 if (!impl)
4353 return false;
4354 return IMPL->specified();
4355}
4356
4357/*!
4358 Returns the element node this attribute is attached to or a \link
4359 QDomNode::isNull() null node\endlink if this attribute is not
4360 attached to any element.
4361*/
4362QDomElement QDomAttr::ownerElement() const
4363{
4364 Q_ASSERT(impl->parent());
4365 if (!impl->parent()->isElement())
4366 return QDomElement();
4367 return QDomElement((QDomElementPrivate*)(impl->parent()));
4368}
4369
4370/*!
4371 Returns the value of the attribute or an empty string if the
4372 attribute has not been specified.
4373
4374 \sa specified() setValue()
4375*/
4376QString QDomAttr::value() const
4377{
4378 if (!impl)
4379 return QString();
4380 return impl->nodeValue();
4381}
4382
4383/*!
4384 Sets the attribute's value to \a v.
4385
4386 \sa value()
4387*/
4388void QDomAttr::setValue(const QString& v)
4389{
4390 if (!impl)
4391 return;
4392 impl->setNodeValue(v);
4393 IMPL->m_specified = true;
4394}
4395
4396/*!
4397 \fn QDomNode::NodeType QDomAttr::nodeType() const
4398
4399 Returns \link QDomNode::NodeType AttributeNode\endlink.
4400*/
4401
4402#undef IMPL
4403
4404/**************************************************************
4405 *
4406 * QDomElementPrivate
4407 *
4408 **************************************************************/
4409
4410QDomElementPrivate::QDomElementPrivate(QDomDocumentPrivate* d, QDomNodePrivate* p,
4411 const QString& tagname)
4412 : QDomNodePrivate(d, p)
4413{
4414 name = tagname;
4415 m_attr = new QDomNamedNodeMapPrivate(this);
4416}
4417
4418QDomElementPrivate::QDomElementPrivate(QDomDocumentPrivate* d, QDomNodePrivate* p,
4419 const QString& nsURI, const QString& qName)
4420 : QDomNodePrivate(d, p)
4421{
4422 qt_split_namespace(prefix, name, qName, !nsURI.isNull());
4423 namespaceURI = nsURI;
4424 createdWithDom1Interface = false;
4425 m_attr = new QDomNamedNodeMapPrivate(this);
4426}
4427
4428QDomElementPrivate::QDomElementPrivate(QDomElementPrivate* n, bool deep) :
4429 QDomNodePrivate(n, deep)
4430{
4431 m_attr = n->m_attr->clone(this);
4432 // Reference is down to 0, so we set it to 1 here.
4433 m_attr->ref.ref();
4434}
4435
4436QDomElementPrivate::~QDomElementPrivate()
4437{
4438 if (!m_attr->ref.deref())
4439 delete m_attr;
4440}
4441
4442QDomNodePrivate* QDomElementPrivate::cloneNode(bool deep)
4443{
4444 QDomNodePrivate* p = new QDomElementPrivate(this, deep);
4445 // We are not interested in this node
4446 p->ref.deref();
4447 return p;
4448}
4449
4450QString QDomElementPrivate::attribute(const QString& name_, const QString& defValue) const
4451{
4452 QDomNodePrivate* n = m_attr->namedItem(name_);
4453 if (!n)
4454 return defValue;
4455
4456 return n->nodeValue();
4457}
4458
4459QString QDomElementPrivate::attributeNS(const QString& nsURI, const QString& localName, const QString& defValue) const
4460{
4461 QDomNodePrivate* n = m_attr->namedItemNS(nsURI, localName);
4462 if (!n)
4463 return defValue;
4464
4465 return n->nodeValue();
4466}
4467
4468void QDomElementPrivate::setAttribute(const QString& aname, const QString& newValue)
4469{
4470 QDomNodePrivate* n = m_attr->namedItem(aname);
4471 if (!n) {
4472 n = new QDomAttrPrivate(ownerDocument(), this, aname);
4473 n->setNodeValue(newValue);
4474
4475 // Referencing is done by the map, so we set the reference counter back
4476 // to 0 here. This is ok since we created the QDomAttrPrivate.
4477 n->ref.deref();
4478 m_attr->setNamedItem(n);
4479 } else {
4480 n->setNodeValue(newValue);
4481 }
4482}
4483
4484void QDomElementPrivate::setAttributeNS(const QString& nsURI, const QString& qName, const QString& newValue)
4485{
4486 QString prefix, localName;
4487 qt_split_namespace(prefix, localName, qName, true);
4488 QDomNodePrivate* n = m_attr->namedItemNS(nsURI, localName);
4489 if (!n) {
4490 n = new QDomAttrPrivate(ownerDocument(), this, nsURI, qName);
4491 n->setNodeValue(newValue);
4492
4493 // Referencing is done by the map, so we set the reference counter back
4494 // to 0 here. This is ok since we created the QDomAttrPrivate.
4495 n->ref.deref();
4496 m_attr->setNamedItem(n);
4497 } else {
4498 n->setNodeValue(newValue);
4499 n->prefix = prefix;
4500 }
4501}
4502
4503void QDomElementPrivate::removeAttribute(const QString& aname)
4504{
4505 QDomNodePrivate* p = m_attr->removeNamedItem(aname);
4506 if (p && p->ref == 0)
4507 delete p;
4508}
4509
4510QDomAttrPrivate* QDomElementPrivate::attributeNode(const QString& aname)
4511{
4512 return (QDomAttrPrivate*)m_attr->namedItem(aname);
4513}
4514
4515QDomAttrPrivate* QDomElementPrivate::attributeNodeNS(const QString& nsURI, const QString& localName)
4516{
4517 return (QDomAttrPrivate*)m_attr->namedItemNS(nsURI, localName);
4518}
4519
4520QDomAttrPrivate* QDomElementPrivate::setAttributeNode(QDomAttrPrivate* newAttr)
4521{
4522 QDomNodePrivate* n = m_attr->namedItem(newAttr->nodeName());
4523
4524 // Referencing is done by the maps
4525 m_attr->setNamedItem(newAttr);
4526
4527 newAttr->setParent(this);
4528
4529 return (QDomAttrPrivate*)n;
4530}
4531
4532QDomAttrPrivate* QDomElementPrivate::setAttributeNodeNS(QDomAttrPrivate* newAttr)
4533{
4534 QDomNodePrivate* n = 0;
4535 if (!newAttr->prefix.isNull())
4536 n = m_attr->namedItemNS(newAttr->namespaceURI, newAttr->name);
4537
4538 // Referencing is done by the maps
4539 m_attr->setNamedItem(newAttr);
4540
4541 return (QDomAttrPrivate*)n;
4542}
4543
4544QDomAttrPrivate* QDomElementPrivate::removeAttributeNode(QDomAttrPrivate* oldAttr)
4545{
4546 return (QDomAttrPrivate*)m_attr->removeNamedItem(oldAttr->nodeName());
4547}
4548
4549bool QDomElementPrivate::hasAttribute(const QString& aname)
4550{
4551 return m_attr->contains(aname);
4552}
4553
4554bool QDomElementPrivate::hasAttributeNS(const QString& nsURI, const QString& localName)
4555{
4556 return m_attr->containsNS(nsURI, localName);
4557}
4558
4559QString QDomElementPrivate::text()
4560{
4561 QString t(QLatin1String(""));
4562
4563 QDomNodePrivate* p = first;
4564 while (p) {
4565 if (p->isText() || p->isCDATASection())
4566 t += p->nodeValue();
4567 else if (p->isElement())
4568 t += ((QDomElementPrivate*)p)->text();
4569 p = p->next;
4570 }
4571
4572 return t;
4573}
4574
4575void QDomElementPrivate::save(QTextStream& s, int depth, int indent) const
4576{
4577 if (!(prev && prev->isText()))
4578 s << QString(indent < 1 ? 0 : depth * indent, QLatin1Char(' '));
4579
4580 QString qName(name);
4581 QString nsDecl(QLatin1String(""));
4582 if (!namespaceURI.isNull()) {
4583 /** ### Qt 5:
4584 *
4585 * If we still have QDom, optimize this so that we only declare namespaces that are not
4586 * yet declared. We loose default namespace mappings, so maybe we should rather store
4587 * the information that we get from startPrefixMapping()/endPrefixMapping() and use them.
4588 * Modifications becomes more complex then, however.
4589 *
4590 * We cannot do this during the Qt 4 series because it would require too invasive changes, and
4591 * hence possibly behavioral changes.
4592 */
4593 if (prefix.isEmpty()) {
4594 nsDecl = QLatin1String(" xmlns");
4595 } else {
4596 qName = prefix + QLatin1Char(':') + name;
4597 nsDecl = QLatin1String(" xmlns:") + prefix;
4598 }
4599 nsDecl += QLatin1String("=\"") + encodeText(namespaceURI, s) + QLatin1Char('\"');
4600 }
4601 s << '<' << qName << nsDecl;
4602
4603 QSet<QString> outputtedPrefixes;
4604
4605 /* Write out attributes. */
4606 if (!m_attr->map.isEmpty()) {
4607 QHash<QString, QDomNodePrivate *>::const_iterator it = m_attr->map.constBegin();
4608 for (; it != m_attr->map.constEnd(); ++it) {
4609 s << ' ';
4610 if (it.value()->namespaceURI.isNull()) {
4611 s << it.value()->name << "=\"" << encodeText(it.value()->value, s, true, true) << '\"';
4612 } else {
4613 s << it.value()->prefix << ':' << it.value()->name << "=\"" << encodeText(it.value()->value, s, true, true) << '\"';
4614 /* This is a fix for 138243, as good as it gets.
4615 *
4616 * QDomElementPrivate::save() output a namespace declaration if
4617 * the element is in a namespace, no matter what. This function do as well, meaning
4618 * that we get two identical namespace declaration if we don't have the if-
4619 * statement below.
4620 *
4621 * This doesn't work when the parent element has the same prefix as us but
4622 * a different namespace. However, this can only occur by the user modifying the element,
4623 * and we don't do fixups by that anyway, and hence it's the user responsibility to not
4624 * arrive in those situations. */
4625 if((!it.value()->ownerNode ||
4626 it.value()->ownerNode->prefix != it.value()->prefix) &&
4627 !outputtedPrefixes.contains(it.value()->prefix)) {
4628 s << " xmlns:" << it.value()->prefix << "=\"" << encodeText(it.value()->namespaceURI, s, true, true) << '\"';
4629 outputtedPrefixes.insert(it.value()->prefix);
4630 }
4631 }
4632 }
4633 }
4634
4635 if (last) {
4636 // has child nodes
4637 if (first->isText())
4638 s << '>';
4639 else {
4640 s << '>';
4641
4642 /* -1 disables new lines. */
4643 if (indent != -1)
4644 s << endl;
4645 }
4646 QDomNodePrivate::save(s, depth + 1, indent); if (!last->isText())
4647 s << QString(indent < 1 ? 0 : depth * indent, QLatin1Char(' '));
4648
4649 s << "</" << qName << '>';
4650 } else {
4651 s << "/>";
4652 }
4653 if (!(next && next->isText())) {
4654 /* -1 disables new lines. */
4655 if (indent != -1)
4656 s << endl;
4657 }
4658}
4659
4660/**************************************************************
4661 *
4662 * QDomElement
4663 *
4664 **************************************************************/
4665
4666#define IMPL ((QDomElementPrivate*)impl)
4667
4668/*!
4669 \class QDomElement
4670 \reentrant
4671 \brief The QDomElement class represents one element in the DOM tree.
4672
4673 \inmodule QtXml
4674 \ingroup xml-tools
4675
4676 Elements have a tagName() and zero or more attributes associated
4677 with them. The tag name can be changed with setTagName().
4678
4679 Element attributes are represented by QDomAttr objects that can
4680 be queried using the attribute() and attributeNode() functions.
4681 You can set attributes with the setAttribute() and
4682 setAttributeNode() functions. Attributes can be removed with
4683 removeAttribute(). There are namespace-aware equivalents to these
4684 functions, i.e. setAttributeNS(), setAttributeNodeNS() and
4685 removeAttributeNS().
4686
4687 If you want to access the text of a node use text(), e.g.
4688 \snippet doc/src/snippets/code/src_xml_dom_qdom.cpp 9
4689 The text() function operates recursively to find the text (since
4690 not all elements contain text). If you want to find all the text
4691 in all of a node's children, iterate over the children looking for
4692 QDomText nodes, e.g.
4693 \snippet doc/src/snippets/code/src_xml_dom_qdom.cpp 10
4694 Note that we attempt to convert each node to a text node and use
4695 text() rather than using firstChild().toText().data() or
4696 n.toText().data() directly on the node, because the node may not
4697 be a text element.
4698
4699 You can get a list of all the decendents of an element which have
4700 a specified tag name with elementsByTagName() or
4701 elementsByTagNameNS().
4702
4703 To browse the elements of a dom document use firstChildElement(), lastChildElement(),
4704 nextSiblingElement() and previousSiblingElement(). For example, to iterate over all
4705 child elements called "entry" in a root element called "database", you can use:
4706 \snippet doc/src/snippets/code/src_xml_dom_qdom.cpp 11
4707
4708 For further information about the Document Object Model see
4709 \l{http://www.w3.org/TR/REC-DOM-Level-1/}{Level 1} and
4710 \l{http://www.w3.org/TR/DOM-Level-2-Core/}{Level 2 Core}.
4711 For a more general introduction of the DOM implementation see the
4712 QDomDocument documentation.
4713*/
4714
4715/*!
4716 Constructs an empty element. Use the QDomDocument::createElement()
4717 function to construct elements with content.
4718*/
4719QDomElement::QDomElement()
4720 : QDomNode()
4721{
4722}
4723
4724/*!
4725 Constructs a copy of \a x.
4726
4727 The data of the copy is shared (shallow copy): modifying one node
4728 will also change the other. If you want to make a deep copy, use
4729 cloneNode().
4730*/
4731QDomElement::QDomElement(const QDomElement& x)
4732 : QDomNode(x)
4733{
4734}
4735
4736QDomElement::QDomElement(QDomElementPrivate* n)
4737 : QDomNode(n)
4738{
4739}
4740
4741/*!
4742 Assigns \a x to this DOM element.
4743
4744 The data of the copy is shared (shallow copy): modifying one node
4745 will also change the other. If you want to make a deep copy, use
4746 cloneNode().
4747*/
4748QDomElement& QDomElement::operator= (const QDomElement& x)
4749{
4750 return (QDomElement&) QDomNode::operator=(x);
4751}
4752
4753/*!
4754 \fn QDomNode::NodeType QDomElement::nodeType() const
4755
4756 Returns \c ElementNode.
4757*/
4758
4759/*!
4760 Sets this element's tag name to \a name.
4761
4762 \sa tagName()
4763*/
4764void QDomElement::setTagName(const QString& name)
4765{
4766 if (impl)
4767 impl->name = name;
4768}
4769
4770/*!
4771 Returns the tag name of this element. For an XML element like this:
4772
4773 \snippet doc/src/snippets/code/src_xml_dom_qdom.cpp 12
4774
4775 the tagname would return "img".
4776
4777 \sa setTagName()
4778*/
4779QString QDomElement::tagName() const
4780{
4781 if (!impl)
4782 return QString();
4783 return impl->nodeName();
4784}
4785
4786
4787/*!
4788 Returns a QDomNamedNodeMap containing all this element's attributes.
4789
4790 \sa attribute() setAttribute() attributeNode() setAttributeNode()
4791*/
4792QDomNamedNodeMap QDomElement::attributes() const
4793{
4794 if (!impl)
4795 return QDomNamedNodeMap();
4796 return QDomNamedNodeMap(IMPL->attributes());
4797}
4798
4799/*!
4800 Returns the attribute called \a name. If the attribute does not
4801 exist \a defValue is returned.
4802
4803 \sa setAttribute() attributeNode() setAttributeNode() attributeNS()
4804*/
4805QString QDomElement::attribute(const QString& name, const QString& defValue) const
4806{
4807 if (!impl)
4808 return defValue;
4809 return IMPL->attribute(name, defValue);
4810}
4811
4812/*!
4813 Adds an attribute called \a name with value \a value. If an
4814 attribute with the same name exists, its value is replaced by \a
4815 value.
4816
4817 \sa attribute() setAttributeNode() setAttributeNS()
4818*/
4819void QDomElement::setAttribute(const QString& name, const QString& value)
4820{
4821 if (!impl)
4822 return;
4823 IMPL->setAttribute(name, value);
4824}
4825
4826/*!
4827 \fn void QDomElement::setAttribute(const QString& name, int value)
4828
4829 \overload
4830 The number is formatted according to the current locale.
4831*/
4832
4833/*!
4834 \fn void QDomElement::setAttribute(const QString& name, uint value)
4835
4836 \overload
4837 The number is formatted according to the current locale.
4838*/
4839
4840/*!
4841 \overload
4842
4843 The number is formatted according to the current locale.
4844*/
4845void QDomElement::setAttribute(const QString& name, qlonglong value)
4846{
4847 if (!impl)
4848 return;
4849 QString x;
4850 x.setNum(value);
4851 IMPL->setAttribute(name, x);
4852}
4853
4854/*!
4855 \overload
4856
4857 The number is formatted according to the current locale.
4858*/
4859void QDomElement::setAttribute(const QString& name, qulonglong value)
4860{
4861 if (!impl)
4862 return;
4863 QString x;
4864 x.setNum(value);
4865 IMPL->setAttribute(name, x);
4866}
4867
4868/*!
4869 \overload
4870
4871 The number is formatted according to the current locale.
4872*/
4873void QDomElement::setAttribute(const QString& name, float value)
4874{
4875 if (!impl)
4876 return;
4877 QString x;
4878 x.setNum(value);
4879 IMPL->setAttribute(name, x);
4880}
4881
4882/*!
4883 \overload
4884
4885 The number is formatted according to the current locale.
4886*/
4887void QDomElement::setAttribute(const QString& name, double value)
4888{
4889 if (!impl)
4890 return;
4891 QString x;
4892 char buf[256];
4893 int count = qsnprintf(buf, sizeof(buf), "%.16g", value);
4894 if (count > 0)
4895 x = QString::fromLatin1(buf, count);
4896 else
4897 x.setNum(value); // Fallback
4898 IMPL->setAttribute(name, x);
4899}
4900
4901/*!
4902 Removes the attribute called name \a name from this element.
4903
4904 \sa setAttribute() attribute() removeAttributeNS()
4905*/
4906void QDomElement::removeAttribute(const QString& name)
4907{
4908 if (!impl)
4909 return;
4910 IMPL->removeAttribute(name);
4911}
4912
4913/*!
4914 Returns the QDomAttr object that corresponds to the attribute
4915 called \a name. If no such attribute exists a \link
4916 QDomNode::isNull() null attribute\endlink is returned.
4917
4918 \sa setAttributeNode() attribute() setAttribute() attributeNodeNS()
4919*/
4920QDomAttr QDomElement::attributeNode(const QString& name)
4921{
4922 if (!impl)
4923 return QDomAttr();
4924 return QDomAttr(IMPL->attributeNode(name));
4925}
4926
4927/*!
4928 Adds the attribute \a newAttr to this element.
4929
4930 If the element has another attribute that has the same name as \a
4931 newAttr, this function replaces that attribute and returns it;
4932 otherwise the function returns a \link QDomNode::isNull() null
4933 attribute\endlink.
4934
4935 \sa attributeNode() setAttribute() setAttributeNodeNS()
4936*/
4937QDomAttr QDomElement::setAttributeNode(const QDomAttr& newAttr)
4938{
4939 if (!impl)
4940 return QDomAttr();
4941 return QDomAttr(IMPL->setAttributeNode(((QDomAttrPrivate*)newAttr.impl)));
4942}
4943
4944/*!
4945 Removes the attribute \a oldAttr from the element and returns it.
4946
4947 \sa attributeNode() setAttributeNode()
4948*/
4949QDomAttr QDomElement::removeAttributeNode(const QDomAttr& oldAttr)
4950{
4951 if (!impl)
4952 return QDomAttr(); // ### should this return oldAttr?
4953 return QDomAttr(IMPL->removeAttributeNode(((QDomAttrPrivate*)oldAttr.impl)));
4954}
4955
4956/*!
4957 Returns a QDomNodeList containing all descendants of this element
4958 named \a tagname encountered during a preorder traversal of the
4959 element subtree with this element as its root. The order of the
4960 elements in the returned list is the order they are encountered
4961 during the preorder traversal.
4962
4963 \sa elementsByTagNameNS() QDomDocument::elementsByTagName()
4964*/
4965QDomNodeList QDomElement::elementsByTagName(const QString& tagname) const
4966{
4967 return QDomNodeList(new QDomNodeListPrivate(impl, tagname));
4968}
4969
4970/*!
4971 Returns true if this element has an attribute called \a name;
4972 otherwise returns false.
4973
4974 \bold{Note:} This function does not take the presence of namespaces
4975 into account. As a result, the specified name will be tested
4976 against fully-qualified attribute names that include any namespace
4977 prefixes that may be present.
4978
4979 Use hasAttributeNS() to explicitly test for attributes with specific
4980 namespaces and names.
4981*/
4982bool QDomElement::hasAttribute(const QString& name) const
4983{
4984 if (!impl)
4985 return false;
4986 return IMPL->hasAttribute(name);
4987}
4988
4989/*!
4990 Returns the attribute with the local name \a localName and the
4991 namespace URI \a nsURI. If the attribute does not exist \a
4992 defValue is returned.
4993
4994 \sa setAttributeNS() attributeNodeNS() setAttributeNodeNS() attribute()
4995*/
4996QString QDomElement::attributeNS(const QString nsURI, const QString& localName, const QString& defValue) const
4997{
4998 if (!impl)
4999 return defValue;
5000 return IMPL->attributeNS(nsURI, localName, defValue);
5001}
5002
5003/*!
5004 Adds an attribute with the qualified name \a qName and the
5005 namespace URI \a nsURI with the value \a value. If an attribute
5006 with the same local name and namespace URI exists, its prefix is
5007 replaced by the prefix of \a qName and its value is repaced by \a
5008 value.
5009
5010 Although \a qName is the qualified name, the local name is used to
5011 decide if an existing attribute's value should be replaced.
5012
5013 \sa attributeNS() setAttributeNodeNS() setAttribute()
5014*/
5015void QDomElement::setAttributeNS(const QString nsURI, const QString& qName, const QString& value)
5016{
5017 if (!impl)
5018 return;
5019 IMPL->setAttributeNS(nsURI, qName, value);
5020}
5021
5022/*!
5023 \fn void QDomElement::setAttributeNS(const QString nsURI, const QString& qName, int value)
5024
5025 \overload
5026*/
5027
5028/*!
5029 \fn void QDomElement::setAttributeNS(const QString nsURI, const QString& qName, uint value)
5030
5031 \overload
5032*/
5033
5034/*!
5035 \overload
5036*/
5037void QDomElement::setAttributeNS(const QString nsURI, const QString& qName, qlonglong value)
5038{
5039 if (!impl)
5040 return;
5041 QString x;
5042 x.setNum(value);
5043 IMPL->setAttributeNS(nsURI, qName, x);
5044}
5045
5046/*!
5047 \overload
5048*/
5049void QDomElement::setAttributeNS(const QString nsURI, const QString& qName, qulonglong value)
5050{
5051 if (!impl)
5052 return;
5053 QString x;
5054 x.setNum(value);
5055 IMPL->setAttributeNS(nsURI, qName, x);
5056}
5057
5058/*!
5059 \overload
5060*/
5061void QDomElement::setAttributeNS(const QString nsURI, const QString& qName, double value)
5062{
5063 if (!impl)
5064 return;
5065 QString x;
5066 x.setNum(value);
5067 IMPL->setAttributeNS(nsURI, qName, x);
5068}
5069
5070/*!
5071 Removes the attribute with the local name \a localName and the
5072 namespace URI \a nsURI from this element.
5073
5074 \sa setAttributeNS() attributeNS() removeAttribute()
5075*/
5076void QDomElement::removeAttributeNS(const QString& nsURI, const QString& localName)
5077{
5078 if (!impl)
5079 return;
5080 QDomNodePrivate *n = IMPL->attributeNodeNS(nsURI, localName);
5081 if (!n)
5082 return;
5083 IMPL->removeAttribute(n->nodeName());
5084}
5085
5086/*!
5087 Returns the QDomAttr object that corresponds to the attribute
5088 with the local name \a localName and the namespace URI \a nsURI.
5089 If no such attribute exists a \l{QDomNode::isNull()}{null
5090 attribute} is returned.
5091
5092 \sa setAttributeNode() attribute() setAttribute()
5093*/
5094QDomAttr QDomElement::attributeNodeNS(const QString& nsURI, const QString& localName)
5095{
5096 if (!impl)
5097 return QDomAttr();
5098 return QDomAttr(IMPL->attributeNodeNS(nsURI, localName));
5099}
5100
5101/*!
5102 Adds the attribute \a newAttr to this element.
5103
5104 If the element has another attribute that has the same local name
5105 and namespace URI as \a newAttr, this function replaces that
5106 attribute and returns it; otherwise the function returns a \link
5107 QDomNode::isNull() null attribute\endlink.
5108
5109 \sa attributeNodeNS() setAttributeNS() setAttributeNode()
5110*/
5111QDomAttr QDomElement::setAttributeNodeNS(const QDomAttr& newAttr)
5112{
5113 if (!impl)
5114 return QDomAttr();
5115 return QDomAttr(IMPL->setAttributeNodeNS(((QDomAttrPrivate*)newAttr.impl)));
5116}
5117
5118/*!
5119 Returns a QDomNodeList containing all descendants of this element
5120 with local name \a localName and namespace URI \a nsURI encountered
5121 during a preorder traversal of the element subtree with this element
5122 as its root. The order of the elements in the returned list is the
5123 order they are encountered during the preorder traversal.
5124
5125 \sa elementsByTagName() QDomDocument::elementsByTagNameNS()
5126*/
5127QDomNodeList QDomElement::elementsByTagNameNS(const QString& nsURI, const QString& localName) const
5128{
5129 return QDomNodeList(new QDomNodeListPrivate(impl, nsURI, localName));
5130}
5131
5132/*!
5133 Returns true if this element has an attribute with the local name
5134 \a localName and the namespace URI \a nsURI; otherwise returns
5135 false.
5136*/
5137bool QDomElement::hasAttributeNS(const QString& nsURI, const QString& localName) const
5138{
5139 if (!impl)
5140 return false;
5141 return IMPL->hasAttributeNS(nsURI, localName);
5142}
5143
5144/*!
5145 Returns the element's text or an empty string.
5146
5147 Example:
5148 \snippet doc/src/snippets/code/src_xml_dom_qdom.cpp 13
5149
5150 The function text() of the QDomElement for the \c{<h1>} tag,
5151 will return the following text:
5152
5153 \snippet doc/src/snippets/code/src_xml_dom_qdom.cpp 14
5154
5155 Comments are ignored by this function. It only evaluates QDomText
5156 and QDomCDATASection objects.
5157*/
5158QString QDomElement::text() const
5159{
5160 if (!impl)
5161 return QString();
5162 return IMPL->text();
5163}
5164
5165#undef IMPL
5166
5167/**************************************************************
5168 *
5169 * QDomTextPrivate
5170 *
5171 **************************************************************/
5172
5173QDomTextPrivate::QDomTextPrivate(QDomDocumentPrivate* d, QDomNodePrivate* parent, const QString& val)
5174 : QDomCharacterDataPrivate(d, parent, val)
5175{
5176 name = QLatin1String("#text");
5177}
5178
5179QDomTextPrivate::QDomTextPrivate(QDomTextPrivate* n, bool deep)
5180 : QDomCharacterDataPrivate(n, deep)
5181{
5182}
5183
5184QDomNodePrivate* QDomTextPrivate::cloneNode(bool deep)
5185{
5186 QDomNodePrivate* p = new QDomTextPrivate(this, deep);
5187 // We are not interested in this node
5188 p->ref.deref();
5189 return p;
5190}
5191
5192QDomTextPrivate* QDomTextPrivate::splitText(int offset)
5193{
5194 if (!parent()) {
5195 qWarning("QDomText::splitText The node has no parent. So I can not split");
5196 return 0;
5197 }
5198
5199 QDomTextPrivate* t = new QDomTextPrivate(ownerDocument(), 0, value.mid(offset));
5200 value.truncate(offset);
5201
5202 parent()->insertAfter(t, this);
5203
5204 return t;
5205}
5206
5207void QDomTextPrivate::save(QTextStream& s, int, int) const
5208{
5209 QDomTextPrivate *that = const_cast<QDomTextPrivate*>(this);
5210 s << encodeText(value, s, !(that->parent() && that->parent()->isElement()), false, true);
5211}
5212
5213/**************************************************************
5214 *
5215 * QDomText
5216 *
5217 **************************************************************/
5218
5219#define IMPL ((QDomTextPrivate*)impl)
5220
5221/*!
5222 \class QDomText
5223 \reentrant
5224 \brief The QDomText class represents text data in the parsed XML document.
5225
5226 \inmodule QtXml
5227 \ingroup xml-tools
5228
5229 You can split the text in a QDomText object over two QDomText
5230 objecs with splitText().
5231
5232 For further information about the Document Object Model see
5233 \l{http://www.w3.org/TR/REC-DOM-Level-1/}{Level 1} and
5234 \l{http://www.w3.org/TR/DOM-Level-2-Core/}{Level 2 Core}.
5235 For a more general introduction of the DOM implementation see the
5236 QDomDocument documentation.
5237*/
5238
5239/*!
5240 Constructs an empty QDomText object.
5241
5242 To construct a QDomText with content, use QDomDocument::createTextNode().
5243*/
5244QDomText::QDomText()
5245 : QDomCharacterData()
5246{
5247}
5248
5249/*!
5250 Constructs a copy of \a x.
5251
5252 The data of the copy is shared (shallow copy): modifying one node
5253 will also change the other. If you want to make a deep copy, use
5254 cloneNode().
5255*/
5256QDomText::QDomText(const QDomText& x)
5257 : QDomCharacterData(x)
5258{
5259}
5260
5261QDomText::QDomText(QDomTextPrivate* n)
5262 : QDomCharacterData(n)
5263{
5264}
5265
5266/*!
5267 Assigns \a x to this DOM text.
5268
5269 The data of the copy is shared (shallow copy): modifying one node
5270 will also change the other. If you want to make a deep copy, use
5271 cloneNode().
5272*/
5273QDomText& QDomText::operator= (const QDomText& x)
5274{
5275 return (QDomText&) QDomNode::operator=(x);
5276}
5277
5278/*!
5279 \fn QDomNode::NodeType QDomText::nodeType() const
5280
5281 Returns \c TextNode.
5282*/
5283
5284/*!
5285 Splits this DOM text object into two QDomText objects. This object
5286 keeps its first \a offset characters and the second (newly
5287 created) object is inserted into the document tree after this
5288 object with the remaining characters.
5289
5290 The function returns the newly created object.
5291
5292 \sa QDomNode::normalize()
5293*/
5294QDomText QDomText::splitText(int offset)
5295{
5296 if (!impl)
5297 return QDomText();
5298 return QDomText(IMPL->splitText(offset));
5299}
5300
5301#undef IMPL
5302
5303/**************************************************************
5304 *
5305 * QDomCommentPrivate
5306 *
5307 **************************************************************/
5308
5309QDomCommentPrivate::QDomCommentPrivate(QDomDocumentPrivate* d, QDomNodePrivate* parent, const QString& val)
5310 : QDomCharacterDataPrivate(d, parent, val)
5311{
5312 name = QLatin1String("#comment");
5313}
5314
5315QDomCommentPrivate::QDomCommentPrivate(QDomCommentPrivate* n, bool deep)
5316 : QDomCharacterDataPrivate(n, deep)
5317{
5318}
5319
5320
5321QDomNodePrivate* QDomCommentPrivate::cloneNode(bool deep)
5322{
5323 QDomNodePrivate* p = new QDomCommentPrivate(this, deep);
5324 // We are not interested in this node
5325 p->ref.deref();
5326 return p;
5327}
5328
5329void QDomCommentPrivate::save(QTextStream& s, int depth, int indent) const
5330{
5331 /* We don't output whitespace if we would pollute a text node. */
5332 if (!(prev && prev->isText()))
5333 s << QString(indent < 1 ? 0 : depth * indent, QLatin1Char(' '));
5334
5335 s << "<!--" << value;
5336 if (value.endsWith(QLatin1Char('-')))
5337 s << ' '; // Ensures that XML comment doesn't end with --->
5338 s << "-->";
5339
5340 if (!(next && next->isText()))
5341 s << endl;
5342}
5343
5344/**************************************************************
5345 *
5346 * QDomComment
5347 *
5348 **************************************************************/
5349
5350/*!
5351 \class QDomComment
5352 \reentrant
5353 \brief The QDomComment class represents an XML comment.
5354
5355 \inmodule QtXml
5356 \ingroup xml-tools
5357
5358 A comment in the parsed XML such as this:
5359 \snippet doc/src/snippets/code/src_xml_dom_qdom.cpp 15
5360 is represented by QDomComment objects in the parsed Dom tree.
5361
5362 For further information about the Document Object Model see
5363 \l{http://www.w3.org/TR/REC-DOM-Level-1/} and
5364 \l{http://www.w3.org/TR/DOM-Level-2-Core/}.
5365 For a more general introduction of the DOM implementation see the
5366 QDomDocument documentation.
5367*/
5368
5369/*!
5370 Constructs an empty comment. To construct a comment with content,
5371 use the QDomDocument::createComment() function.
5372*/
5373QDomComment::QDomComment()
5374 : QDomCharacterData()
5375{
5376}
5377
5378/*!
5379 Constructs a copy of \a x.
5380
5381 The data of the copy is shared (shallow copy): modifying one node
5382 will also change the other. If you want to make a deep copy, use
5383 cloneNode().
5384*/
5385QDomComment::QDomComment(const QDomComment& x)
5386 : QDomCharacterData(x)
5387{
5388}
5389
5390QDomComment::QDomComment(QDomCommentPrivate* n)
5391 : QDomCharacterData(n)
5392{
5393}
5394
5395/*!
5396 Assigns \a x to this DOM comment.
5397
5398 The data of the copy is shared (shallow copy): modifying one node
5399 will also change the other. If you want to make a deep copy, use
5400 cloneNode().
5401*/
5402QDomComment& QDomComment::operator= (const QDomComment& x)
5403{
5404 return (QDomComment&) QDomNode::operator=(x);
5405}
5406
5407/*!
5408 \fn QDomNode::NodeType QDomComment::nodeType() const
5409
5410 Returns \c CommentNode.
5411*/
5412
5413/**************************************************************
5414 *
5415 * QDomCDATASectionPrivate
5416 *
5417 **************************************************************/
5418
5419QDomCDATASectionPrivate::QDomCDATASectionPrivate(QDomDocumentPrivate* d, QDomNodePrivate* parent,
5420 const QString& val)
5421 : QDomTextPrivate(d, parent, val)
5422{
5423 name = QLatin1String("#cdata-section");
5424}
5425
5426QDomCDATASectionPrivate::QDomCDATASectionPrivate(QDomCDATASectionPrivate* n, bool deep)
5427 : QDomTextPrivate(n, deep)
5428{
5429}
5430
5431QDomNodePrivate* QDomCDATASectionPrivate::cloneNode(bool deep)
5432{
5433 QDomNodePrivate* p = new QDomCDATASectionPrivate(this, deep);
5434 // We are not interested in this node
5435 p->ref.deref();
5436 return p;
5437}
5438
5439void QDomCDATASectionPrivate::save(QTextStream& s, int, int) const
5440{
5441 // ### How do we escape "]]>" ?
5442 // "]]>" is not allowed; so there should be none in value anyway
5443 s << "<![CDATA[" << value << "]]>";
5444}
5445
5446/**************************************************************
5447 *
5448 * QDomCDATASection
5449 *
5450 **************************************************************/
5451
5452/*!
5453 \class QDomCDATASection
5454 \reentrant
5455 \brief The QDomCDATASection class represents an XML CDATA section.
5456
5457 \inmodule QtXml
5458 \ingroup xml-tools
5459
5460 CDATA sections are used to escape blocks of text containing
5461 characters that would otherwise be regarded as markup. The only
5462 delimiter that is recognized in a CDATA section is the "]]&gt;"
5463 string that terminates the CDATA section. CDATA sections cannot be
5464 nested. Their primary purpose is for including material such as
5465 XML fragments, without needing to escape all the delimiters.
5466
5467 Adjacent QDomCDATASection nodes are not merged by the
5468 QDomNode::normalize() function.
5469
5470 For further information about the Document Object Model see
5471 \l{http://www.w3.org/TR/REC-DOM-Level-1/} and
5472 \l{http://www.w3.org/TR/DOM-Level-2-Core/}.
5473 For a more general introduction of the DOM implementation see the
5474 QDomDocument documentation.
5475*/
5476
5477/*!
5478 Constructs an empty CDATA section. To create a CDATA section with
5479 content, use the QDomDocument::createCDATASection() function.
5480*/
5481QDomCDATASection::QDomCDATASection()
5482 : QDomText()
5483{
5484}
5485
5486/*!
5487 Constructs a copy of \a x.
5488
5489 The data of the copy is shared (shallow copy): modifying one node
5490 will also change the other. If you want to make a deep copy, use
5491 cloneNode().
5492*/
5493QDomCDATASection::QDomCDATASection(const QDomCDATASection& x)
5494 : QDomText(x)
5495{
5496}
5497
5498QDomCDATASection::QDomCDATASection(QDomCDATASectionPrivate* n)
5499 : QDomText(n)
5500{
5501}
5502
5503/*!
5504 Assigns \a x to this CDATA section.
5505
5506 The data of the copy is shared (shallow copy): modifying one node
5507 will also change the other. If you want to make a deep copy, use
5508 cloneNode().
5509*/
5510QDomCDATASection& QDomCDATASection::operator= (const QDomCDATASection& x)
5511{
5512 return (QDomCDATASection&) QDomNode::operator=(x);
5513}
5514
5515/*!
5516 \fn QDomNode::NodeType QDomCDATASection::nodeType() const
5517
5518 Returns \c CDATASection.
5519*/
5520
5521/**************************************************************
5522 *
5523 * QDomNotationPrivate
5524 *
5525 **************************************************************/
5526
5527QDomNotationPrivate::QDomNotationPrivate(QDomDocumentPrivate* d, QDomNodePrivate* parent,
5528 const QString& aname,
5529 const QString& pub, const QString& sys)
5530 : QDomNodePrivate(d, parent)
5531{
5532 name = aname;
5533 m_pub = pub;
5534 m_sys = sys;
5535}
5536
5537QDomNotationPrivate::QDomNotationPrivate(QDomNotationPrivate* n, bool deep)
5538 : QDomNodePrivate(n, deep)
5539{
5540 m_sys = n->m_sys;
5541 m_pub = n->m_pub;
5542}
5543
5544QDomNodePrivate* QDomNotationPrivate::cloneNode(bool deep)
5545{
5546 QDomNodePrivate* p = new QDomNotationPrivate(this, deep);
5547 // We are not interested in this node
5548 p->ref.deref();
5549 return p;
5550}
5551
5552void QDomNotationPrivate::save(QTextStream& s, int, int) const
5553{
5554 s << "<!NOTATION " << name << ' ';
5555 if (!m_pub.isNull()) {
5556 s << "PUBLIC " << quotedValue(m_pub);
5557 if (!m_sys.isNull())
5558 s << ' ' << quotedValue(m_sys);
5559 } else {
5560 s << "SYSTEM " << quotedValue(m_sys);
5561 }
5562 s << '>' << endl;
5563}
5564
5565/**************************************************************
5566 *
5567 * QDomNotation
5568 *
5569 **************************************************************/
5570
5571#define IMPL ((QDomNotationPrivate*)impl)
5572
5573/*!
5574 \class QDomNotation
5575 \reentrant
5576 \brief The QDomNotation class represents an XML notation.
5577
5578 \inmodule QtXml
5579 \ingroup xml-tools
5580
5581 A notation either declares, by name, the format of an unparsed
5582 entity (see section 4.7 of the XML 1.0 specification), or is used
5583 for formal declaration of processing instruction targets (see
5584 section 2.6 of the XML 1.0 specification).
5585
5586 DOM does not support editing notation nodes; they are therefore
5587 read-only.
5588
5589 A notation node does not have any parent.
5590
5591 You can retrieve the publicId() and systemId() from a notation
5592 node.
5593
5594 For further information about the Document Object Model see
5595 \l{http://www.w3.org/TR/REC-DOM-Level-1/}{Level 1} and
5596 \l{http://www.w3.org/TR/DOM-Level-2-Core/}{Level 2 Core}.
5597 For a more general introduction of the DOM implementation see the
5598 QDomDocument documentation.
5599*/
5600
5601
5602/*!
5603 Constructor.
5604*/
5605QDomNotation::QDomNotation()
5606 : QDomNode()
5607{
5608}
5609
5610/*!
5611 Constructs a copy of \a x.
5612
5613 The data of the copy is shared (shallow copy): modifying one node
5614 will also change the other. If you want to make a deep copy, use
5615 cloneNode().
5616*/
5617QDomNotation::QDomNotation(const QDomNotation& x)
5618 : QDomNode(x)
5619{
5620}
5621
5622QDomNotation::QDomNotation(QDomNotationPrivate* n)
5623 : QDomNode(n)
5624{
5625}
5626
5627/*!
5628 Assigns \a x to this DOM notation.
5629
5630 The data of the copy is shared (shallow copy): modifying one node
5631 will also change the other. If you want to make a deep copy, use
5632 cloneNode().
5633*/
5634QDomNotation& QDomNotation::operator= (const QDomNotation& x)
5635{
5636 return (QDomNotation&) QDomNode::operator=(x);
5637}
5638
5639/*!
5640 \fn QDomNode::NodeType QDomNotation::nodeType() const
5641
5642 Returns \c NotationNode.
5643*/
5644
5645/*!
5646 Returns the public identifier of this notation.
5647*/
5648QString QDomNotation::publicId() const
5649{
5650 if (!impl)
5651 return QString();
5652 return IMPL->m_pub;
5653}
5654
5655/*!
5656 Returns the system identifier of this notation.
5657*/
5658QString QDomNotation::systemId() const
5659{
5660 if (!impl)
5661 return QString();
5662 return IMPL->m_sys;
5663}
5664
5665#undef IMPL
5666
5667/**************************************************************
5668 *
5669 * QDomEntityPrivate
5670 *
5671 **************************************************************/
5672
5673QDomEntityPrivate::QDomEntityPrivate(QDomDocumentPrivate* d, QDomNodePrivate* parent,
5674 const QString& aname,
5675 const QString& pub, const QString& sys, const QString& notation)
5676 : QDomNodePrivate(d, parent)
5677{
5678 name = aname;
5679 m_pub = pub;
5680 m_sys = sys;
5681 m_notationName = notation;
5682}
5683
5684QDomEntityPrivate::QDomEntityPrivate(QDomEntityPrivate* n, bool deep)
5685 : QDomNodePrivate(n, deep)
5686{
5687 m_sys = n->m_sys;
5688 m_pub = n->m_pub;
5689 m_notationName = n->m_notationName;
5690}
5691
5692QDomNodePrivate* QDomEntityPrivate::cloneNode(bool deep)
5693{
5694 QDomNodePrivate* p = new QDomEntityPrivate(this, deep);
5695 // We are not interested in this node
5696 p->ref.deref();
5697 return p;
5698}
5699
5700/*
5701 Encode an entity value upon saving.
5702*/
5703static QByteArray encodeEntity(const QByteArray& str)
5704{
5705 QByteArray tmp(str);
5706 uint len = tmp.size();
5707 uint i = 0;
5708 const char* d = tmp.data();
5709 while (i < len) {
5710 if (d[i] == '%'){
5711 tmp.replace(i, 1, "&#60;");
5712 d = tmp;
5713 len += 4;
5714 i += 5;
5715 }
5716 else if (d[i] == '"') {
5717 tmp.replace(i, 1, "&#34;");
5718 d = tmp;
5719 len += 4;
5720 i += 5;
5721 } else if (d[i] == '&' && i + 1 < len && d[i+1] == '#') {
5722 // Dont encode &lt; or &quot; or &custom;.
5723 // Only encode character references
5724 tmp.replace(i, 1, "&#38;");
5725 d = tmp;
5726 len += 4;
5727 i += 5;
5728 } else {
5729 ++i;
5730 }
5731 }
5732
5733 return tmp;
5734}
5735
5736void QDomEntityPrivate::save(QTextStream& s, int, int) const
5737{
5738 QString _name = name;
5739 if (_name.startsWith(QLatin1Char('%')))
5740 _name = QLatin1String("% ") + _name.mid(1);
5741
5742 if (m_sys.isNull() && m_pub.isNull()) {
5743 s << "<!ENTITY " << _name << " \"" << encodeEntity(value.toUtf8()) << "\">" << endl;
5744 } else {
5745 s << "<!ENTITY " << _name << ' ';
5746 if (m_pub.isNull()) {
5747 s << "SYSTEM " << quotedValue(m_sys);
5748 } else {
5749 s << "PUBLIC " << quotedValue(m_pub) << ' ' << quotedValue(m_sys);
5750 }
5751 if (! m_notationName.isNull()) {
5752 s << " NDATA " << m_notationName;
5753 }
5754 s << '>' << endl;
5755 }
5756}
5757
5758/**************************************************************
5759 *
5760 * QDomEntity
5761 *
5762 **************************************************************/
5763
5764#define IMPL ((QDomEntityPrivate*)impl)
5765
5766/*!
5767 \class QDomEntity
5768 \reentrant
5769 \brief The QDomEntity class represents an XML entity.
5770
5771 \inmodule QtXml
5772 \ingroup xml-tools
5773
5774 This class represents an entity in an XML document, either parsed
5775 or unparsed. Note that this models the entity itself not the
5776 entity declaration.
5777
5778 DOM does not support editing entity nodes; if a user wants to make
5779 changes to the contents of an entity, every related
5780 QDomEntityReference node must be replaced in the DOM tree by a
5781 clone of the entity's contents, and then the desired changes must
5782 be made to each of the clones instead. All the descendants of an
5783 entity node are read-only.
5784
5785 An entity node does not have any parent.
5786
5787 You can access the entity's publicId(), systemId() and
5788 notationName() when available.
5789
5790 For further information about the Document Object Model see
5791 \l{http://www.w3.org/TR/REC-DOM-Level-1/}{Level 1} and
5792 \l{http://www.w3.org/TR/DOM-Level-2-Core/}{Level 2 Core}.
5793 For a more general introduction of the DOM implementation see the
5794 QDomDocument documentation.
5795*/
5796
5797
5798/*!
5799 Constructs an empty entity.
5800*/
5801QDomEntity::QDomEntity()
5802 : QDomNode()
5803{
5804}
5805
5806
5807/*!
5808 Constructs a copy of \a x.
5809
5810 The data of the copy is shared (shallow copy): modifying one node
5811 will also change the other. If you want to make a deep copy, use
5812 cloneNode().
5813*/
5814QDomEntity::QDomEntity(const QDomEntity& x)
5815 : QDomNode(x)
5816{
5817}
5818
5819QDomEntity::QDomEntity(QDomEntityPrivate* n)
5820 : QDomNode(n)
5821{
5822}
5823
5824/*!
5825 Assigns \a x to this DOM entity.
5826
5827 The data of the copy is shared (shallow copy): modifying one node
5828 will also change the other. If you want to make a deep copy, use
5829 cloneNode().
5830*/
5831QDomEntity& QDomEntity::operator= (const QDomEntity& x)
5832{
5833 return (QDomEntity&) QDomNode::operator=(x);
5834}
5835
5836/*!
5837 \fn QDomNode::NodeType QDomEntity::nodeType() const
5838
5839 Returns \c EntityNode.
5840*/
5841
5842/*!
5843 Returns the public identifier associated with this entity. If the
5844 public identifier was not specified an empty string is returned.
5845*/
5846QString QDomEntity::publicId() const
5847{
5848 if (!impl)
5849 return QString();
5850 return IMPL->m_pub;
5851}
5852
5853/*!
5854 Returns the system identifier associated with this entity. If the
5855 system identifier was not specified an empty string is returned.
5856*/
5857QString QDomEntity::systemId() const
5858{
5859 if (!impl)
5860 return QString();
5861 return IMPL->m_sys;
5862}
5863
5864/*!
5865 For unparsed entities this function returns the name of the
5866 notation for the entity. For parsed entities this function returns
5867 an empty string.
5868*/
5869QString QDomEntity::notationName() const
5870{
5871 if (!impl)
5872 return QString();
5873 return IMPL->m_notationName;
5874}
5875
5876#undef IMPL
5877
5878/**************************************************************
5879 *
5880 * QDomEntityReferencePrivate
5881 *
5882 **************************************************************/
5883
5884QDomEntityReferencePrivate::QDomEntityReferencePrivate(QDomDocumentPrivate* d, QDomNodePrivate* parent, const QString& aname)
5885 : QDomNodePrivate(d, parent)
5886{
5887 name = aname;
5888}
5889
5890QDomEntityReferencePrivate::QDomEntityReferencePrivate(QDomNodePrivate* n, bool deep)
5891 : QDomNodePrivate(n, deep)
5892{
5893}
5894
5895QDomNodePrivate* QDomEntityReferencePrivate::cloneNode(bool deep)
5896{
5897 QDomNodePrivate* p = new QDomEntityReferencePrivate(this, deep);
5898 // We are not interested in this node
5899 p->ref.deref();
5900 return p;
5901}
5902
5903void QDomEntityReferencePrivate::save(QTextStream& s, int, int) const
5904{
5905 s << '&' << name << ';';
5906}
5907
5908/**************************************************************
5909 *
5910 * QDomEntityReference
5911 *
5912 **************************************************************/
5913
5914/*!
5915 \class QDomEntityReference
5916 \reentrant
5917 \brief The QDomEntityReference class represents an XML entity reference.
5918
5919 \inmodule QtXml
5920 \ingroup xml-tools
5921
5922 A QDomEntityReference object may be inserted into the DOM tree
5923 when an entity reference is in the source document, or when the
5924 user wishes to insert an entity reference.
5925
5926 Note that character references and references to predefined
5927 entities are expanded by the XML processor so that characters are
5928 represented by their Unicode equivalent rather than by an entity
5929 reference.
5930
5931 Moreover, the XML processor may completely expand references to
5932 entities while building the DOM tree, instead of providing
5933 QDomEntityReference objects.
5934
5935 If it does provide such objects, then for a given entity reference
5936 node, it may be that there is no entity node representing the
5937 referenced entity; but if such an entity exists, then the child
5938 list of the entity reference node is the same as that of the
5939 entity node. As with the entity node, all descendants of the
5940 entity reference are read-only.
5941
5942 For further information about the Document Object Model see
5943 \l{http://www.w3.org/TR/REC-DOM-Level-1/}{Level 1} and
5944 \l{http://www.w3.org/TR/DOM-Level-2-Core/}{Level 2 Core}.
5945 For a more general introduction of the DOM implementation see the
5946 QDomDocument documentation.
5947*/
5948
5949/*!
5950 Constructs an empty entity reference. Use
5951 QDomDocument::createEntityReference() to create a entity reference
5952 with content.
5953*/
5954QDomEntityReference::QDomEntityReference()
5955 : QDomNode()
5956{
5957}
5958
5959/*!
5960 Constructs a copy of \a x.
5961
5962 The data of the copy is shared (shallow copy): modifying one node
5963 will also change the other. If you want to make a deep copy, use
5964 cloneNode().
5965*/
5966QDomEntityReference::QDomEntityReference(const QDomEntityReference& x)
5967 : QDomNode(x)
5968{
5969}
5970
5971QDomEntityReference::QDomEntityReference(QDomEntityReferencePrivate* n)
5972 : QDomNode(n)
5973{
5974}
5975
5976/*!
5977 Assigns \a x to this entity reference.
5978
5979 The data of the copy is shared (shallow copy): modifying one node
5980 will also change the other. If you want to make a deep copy, use
5981 cloneNode().
5982*/
5983QDomEntityReference& QDomEntityReference::operator= (const QDomEntityReference& x)
5984{
5985 return (QDomEntityReference&) QDomNode::operator=(x);
5986}
5987
5988/*!
5989 \fn QDomNode::NodeType QDomEntityReference::nodeType() const
5990
5991 Returns \c EntityReference.
5992*/
5993
5994/**************************************************************
5995 *
5996 * QDomProcessingInstructionPrivate
5997 *
5998 **************************************************************/
5999
6000QDomProcessingInstructionPrivate::QDomProcessingInstructionPrivate(QDomDocumentPrivate* d,
6001 QDomNodePrivate* parent, const QString& target, const QString& data)
6002 : QDomNodePrivate(d, parent)
6003{
6004 name = target;
6005 value = data;
6006}
6007
6008QDomProcessingInstructionPrivate::QDomProcessingInstructionPrivate(QDomProcessingInstructionPrivate* n, bool deep)
6009 : QDomNodePrivate(n, deep)
6010{
6011}
6012
6013
6014QDomNodePrivate* QDomProcessingInstructionPrivate::cloneNode(bool deep)
6015{
6016 QDomNodePrivate* p = new QDomProcessingInstructionPrivate(this, deep);
6017 // We are not interested in this node
6018 p->ref.deref();
6019 return p;
6020}
6021
6022void QDomProcessingInstructionPrivate::save(QTextStream& s, int, int) const
6023{
6024 s << "<?" << name << ' ' << value << "?>" << endl;
6025}
6026
6027/**************************************************************
6028 *
6029 * QDomProcessingInstruction
6030 *
6031 **************************************************************/
6032
6033/*!
6034 \class QDomProcessingInstruction
6035 \reentrant
6036 \brief The QDomProcessingInstruction class represents an XML processing
6037 instruction.
6038
6039 \inmodule QtXml
6040 \ingroup xml-tools
6041
6042 Processing instructions are used in XML to keep processor-specific
6043 information in the text of the document.
6044
6045 The XML declaration that appears at the top of an XML document,
6046 typically \tt{<?xml version='1.0' encoding='UTF-8'?>}, is treated by QDom as a
6047 processing instruction. This is unfortunate, since the XML declaration is
6048 not a processing instruction; among other differences, it cannot be
6049 inserted into a document anywhere but on the first line.
6050
6051 Do not use this function to create an xml declaration, since although it
6052 has the same syntax as a processing instruction, it isn't, and might not
6053 be treated by QDom as such.
6054
6055 The content of the processing instruction is retrieved with data()
6056 and set with setData(). The processing instruction's target is
6057 retrieved with target().
6058
6059 For further information about the Document Object Model see
6060 \l{http://www.w3.org/TR/REC-DOM-Level-1/}{Level 1} and
6061 \l{http://www.w3.org/TR/DOM-Level-2-Core/}{Level 2 Core}.
6062 For a more general introduction of the DOM implementation see the
6063 QDomDocument documentation.
6064*/
6065
6066/*!
6067 Constructs an empty processing instruction. Use
6068 QDomDocument::createProcessingInstruction() to create a processing
6069 instruction with content.
6070*/
6071QDomProcessingInstruction::QDomProcessingInstruction()
6072 : QDomNode()
6073{
6074}
6075
6076/*!
6077 Constructs a copy of \a x.
6078
6079 The data of the copy is shared (shallow copy): modifying one node
6080 will also change the other. If you want to make a deep copy, use
6081 cloneNode().
6082*/
6083QDomProcessingInstruction::QDomProcessingInstruction(const QDomProcessingInstruction& x)
6084 : QDomNode(x)
6085{
6086}
6087
6088QDomProcessingInstruction::QDomProcessingInstruction(QDomProcessingInstructionPrivate* n)
6089 : QDomNode(n)
6090{
6091}
6092
6093/*!
6094 Assigns \a x to this processing instruction.
6095
6096 The data of the copy is shared (shallow copy): modifying one node
6097 will also change the other. If you want to make a deep copy, use
6098 cloneNode().
6099*/
6100QDomProcessingInstruction& QDomProcessingInstruction::operator= (const QDomProcessingInstruction& x)
6101{
6102 return (QDomProcessingInstruction&) QDomNode::operator=(x);
6103}
6104
6105/*!
6106 \fn QDomNode::NodeType QDomProcessingInstruction::nodeType() const
6107
6108 Returns \c ProcessingInstructionNode.
6109*/
6110
6111/*!
6112 Returns the target of this processing instruction.
6113
6114 \sa data()
6115*/
6116QString QDomProcessingInstruction::target() const
6117{
6118 if (!impl)
6119 return QString();
6120 return impl->nodeName();
6121}
6122
6123/*!
6124 Returns the content of this processing instruction.
6125
6126 \sa setData() target()
6127*/
6128QString QDomProcessingInstruction::data() const
6129{
6130 if (!impl)
6131 return QString();
6132 return impl->nodeValue();
6133}
6134
6135/*!
6136 Sets the data contained in the processing instruction to \a d.
6137
6138 \sa data()
6139*/
6140void QDomProcessingInstruction::setData(const QString& d)
6141{
6142 if (!impl)
6143 return;
6144 impl->setNodeValue(d);
6145}
6146
6147/**************************************************************
6148 *
6149 * QDomDocumentPrivate
6150 *
6151 **************************************************************/
6152
6153QDomDocumentPrivate::QDomDocumentPrivate()
6154 : QDomNodePrivate(0),
6155 impl(new QDomImplementationPrivate),
6156 nodeListTime(1)
6157{
6158 type = new QDomDocumentTypePrivate(this, this);
6159 type->ref.deref();
6160
6161 name = QLatin1String("#document");
6162}
6163
6164QDomDocumentPrivate::QDomDocumentPrivate(const QString& aname)
6165 : QDomNodePrivate(0),
6166 impl(new QDomImplementationPrivate),
6167 nodeListTime(1)
6168{
6169 type = new QDomDocumentTypePrivate(this, this);
6170 type->ref.deref();
6171 type->name = aname;
6172
6173 name = QLatin1String("#document");
6174}
6175
6176QDomDocumentPrivate::QDomDocumentPrivate(QDomDocumentTypePrivate* dt)
6177 : QDomNodePrivate(0),
6178 impl(new QDomImplementationPrivate),
6179 nodeListTime(1)
6180{
6181 if (dt != 0) {
6182 type = dt;
6183 } else {
6184 type = new QDomDocumentTypePrivate(this, this);
6185 type->ref.deref();
6186 }
6187
6188 name = QLatin1String("#document");
6189}
6190
6191QDomDocumentPrivate::QDomDocumentPrivate(QDomDocumentPrivate* n, bool deep)
6192 : QDomNodePrivate(n, deep),
6193 impl(n->impl->clone()),
6194 nodeListTime(1)
6195{
6196 type = static_cast<QDomDocumentTypePrivate*>(n->type->cloneNode());
6197 type->setParent(this);
6198}
6199
6200QDomDocumentPrivate::~QDomDocumentPrivate()
6201{
6202}
6203
6204void QDomDocumentPrivate::clear()
6205{
6206 impl.reset();
6207 type.reset();
6208 QDomNodePrivate::clear();
6209}
6210
6211static void initializeReader(QXmlSimpleReader &reader, bool namespaceProcessing)
6212{
6213 reader.setFeature(QLatin1String("http://xml.org/sax/features/namespaces"), namespaceProcessing);
6214 reader.setFeature(QLatin1String("http://xml.org/sax/features/namespace-prefixes"), !namespaceProcessing);
6215 reader.setFeature(QLatin1String("http://trolltech.com/xml/features/report-whitespace-only-CharData"), false); // Shouldn't change in Qt 4
6216}
6217
6218bool QDomDocumentPrivate::setContent(QXmlInputSource *source, bool namespaceProcessing, QString *errorMsg, int *errorLine, int *errorColumn)
6219{
6220 QXmlSimpleReader reader;
6221 initializeReader(reader, namespaceProcessing);
6222 return setContent(source, &reader, errorMsg, errorLine, errorColumn);
6223}
6224
6225bool QDomDocumentPrivate::setContent(QXmlInputSource *source, QXmlReader *reader, QString *errorMsg, int *errorLine, int *errorColumn)
6226{
6227 clear();
6228 impl = new QDomImplementationPrivate;
6229 type = new QDomDocumentTypePrivate(this, this);
6230 type->ref.deref();
6231
6232 bool namespaceProcessing = reader->feature(QLatin1String("http://xml.org/sax/features/namespaces"))
6233 && !reader->feature(QLatin1String("http://xml.org/sax/features/namespace-prefixes"));
6234
6235 QDomHandler hnd(this, namespaceProcessing);
6236 reader->setContentHandler(&hnd);
6237 reader->setErrorHandler(&hnd);
6238 reader->setLexicalHandler(&hnd);
6239 reader->setDeclHandler(&hnd);
6240 reader->setDTDHandler(&hnd);
6241
6242 if (!reader->parse(source)) {
6243 if (errorMsg)
6244 *errorMsg = hnd.errorMsg;
6245 if (errorLine)
6246 *errorLine = hnd.errorLine;
6247 if (errorColumn)
6248 *errorColumn = hnd.errorColumn;
6249 return false;
6250 }
6251
6252 return true;
6253}
6254
6255QDomNodePrivate* QDomDocumentPrivate::cloneNode(bool deep)
6256{
6257 QDomNodePrivate *p = new QDomDocumentPrivate(this, deep);
6258 // We are not interested in this node
6259 p->ref.deref();
6260 return p;
6261}
6262
6263QDomElementPrivate* QDomDocumentPrivate::documentElement()
6264{
6265 QDomNodePrivate *p = first;
6266 while (p && !p->isElement())
6267 p = p->next;
6268
6269 return static_cast<QDomElementPrivate *>(p);
6270}
6271
6272QDomElementPrivate* QDomDocumentPrivate::createElement(const QString &tagName)
6273{
6274 bool ok;
6275 QString fixedName = fixedXmlName(tagName, &ok);
6276 if (!ok)
6277 return 0;
6278
6279 QDomElementPrivate *e = new QDomElementPrivate(this, 0, fixedName);
6280 e->ref.deref();
6281 return e;
6282}
6283
6284QDomElementPrivate* QDomDocumentPrivate::createElementNS(const QString &nsURI, const QString &qName)
6285{
6286 bool ok;
6287 QString fixedName = fixedXmlName(qName, &ok, true);
6288 if (!ok)
6289 return 0;
6290
6291 QDomElementPrivate *e = new QDomElementPrivate(this, 0, nsURI, fixedName);
6292 e->ref.deref();
6293 return e;
6294}
6295
6296QDomDocumentFragmentPrivate* QDomDocumentPrivate::createDocumentFragment()
6297{
6298 QDomDocumentFragmentPrivate *f = new QDomDocumentFragmentPrivate(this, (QDomNodePrivate*)0);
6299 f->ref.deref();
6300 return f;
6301}
6302
6303QDomTextPrivate* QDomDocumentPrivate::createTextNode(const QString &data)
6304{
6305 bool ok;
6306 QString fixedData = fixedCharData(data, &ok);
6307 if (!ok)
6308 return 0;
6309
6310 QDomTextPrivate *t = new QDomTextPrivate(this, 0, fixedData);
6311 t->ref.deref();
6312 return t;
6313}
6314
6315QDomCommentPrivate* QDomDocumentPrivate::createComment(const QString &data)
6316{
6317 bool ok;
6318 QString fixedData = fixedComment(data, &ok);
6319 if (!ok)
6320 return 0;
6321
6322 QDomCommentPrivate *c = new QDomCommentPrivate(this, 0, fixedData);
6323 c->ref.deref();
6324 return c;
6325}
6326
6327QDomCDATASectionPrivate* QDomDocumentPrivate::createCDATASection(const QString &data)
6328{
6329 bool ok;
6330 QString fixedData = fixedCDataSection(data, &ok);
6331 if (!ok)
6332 return 0;
6333
6334 QDomCDATASectionPrivate *c = new QDomCDATASectionPrivate(this, 0, fixedData);
6335 c->ref.deref();
6336 return c;
6337}
6338
6339QDomProcessingInstructionPrivate* QDomDocumentPrivate::createProcessingInstruction(const QString &target,
6340 const QString &data)
6341{
6342 bool ok;
6343 QString fixedData = fixedPIData(data, &ok);
6344 if (!ok)
6345 return 0;
6346 // [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
6347 QString fixedTarget = fixedXmlName(target, &ok);
6348 if (!ok)
6349 return 0;
6350
6351 QDomProcessingInstructionPrivate *p = new QDomProcessingInstructionPrivate(this, 0, fixedTarget, fixedData);
6352 p->ref.deref();
6353 return p;
6354}
6355QDomAttrPrivate* QDomDocumentPrivate::createAttribute(const QString &aname)
6356{
6357 bool ok;
6358 QString fixedName = fixedXmlName(aname, &ok);
6359 if (!ok)
6360 return 0;
6361
6362 QDomAttrPrivate *a = new QDomAttrPrivate(this, 0, fixedName);
6363 a->ref.deref();
6364 return a;
6365}
6366
6367QDomAttrPrivate* QDomDocumentPrivate::createAttributeNS(const QString &nsURI, const QString &qName)
6368{
6369 bool ok;
6370 QString fixedName = fixedXmlName(qName, &ok, true);
6371 if (!ok)
6372 return 0;
6373
6374 QDomAttrPrivate *a = new QDomAttrPrivate(this, 0, nsURI, fixedName);
6375 a->ref.deref();
6376 return a;
6377}
6378
6379QDomEntityReferencePrivate* QDomDocumentPrivate::createEntityReference(const QString &aname)
6380{
6381 bool ok;
6382 QString fixedName = fixedXmlName(aname, &ok);
6383 if (!ok)
6384 return 0;
6385
6386 QDomEntityReferencePrivate *e = new QDomEntityReferencePrivate(this, 0, fixedName);
6387 e->ref.deref();
6388 return e;
6389}
6390
6391QDomNodePrivate* QDomDocumentPrivate::importNode(const QDomNodePrivate *importedNode, bool deep)
6392{
6393 QDomNodePrivate *node = 0;
6394 switch (importedNode->nodeType()) {
6395 case QDomNode::AttributeNode:
6396 node = new QDomAttrPrivate((QDomAttrPrivate*)importedNode, true);
6397 break;
6398 case QDomNode::DocumentFragmentNode:
6399 node = new QDomDocumentFragmentPrivate((QDomDocumentFragmentPrivate*)importedNode, deep);
6400 break;
6401 case QDomNode::ElementNode:
6402 node = new QDomElementPrivate((QDomElementPrivate*)importedNode, deep);
6403 break;
6404 case QDomNode::EntityNode:
6405 node = new QDomEntityPrivate((QDomEntityPrivate*)importedNode, deep);
6406 break;
6407 case QDomNode::EntityReferenceNode:
6408 node = new QDomEntityReferencePrivate((QDomEntityReferencePrivate*)importedNode, false);
6409 break;
6410 case QDomNode::NotationNode:
6411 node = new QDomNotationPrivate((QDomNotationPrivate*)importedNode, deep);
6412 break;
6413 case QDomNode::ProcessingInstructionNode:
6414 node = new QDomProcessingInstructionPrivate((QDomProcessingInstructionPrivate*)importedNode, deep);
6415 break;
6416 case QDomNode::TextNode:
6417 node = new QDomTextPrivate((QDomTextPrivate*)importedNode, deep);
6418 break;
6419 case QDomNode::CDATASectionNode:
6420 node = new QDomCDATASectionPrivate((QDomCDATASectionPrivate*)importedNode, deep);
6421 break;
6422 case QDomNode::CommentNode:
6423 node = new QDomCommentPrivate((QDomCommentPrivate*)importedNode, deep);
6424 break;
6425 default:
6426 break;
6427 }
6428 if (node) {
6429 node->setOwnerDocument(this);
6430 // The QDomNode constructor increases the refcount, so deref first to
6431 // keep refcount balanced.
6432 node->ref.deref();
6433 }
6434 return node;
6435}
6436
6437void QDomDocumentPrivate::saveDocument(QTextStream& s, const int indent, QDomNode::EncodingPolicy encUsed) const
6438{
6439 const QDomNodePrivate* n = first;
6440
6441 if(encUsed == QDomNode::EncodingFromDocument) {
6442#ifndef QT_NO_TEXTCODEC
6443 const QDomNodePrivate* n = first;
6444
6445 QTextCodec *codec = 0;
6446
6447 if (n && n->isProcessingInstruction() && n->nodeName() == QLatin1String("xml")) {
6448 // we have an XML declaration
6449 QString data = n->nodeValue();
6450 QRegExp encoding(QString::fromLatin1("encoding\\s*=\\s*((\"([^\"]*)\")|('([^']*)'))"));
6451 encoding.indexIn(data);
6452 QString enc = encoding.cap(3);
6453 if (enc.isEmpty())
6454 enc = encoding.cap(5);
6455 if (!enc.isEmpty())
6456 codec = QTextCodec::codecForName(enc.toLatin1().data());
6457 }
6458 if (!codec)
6459 codec = QTextCodec::codecForName("UTF-8");
6460 if (codec)
6461 s.setCodec(codec);
6462#endif
6463 bool doc = false;
6464
6465 while (n) {
6466 if (!doc && !(n->isProcessingInstruction() && n->nodeName() == QLatin1String("xml"))) {
6467 // save doctype after XML declaration
6468 type->save(s, 0, indent);
6469 doc = true;
6470 }
6471 n->save(s, 0, indent);
6472 n = n->next;
6473 }
6474 }
6475 else {
6476
6477 // Write out the XML declaration.
6478#ifdef QT_NO_TEXTCODEC
6479 const QLatin1String codecName("iso-8859-1");
6480#else
6481 const QTextCodec *const codec = s.codec();
6482 Q_ASSERT_X(codec, "QDomNode::save()", "A codec must be specified in the text stream.");
6483 const QByteArray codecName = codec->name();
6484#endif
6485
6486 s << "<?xml version=\"1.0\" encoding=\""
6487 << codecName
6488 << "\"?>\n";
6489
6490 // Skip the first processing instruction by name "xml", if any such exists.
6491 const QDomNodePrivate* startNode = n;
6492
6493 // First, we try to find the PI and sets the startNode to the one appearing after it.
6494 while (n) {
6495 if(n->isProcessingInstruction() && n->nodeName() == QLatin1String("xml")) {
6496 startNode = n->next;
6497 break;
6498 }
6499 else
6500 n = n->next;
6501 }
6502
6503 // Now we serialize all the nodes after the faked XML declaration(the PI).
6504 while(startNode) {
6505 startNode->save(s, 0, indent);
6506 startNode = startNode->next;
6507 }
6508 }
6509}
6510
6511/**************************************************************
6512 *
6513 * QDomDocument
6514 *
6515 **************************************************************/
6516
6517#define IMPL ((QDomDocumentPrivate*)impl)
6518
6519/*!
6520 \class QDomDocument
6521 \reentrant
6522 \brief The QDomDocument class represents an XML document.
6523
6524 \inmodule QtXml
6525
6526 \ingroup xml-tools
6527
6528 The QDomDocument class represents the entire XML document.
6529 Conceptually, it is the root of the document tree, and provides
6530 the primary access to the document's data.
6531
6532 Since elements, text nodes, comments, processing instructions,
6533 etc., cannot exist outside the context of a document, the document
6534 class also contains the factory functions needed to create these
6535 objects. The node objects created have an ownerDocument() function
6536 which associates them with the document within whose context they
6537 were created. The DOM classes that will be used most often are
6538 QDomNode, QDomDocument, QDomElement and QDomText.
6539
6540 The parsed XML is represented internally by a tree of objects that
6541 can be accessed using the various QDom classes. All QDom classes
6542 only \e reference objects in the internal tree. The internal
6543 objects in the DOM tree will get deleted once the last QDom
6544 object referencing them and the QDomDocument itself are deleted.
6545
6546 Creation of elements, text nodes, etc. is done using the various
6547 factory functions provided in this class. Using the default
6548 constructors of the QDom classes will only result in empty
6549 objects that cannot be manipulated or inserted into the Document.
6550
6551 The QDomDocument class has several functions for creating document
6552 data, for example, createElement(), createTextNode(),
6553 createComment(), createCDATASection(),
6554 createProcessingInstruction(), createAttribute() and
6555 createEntityReference(). Some of these functions have versions
6556 that support namespaces, i.e. createElementNS() and
6557 createAttributeNS(). The createDocumentFragment() function is used
6558 to hold parts of the document; this is useful for manipulating for
6559 complex documents.
6560
6561 The entire content of the document is set with setContent(). This
6562 function parses the string it is passed as an XML document and
6563 creates the DOM tree that represents the document. The root
6564 element is available using documentElement(). The textual
6565 representation of the document can be obtained using toString().
6566
6567 It is possible to insert a node from another document into the
6568 document using importNode().
6569
6570 You can obtain a list of all the elements that have a particular
6571 tag with elementsByTagName() or with elementsByTagNameNS().
6572
6573 The QDom classes are typically used as follows:
6574 \snippet doc/src/snippets/code/src_xml_dom_qdom.cpp 16
6575
6576 Once \c doc and \c elem go out of scope, the whole internal tree
6577 representing the XML document is deleted.
6578
6579 To create a document using DOM use code like this:
6580 \snippet doc/src/snippets/code/src_xml_dom_qdom.cpp 17
6581
6582 For further information about the Document Object Model see
6583 the Document Object Model (DOM)
6584 \l{http://www.w3.org/TR/REC-DOM-Level-1/}{Level 1} and
6585 \l{http://www.w3.org/TR/DOM-Level-2-Core/}{Level 2 Core}
6586 Specifications.
6587
6588 \sa {DOM Bookmarks Example}, {Simple DOM Model Example}
6589*/
6590
6591
6592/*!
6593 Constructs an empty document.
6594*/
6595QDomDocument::QDomDocument()
6596{
6597 impl = 0;
6598}
6599
6600/*!
6601 Creates a document and sets the name of the document type to \a
6602 name.
6603*/
6604QDomDocument::QDomDocument(const QString& name)
6605{
6606 // We take over ownership
6607 impl = new QDomDocumentPrivate(name);
6608}
6609
6610/*!
6611 Creates a document with the document type \a doctype.
6612
6613 \sa QDomImplementation::createDocumentType()
6614*/
6615QDomDocument::QDomDocument(const QDomDocumentType& doctype)
6616{
6617 impl = new QDomDocumentPrivate((QDomDocumentTypePrivate*)(doctype.impl));
6618}
6619
6620/*!
6621 Constructs a copy of \a x.
6622
6623 The data of the copy is shared (shallow copy): modifying one node
6624 will also change the other. If you want to make a deep copy, use
6625 cloneNode().
6626*/
6627QDomDocument::QDomDocument(const QDomDocument& x)
6628 : QDomNode(x)
6629{
6630}
6631
6632QDomDocument::QDomDocument(QDomDocumentPrivate* x)
6633 : QDomNode(x)
6634{
6635}
6636
6637/*!
6638 Assigns \a x to this DOM document.
6639
6640 The data of the copy is shared (shallow copy): modifying one node
6641 will also change the other. If you want to make a deep copy, use
6642 cloneNode().
6643*/
6644QDomDocument& QDomDocument::operator= (const QDomDocument& x)
6645{
6646 return (QDomDocument&) QDomNode::operator=(x);
6647}
6648
6649/*!
6650 Destroys the object and frees its resources.
6651*/
6652QDomDocument::~QDomDocument()
6653{
6654}
6655
6656/*!
6657 \overload
6658
6659 This function reads the XML document from the string \a text, returning
6660 true if the content was successfully parsed; otherwise returns false.
6661 Since \a text is already a Unicode string, no encoding detection
6662 is done.
6663*/
6664bool QDomDocument::setContent(const QString& text, bool namespaceProcessing, QString *errorMsg, int *errorLine, int *errorColumn)
6665{
6666 if (!impl)
6667 impl = new QDomDocumentPrivate();
6668 QXmlInputSource source;
6669 source.setData(text);
6670 return IMPL->setContent(&source, namespaceProcessing, errorMsg, errorLine, errorColumn);
6671}
6672
6673/*!
6674 \nonreentrant
6675
6676 This function parses the XML document from the byte array \a
6677 data and sets it as the content of the document. It tries to
6678 detect the encoding of the document as required by the XML
6679 specification.
6680
6681 If \a namespaceProcessing is true, the parser recognizes
6682 namespaces in the XML file and sets the prefix name, local name
6683 and namespace URI to appropriate values. If \a namespaceProcessing
6684 is false, the parser does no namespace processing when it reads
6685 the XML file.
6686
6687 If a parse error occurs, this function returns false and the error
6688 message is placed in \c{*}\a{errorMsg}, the line number in
6689 \c{*}\a{errorLine} and the column number in \c{*}\a{errorColumn}
6690 (unless the associated pointer is set to 0); otherwise this
6691 function returns true. The various error messages are described in
6692 the QXmlParseException class documentation. Note that, if you
6693 want to display these error messages to your application's users,
6694 they will be displayed in English unless they are explicitly
6695 translated.
6696
6697 If \a namespaceProcessing is true, the function QDomNode::prefix()
6698 returns a string for all elements and attributes. It returns an
6699 empty string if the element or attribute has no prefix.
6700
6701 Text nodes consisting only of whitespace are stripped and won't
6702 appear in the QDomDocument. If this behavior is not desired,
6703 one can use the setContent() overload that allows a QXmlReader to be
6704 supplied.
6705
6706 If \a namespaceProcessing is false, the functions
6707 QDomNode::prefix(), QDomNode::localName() and
6708 QDomNode::namespaceURI() return an empty string.
6709
6710 Entity references are handled as follows:
6711 \list
6712 \o References to internal general entities and character entities occurring in the
6713 content are included. The result is a QDomText node with the references replaced
6714 by their corresponding entity values.
6715 \o References to parameter entities occurring in the internal subset are included.
6716 The result is a QDomDocumentType node which contains entity and notation declarations
6717 with the references replaced by their corresponding entity values.
6718 \o Any general parsed entity reference which is not defined in the internal subset and
6719 which occurs in the content is represented as a QDomEntityReference node.
6720 \o Any parsed entity reference which is not defined in the internal subset and which
6721 occurs outside of the content is replaced with an empty string.
6722 \o Any unparsed entity reference is replaced with an empty string.
6723 \endlist
6724
6725 \sa QDomNode::namespaceURI() QDomNode::localName()
6726 QDomNode::prefix() QString::isNull() QString::isEmpty()
6727*/
6728bool QDomDocument::setContent(const QByteArray &data, bool namespaceProcessing, QString *errorMsg, int *errorLine, int *errorColumn)
6729{
6730 if (!impl)
6731 impl = new QDomDocumentPrivate();
6732 QBuffer buf;
6733 buf.setData(data);
6734 QXmlInputSource source(&buf);
6735 return IMPL->setContent(&source, namespaceProcessing, errorMsg, errorLine, errorColumn);
6736}
6737
6738/*!
6739 \overload
6740
6741 This function reads the XML document from the IO device \a dev, returning
6742 true if the content was successfully parsed; otherwise returns false.
6743*/
6744bool QDomDocument::setContent(QIODevice* dev, bool namespaceProcessing, QString *errorMsg, int *errorLine, int *errorColumn)
6745{
6746 if (!impl)
6747 impl = new QDomDocumentPrivate();
6748 QXmlInputSource source(dev);
6749 return IMPL->setContent(&source, namespaceProcessing, errorMsg, errorLine, errorColumn);
6750}
6751
6752/*!
6753 \overload
6754 \since 4.5
6755
6756 This function reads the XML document from the QXmlInputSource \a source,
6757 returning true if the content was successfully parsed; otherwise returns false.
6758
6759*/
6760bool QDomDocument::setContent(QXmlInputSource *source, bool namespaceProcessing, QString *errorMsg, int *errorLine, int *errorColumn )
6761{
6762 if (!impl)
6763 impl = new QDomDocumentPrivate();
6764 QXmlSimpleReader reader;
6765 initializeReader(reader, namespaceProcessing);
6766 return IMPL->setContent(source, &reader, errorMsg, errorLine, errorColumn);
6767}
6768
6769/*!
6770 \overload
6771
6772 This function reads the XML document from the string \a text, returning
6773 true if the content was successfully parsed; otherwise returns false.
6774 Since \a text is already a Unicode string, no encoding detection
6775 is performed.
6776
6777 No namespace processing is performed either.
6778*/
6779bool QDomDocument::setContent(const QString& text, QString *errorMsg, int *errorLine, int *errorColumn)
6780{
6781 return setContent(text, false, errorMsg, errorLine, errorColumn);
6782}
6783
6784/*!
6785 \overload
6786
6787 This function reads the XML document from the byte array \a buffer,
6788 returning true if the content was successfully parsed; otherwise returns
6789 false.
6790
6791 No namespace processing is performed.
6792*/
6793bool QDomDocument::setContent(const QByteArray& buffer, QString *errorMsg, int *errorLine, int *errorColumn )
6794{
6795 return setContent(buffer, false, errorMsg, errorLine, errorColumn);
6796}
6797
6798/*!
6799 \overload
6800
6801 This function reads the XML document from the IO device \a dev, returning
6802 true if the content was successfully parsed; otherwise returns false.
6803
6804 No namespace processing is performed.
6805*/
6806bool QDomDocument::setContent(QIODevice* dev, QString *errorMsg, int *errorLine, int *errorColumn )
6807{
6808 return setContent(dev, false, errorMsg, errorLine, errorColumn);
6809}
6810
6811/*!
6812 \overload
6813
6814 This function reads the XML document from the QXmlInputSource \a source and
6815 parses it with the QXmlReader \a reader, returning true if the content was
6816 successfully parsed; otherwise returns false.
6817
6818 This function doesn't change the features of the \a reader. If you want to
6819 use certain features for parsing you can use this function to set up the
6820 reader appropriately.
6821
6822 \sa QXmlSimpleReader
6823*/
6824bool QDomDocument::setContent(QXmlInputSource *source, QXmlReader *reader, QString *errorMsg, int *errorLine, int *errorColumn )
6825{
6826 if (!impl)
6827 impl = new QDomDocumentPrivate();
6828 return IMPL->setContent(source, reader, errorMsg, errorLine, errorColumn);
6829}
6830
6831/*!
6832 Converts the parsed document back to its textual representation.
6833
6834 This function uses \a indent as the amount of space to indent
6835 subelements.
6836
6837 If \a indent is -1, no whitespace at all is added.
6838*/
6839QString QDomDocument::toString(int indent) const
6840{
6841 QString str;
6842 QTextStream s(&str, QIODevice::WriteOnly);
6843 save(s, indent);
6844 return str;
6845}
6846
6847/*!
6848 Converts the parsed document back to its textual representation
6849 and returns a QByteArray containing the data encoded as UTF-8.
6850
6851 This function uses \a indent as the amount of space to indent
6852 subelements.
6853
6854 \sa toString()
6855*/
6856QByteArray QDomDocument::toByteArray(int indent) const
6857{
6858 // ### if there is an encoding specified in the xml declaration, this
6859 // encoding declaration should be changed to utf8
6860 return toString(indent).toUtf8();
6861}
6862
6863
6864/*!
6865 Returns the document type of this document.
6866*/
6867QDomDocumentType QDomDocument::doctype() const
6868{
6869 if (!impl)
6870 return QDomDocumentType();
6871 return QDomDocumentType(IMPL->doctype());
6872}
6873
6874/*!
6875 Returns a QDomImplementation object.
6876*/
6877QDomImplementation QDomDocument::implementation() const
6878{
6879 if (!impl)
6880 return QDomImplementation();
6881 return QDomImplementation(IMPL->implementation());
6882}
6883
6884/*!
6885 Returns the root element of the document.
6886*/
6887QDomElement QDomDocument::documentElement() const
6888{
6889 if (!impl)
6890 return QDomElement();
6891 return QDomElement(IMPL->documentElement());
6892}
6893
6894/*!
6895 Creates a new element called \a tagName that can be inserted into
6896 the DOM tree, e.g. using QDomNode::appendChild().
6897
6898 If \a tagName is not a valid XML name, the behavior of this function is governed
6899 by QDomImplementation::InvalidDataPolicy.
6900
6901 \sa createElementNS() QDomNode::appendChild() QDomNode::insertBefore()
6902 QDomNode::insertAfter()
6903*/
6904QDomElement QDomDocument::createElement(const QString& tagName)
6905{
6906 if (!impl)
6907 impl = new QDomDocumentPrivate();
6908 return QDomElement(IMPL->createElement(tagName));
6909}
6910
6911/*!
6912 Creates a new document fragment, that can be used to hold parts of
6913 the document, e.g. when doing complex manipulations of the
6914 document tree.
6915*/
6916QDomDocumentFragment QDomDocument::createDocumentFragment()
6917{
6918 if (!impl)
6919 impl = new QDomDocumentPrivate();
6920 return QDomDocumentFragment(IMPL->createDocumentFragment());
6921}
6922
6923/*!
6924 Creates a text node for the string \a value that can be inserted
6925 into the document tree, e.g. using QDomNode::appendChild().
6926
6927 If \a value contains characters which cannot be stored as character
6928 data of an XML document (even in the form of character references), the
6929 behavior of this function is governed by QDomImplementation::InvalidDataPolicy.
6930
6931 \sa QDomNode::appendChild() QDomNode::insertBefore() QDomNode::insertAfter()
6932*/
6933QDomText QDomDocument::createTextNode(const QString& value)
6934{
6935 if (!impl)
6936 impl = new QDomDocumentPrivate();
6937 return QDomText(IMPL->createTextNode(value));
6938}
6939
6940/*!
6941 Creates a new comment for the string \a value that can be inserted
6942 into the document, e.g. using QDomNode::appendChild().
6943
6944 If \a value contains characters which cannot be stored in an XML comment,
6945 the behavior of this function is governed by QDomImplementation::InvalidDataPolicy.
6946
6947 \sa QDomNode::appendChild() QDomNode::insertBefore() QDomNode::insertAfter()
6948*/
6949QDomComment QDomDocument::createComment(const QString& value)
6950{
6951 if (!impl)
6952 impl = new QDomDocumentPrivate();
6953 return QDomComment(IMPL->createComment(value));
6954}
6955
6956/*!
6957 Creates a new CDATA section for the string \a value that can be
6958 inserted into the document, e.g. using QDomNode::appendChild().
6959
6960 If \a value contains characters which cannot be stored in a CDATA section,
6961 the behavior of this function is governed by
6962 QDomImplementation::InvalidDataPolicy.
6963
6964 \sa QDomNode::appendChild() QDomNode::insertBefore() QDomNode::insertAfter()
6965*/
6966QDomCDATASection QDomDocument::createCDATASection(const QString& value)
6967{
6968 if (!impl)
6969 impl = new QDomDocumentPrivate();
6970 return QDomCDATASection(IMPL->createCDATASection(value));
6971}
6972
6973/*!
6974 Creates a new processing instruction that can be inserted into the
6975 document, e.g. using QDomNode::appendChild(). This function sets
6976 the target for the processing instruction to \a target and the
6977 data to \a data.
6978
6979 If \a target is not a valid XML name, or data if contains characters which cannot
6980 appear in a processing instruction, the behavior of this function is governed by
6981 QDomImplementation::InvalidDataPolicy.
6982
6983 \sa QDomNode::appendChild() QDomNode::insertBefore() QDomNode::insertAfter()
6984*/
6985QDomProcessingInstruction QDomDocument::createProcessingInstruction(const QString& target,
6986 const QString& data)
6987{
6988 if (!impl)
6989 impl = new QDomDocumentPrivate();
6990 return QDomProcessingInstruction(IMPL->createProcessingInstruction(target, data));
6991}
6992
6993
6994/*!
6995 Creates a new attribute called \a name that can be inserted into
6996 an element, e.g. using QDomElement::setAttributeNode().
6997
6998 If \a name is not a valid XML name, the behavior of this function is governed by
6999 QDomImplementation::InvalidDataPolicy.
7000
7001 \sa createAttributeNS()
7002*/
7003QDomAttr QDomDocument::createAttribute(const QString& name)
7004{
7005 if (!impl)
7006 impl = new QDomDocumentPrivate();
7007 return QDomAttr(IMPL->createAttribute(name));
7008}
7009
7010/*!
7011 Creates a new entity reference called \a name that can be inserted
7012 into the document, e.g. using QDomNode::appendChild().
7013
7014 If \a name is not a valid XML name, the behavior of this function is governed by
7015 QDomImplementation::InvalidDataPolicy.
7016
7017 \sa QDomNode::appendChild() QDomNode::insertBefore() QDomNode::insertAfter()
7018*/
7019QDomEntityReference QDomDocument::createEntityReference(const QString& name)
7020{
7021 if (!impl)
7022 impl = new QDomDocumentPrivate();
7023 return QDomEntityReference(IMPL->createEntityReference(name));
7024}
7025
7026/*!
7027 Returns a QDomNodeList, that contains all the elements in the
7028 document with the name \a tagname. The order of the node list is
7029 the order they are encountered in a preorder traversal of the
7030 element tree.
7031
7032 \sa elementsByTagNameNS() QDomElement::elementsByTagName()
7033*/
7034QDomNodeList QDomDocument::elementsByTagName(const QString& tagname) const
7035{
7036 return QDomNodeList(new QDomNodeListPrivate(impl, tagname));
7037}
7038
7039/*!
7040 Imports the node \a importedNode from another document to this
7041 document. \a importedNode remains in the original document; this
7042 function creates a copy that can be used within this document.
7043
7044 This function returns the imported node that belongs to this
7045 document. The returned node has no parent. It is not possible to
7046 import QDomDocument and QDomDocumentType nodes. In those cases
7047 this function returns a \link QDomNode::isNull() null node\endlink.
7048
7049 If \a deep is true, this function imports not only the node \a
7050 importedNode but its whole subtree; if it is false, only the \a
7051 importedNode is imported. The argument \a deep has no effect on
7052 QDomAttr and QDomEntityReference nodes, since the descendants of
7053 QDomAttr nodes are always imported and those of
7054 QDomEntityReference nodes are never imported.
7055
7056 The behavior of this function is slightly different depending on
7057 the node types:
7058 \table
7059 \header \i Node Type \i Behavior
7060 \row \i QDomAttr
7061 \i The owner element is set to 0 and the specified flag is
7062 set to true in the generated attribute. The whole subtree
7063 of \a importedNode is always imported for attribute nodes:
7064 \a deep has no effect.
7065 \row \i QDomDocument
7066 \i Document nodes cannot be imported.
7067 \row \i QDomDocumentFragment
7068 \i If \a deep is true, this function imports the whole
7069 document fragment; otherwise it only generates an empty
7070 document fragment.
7071 \row \i QDomDocumentType
7072 \i Document type nodes cannot be imported.
7073 \row \i QDomElement
7074 \i Attributes for which QDomAttr::specified() is true are
7075 also imported, other attributes are not imported. If \a
7076 deep is true, this function also imports the subtree of \a
7077 importedNode; otherwise it imports only the element node
7078 (and some attributes, see above).
7079 \row \i QDomEntity
7080 \i Entity nodes can be imported, but at the moment there is
7081 no way to use them since the document type is read-only in
7082 DOM level 2.
7083 \row \i QDomEntityReference
7084 \i Descendants of entity reference nodes are never imported:
7085 \a deep has no effect.
7086 \row \i QDomNotation
7087 \i Notation nodes can be imported, but at the moment there is
7088 no way to use them since the document type is read-only in
7089 DOM level 2.
7090 \row \i QDomProcessingInstruction
7091 \i The target and value of the processing instruction is
7092 copied to the new node.
7093 \row \i QDomText
7094 \i The text is copied to the new node.
7095 \row \i QDomCDATASection
7096 \i The text is copied to the new node.
7097 \row \i QDomComment
7098 \i The text is copied to the new node.
7099 \endtable
7100
7101 \sa QDomElement::setAttribute() QDomNode::insertBefore()
7102 QDomNode::insertAfter() QDomNode::replaceChild() QDomNode::removeChild()
7103 QDomNode::appendChild()
7104*/
7105QDomNode QDomDocument::importNode(const QDomNode& importedNode, bool deep)
7106{
7107 if (!impl)
7108 impl = new QDomDocumentPrivate();
7109 return QDomNode(IMPL->importNode(importedNode.impl, deep));
7110}
7111
7112/*!
7113 Creates a new element with namespace support that can be inserted
7114 into the DOM tree. The name of the element is \a qName and the
7115 namespace URI is \a nsURI. This function also sets
7116 QDomNode::prefix() and QDomNode::localName() to appropriate values
7117 (depending on \a qName).
7118
7119 If \a qName is an empty string, returns a null element regardless of
7120 whether the invalid data policy is set.
7121
7122 \sa createElement()
7123*/
7124QDomElement QDomDocument::createElementNS(const QString& nsURI, const QString& qName)
7125{
7126 if (!impl)
7127 impl = new QDomDocumentPrivate();
7128 return QDomElement(IMPL->createElementNS(nsURI, qName));
7129}
7130
7131/*!
7132 Creates a new attribute with namespace support that can be
7133 inserted into an element. The name of the attribute is \a qName
7134 and the namespace URI is \a nsURI. This function also sets
7135 QDomNode::prefix() and QDomNode::localName() to appropriate values
7136 (depending on \a qName).
7137
7138 If \a qName is not a valid XML name, the behavior of this function is governed by
7139 QDomImplementation::InvalidDataPolicy.
7140
7141 \sa createAttribute()
7142*/
7143QDomAttr QDomDocument::createAttributeNS(const QString& nsURI, const QString& qName)
7144{
7145 if (!impl)
7146 impl = new QDomDocumentPrivate();
7147 return QDomAttr(IMPL->createAttributeNS(nsURI, qName));
7148}
7149
7150/*!
7151 Returns a QDomNodeList that contains all the elements in the
7152 document with the local name \a localName and a namespace URI of
7153 \a nsURI. The order of the node list is the order they are
7154 encountered in a preorder traversal of the element tree.
7155
7156 \sa elementsByTagName() QDomElement::elementsByTagNameNS()
7157*/
7158QDomNodeList QDomDocument::elementsByTagNameNS(const QString& nsURI, const QString& localName)
7159{
7160 return QDomNodeList(new QDomNodeListPrivate(impl, nsURI, localName));
7161}
7162
7163/*!
7164 Returns the element whose ID is equal to \a elementId. If no
7165 element with the ID was found, this function returns a \link
7166 QDomNode::isNull() null element\endlink.
7167
7168 Since the QDomClasses do not know which attributes are element
7169 IDs, this function returns always a \link QDomNode::isNull() null
7170 element\endlink. This may change in a future version.
7171*/
7172QDomElement QDomDocument::elementById(const QString& /*elementId*/)
7173{
7174 qWarning("elementById() is not implemented and will always return a null node.");
7175 return QDomElement();
7176}
7177
7178/*!
7179 \fn QDomNode::NodeType QDomDocument::nodeType() const
7180
7181 Returns \c DocumentNode.
7182*/
7183
7184#undef IMPL
7185
7186/**************************************************************
7187 *
7188 * Node casting functions
7189 *
7190 **************************************************************/
7191
7192/*!
7193 Converts a QDomNode into a QDomAttr. If the node is not an
7194 attribute, the returned object will be \link QDomNode::isNull()
7195 null\endlink.
7196
7197 \sa isAttr()
7198*/
7199QDomAttr QDomNode::toAttr() const
7200{
7201 if (impl && impl->isAttr())
7202 return QDomAttr(((QDomAttrPrivate*)impl));
7203 return QDomAttr();
7204}
7205
7206/*!
7207 Converts a QDomNode into a QDomCDATASection. If the node is not a
7208 CDATA section, the returned object will be \link
7209 QDomNode::isNull() null\endlink.
7210
7211 \sa isCDATASection()
7212*/
7213QDomCDATASection QDomNode::toCDATASection() const
7214{
7215 if (impl && impl->isCDATASection())
7216 return QDomCDATASection(((QDomCDATASectionPrivate*)impl));
7217 return QDomCDATASection();
7218}
7219
7220/*!
7221 Converts a QDomNode into a QDomDocumentFragment. If the node is
7222 not a document fragment the returned object will be \link
7223 QDomNode::isNull() null\endlink.
7224
7225 \sa isDocumentFragment()
7226*/
7227QDomDocumentFragment QDomNode::toDocumentFragment() const
7228{
7229 if (impl && impl->isDocumentFragment())
7230 return QDomDocumentFragment(((QDomDocumentFragmentPrivate*)impl));
7231 return QDomDocumentFragment();
7232}
7233
7234/*!
7235 Converts a QDomNode into a QDomDocument. If the node is not a
7236 document the returned object will be \link QDomNode::isNull()
7237 null\endlink.
7238
7239 \sa isDocument()
7240*/
7241QDomDocument QDomNode::toDocument() const
7242{
7243 if (impl && impl->isDocument())
7244 return QDomDocument(((QDomDocumentPrivate*)impl));
7245 return QDomDocument();
7246}
7247
7248/*!
7249 Converts a QDomNode into a QDomDocumentType. If the node is not a
7250 document type the returned object will be \link QDomNode::isNull()
7251 null\endlink.
7252
7253 \sa isDocumentType()
7254*/
7255QDomDocumentType QDomNode::toDocumentType() const
7256{
7257 if (impl && impl->isDocumentType())
7258 return QDomDocumentType(((QDomDocumentTypePrivate*)impl));
7259 return QDomDocumentType();
7260}
7261
7262/*!
7263 Converts a QDomNode into a QDomElement. If the node is not an
7264 element the returned object will be \link QDomNode::isNull()
7265 null\endlink.
7266
7267 \sa isElement()
7268*/
7269QDomElement QDomNode::toElement() const
7270{
7271 if (impl && impl->isElement())
7272 return QDomElement(((QDomElementPrivate*)impl));
7273 return QDomElement();
7274}
7275
7276/*!
7277 Converts a QDomNode into a QDomEntityReference. If the node is not
7278 an entity reference, the returned object will be \link
7279 QDomNode::isNull() null\endlink.
7280
7281 \sa isEntityReference()
7282*/
7283QDomEntityReference QDomNode::toEntityReference() const
7284{
7285 if (impl && impl->isEntityReference())
7286 return QDomEntityReference(((QDomEntityReferencePrivate*)impl));
7287 return QDomEntityReference();
7288}
7289
7290/*!
7291 Converts a QDomNode into a QDomText. If the node is not a text,
7292 the returned object will be \link QDomNode::isNull() null\endlink.
7293
7294 \sa isText()
7295*/
7296QDomText QDomNode::toText() const
7297{
7298 if (impl && impl->isText())
7299 return QDomText(((QDomTextPrivate*)impl));
7300 return QDomText();
7301}
7302
7303/*!
7304 Converts a QDomNode into a QDomEntity. If the node is not an
7305 entity the returned object will be \link QDomNode::isNull()
7306 null\endlink.
7307
7308 \sa isEntity()
7309*/
7310QDomEntity QDomNode::toEntity() const
7311{
7312 if (impl && impl->isEntity())
7313 return QDomEntity(((QDomEntityPrivate*)impl));
7314 return QDomEntity();
7315}
7316
7317/*!
7318 Converts a QDomNode into a QDomNotation. If the node is not a
7319 notation the returned object will be \link QDomNode::isNull()
7320 null\endlink.
7321
7322 \sa isNotation()
7323*/
7324QDomNotation QDomNode::toNotation() const
7325{
7326 if (impl && impl->isNotation())
7327 return QDomNotation(((QDomNotationPrivate*)impl));
7328 return QDomNotation();
7329}
7330
7331/*!
7332 Converts a QDomNode into a QDomProcessingInstruction. If the node
7333 is not a processing instruction the returned object will be \link
7334 QDomNode::isNull() null\endlink.
7335
7336 \sa isProcessingInstruction()
7337*/
7338QDomProcessingInstruction QDomNode::toProcessingInstruction() const
7339{
7340 if (impl && impl->isProcessingInstruction())
7341 return QDomProcessingInstruction(((QDomProcessingInstructionPrivate*)impl));
7342 return QDomProcessingInstruction();
7343}
7344
7345/*!
7346 Converts a QDomNode into a QDomCharacterData. If the node is not a
7347 character data node the returned object will be \link
7348 QDomNode::isNull() null\endlink.
7349
7350 \sa isCharacterData()
7351*/
7352QDomCharacterData QDomNode::toCharacterData() const
7353{
7354 if (impl && impl->isCharacterData())
7355 return QDomCharacterData(((QDomCharacterDataPrivate*)impl));
7356 return QDomCharacterData();
7357}
7358
7359/*!
7360 Converts a QDomNode into a QDomComment. If the node is not a
7361 comment the returned object will be \link QDomNode::isNull()
7362 null\endlink.
7363
7364 \sa isComment()
7365*/
7366QDomComment QDomNode::toComment() const
7367{
7368 if (impl && impl->isComment())
7369 return QDomComment(((QDomCommentPrivate*)impl));
7370 return QDomComment();
7371}
7372
7373/**************************************************************
7374 *
7375 * QDomHandler
7376 *
7377 **************************************************************/
7378
7379QDomHandler::QDomHandler(QDomDocumentPrivate* adoc, bool namespaceProcessing)
7380 : errorLine(0), errorColumn(0), doc(adoc), node(adoc), cdata(false),
7381 nsProcessing(namespaceProcessing), locator(0)
7382{
7383}
7384
7385QDomHandler::~QDomHandler()
7386{
7387}
7388
7389bool QDomHandler::endDocument()
7390{
7391 // ### is this really necessary? (rms)
7392 if (node != doc)
7393 return false;
7394 return true;
7395}
7396
7397bool QDomHandler::startDTD(const QString& name, const QString& publicId, const QString& systemId)
7398{
7399 doc->doctype()->name = name;
7400 doc->doctype()->publicId = publicId;
7401 doc->doctype()->systemId = systemId;
7402 return true;
7403}
7404
7405bool QDomHandler::startElement(const QString& nsURI, const QString&, const QString& qName, const QXmlAttributes& atts)
7406{
7407 // tag name
7408 QDomNodePrivate* n;
7409 if (nsProcessing) {
7410 n = doc->createElementNS(nsURI, qName);
7411 } else {
7412 n = doc->createElement(qName);
7413 }
7414
7415 if (n)
7416 n->setLocation(locator->lineNumber(), locator->columnNumber());
7417
7418 node->appendChild(n);
7419 node = n;
7420
7421 // attributes
7422 for (int i=0; i<atts.length(); i++)
7423 {
7424 if (nsProcessing) {
7425 ((QDomElementPrivate*)node)->setAttributeNS(atts.uri(i), atts.qName(i), atts.value(i));
7426 } else {
7427 ((QDomElementPrivate*)node)->setAttribute(atts.qName(i), atts.value(i));
7428 }
7429 }
7430
7431 return true;
7432}
7433
7434bool QDomHandler::endElement(const QString&, const QString&, const QString&)
7435{
7436 if (!node || node == doc)
7437 return false;
7438 node = node->parent();
7439
7440 return true;
7441}
7442
7443bool QDomHandler::characters(const QString& ch)
7444{
7445 // No text as child of some document
7446 if (node == doc)
7447 return false;
7448
7449 QScopedPointer<QDomNodePrivate> n;
7450 if (cdata) {
7451 n.reset(doc->createCDATASection(ch));
7452 } else if (!entityName.isEmpty()) {
7453 QScopedPointer<QDomEntityPrivate> e(new QDomEntityPrivate(doc, 0, entityName,
7454 QString(), QString(), QString()));
7455 e->value = ch;
7456 doc->doctype()->appendChild(e.data());
7457 e.take();
7458 n.reset(doc->createEntityReference(entityName));
7459 } else {
7460 n.reset(doc->createTextNode(ch));
7461 }
7462 n->setLocation(locator->lineNumber(), locator->columnNumber());
7463 node->appendChild(n.data());
7464 n.take();
7465
7466 return true;
7467}
7468
7469bool QDomHandler::processingInstruction(const QString& target, const QString& data)
7470{
7471 QDomNodePrivate *n;
7472 n = doc->createProcessingInstruction(target, data);
7473 if (n) {
7474 n->setLocation(locator->lineNumber(), locator->columnNumber());
7475 node->appendChild(n);
7476 return true;
7477 }
7478 else
7479 return false;
7480}
7481
7482extern bool qt_xml_skipped_entity_in_content;
7483bool QDomHandler::skippedEntity(const QString& name)
7484{
7485 // we can only handle inserting entity references into content
7486 if (!qt_xml_skipped_entity_in_content)
7487 return true;
7488
7489 QDomNodePrivate *n = doc->createEntityReference(name);
7490 n->setLocation(locator->lineNumber(), locator->columnNumber());
7491 node->appendChild(n);
7492 return true;
7493}
7494
7495bool QDomHandler::fatalError(const QXmlParseException& exception)
7496{
7497 errorMsg = exception.message();
7498 errorLine = exception.lineNumber();
7499 errorColumn = exception.columnNumber();
7500 return QXmlDefaultHandler::fatalError(exception);
7501}
7502
7503bool QDomHandler::startCDATA()
7504{
7505 cdata = true;
7506 return true;
7507}
7508
7509bool QDomHandler::endCDATA()
7510{
7511 cdata = false;
7512 return true;
7513}
7514
7515bool QDomHandler::startEntity(const QString &name)
7516{
7517 entityName = name;
7518 return true;
7519}
7520
7521bool QDomHandler::endEntity(const QString &)
7522{
7523 entityName.clear();
7524 return true;
7525}
7526
7527bool QDomHandler::comment(const QString& ch)
7528{
7529 QDomNodePrivate *n;
7530 n = doc->createComment(ch);
7531 n->setLocation(locator->lineNumber(), locator->columnNumber());
7532 node->appendChild(n);
7533 return true;
7534}
7535
7536bool QDomHandler::unparsedEntityDecl(const QString &name, const QString &publicId, const QString &systemId, const QString &notationName)
7537{
7538 QDomEntityPrivate* e = new QDomEntityPrivate(doc, 0, name,
7539 publicId, systemId, notationName);
7540 doc->doctype()->appendChild(e);
7541 return true;
7542}
7543
7544bool QDomHandler::externalEntityDecl(const QString &name, const QString &publicId, const QString &systemId)
7545{
7546 return unparsedEntityDecl(name, publicId, systemId, QString());
7547}
7548
7549bool QDomHandler::notationDecl(const QString & name, const QString & publicId, const QString & systemId)
7550{
7551 QDomNotationPrivate* n = new QDomNotationPrivate(doc, 0, name, publicId, systemId);
7552 doc->doctype()->appendChild(n);
7553 return true;
7554}
7555
7556void QDomHandler::setDocumentLocator(QXmlLocator *locator)
7557{
7558 this->locator = locator;
7559}
7560
7561QT_END_NAMESPACE
7562
7563#endif // QT_NO_DOM
Note: See TracBrowser for help on using the repository browser.