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

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

trunk: Merged in qt 4.6.1 sources.

File size: 213.0 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 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 Calling this function on a null node(created, for example, with the
2600 default constructor) does nothing.
2601
2602 The DOM specification disallow inserting attribute nodes, but due
2603 to historical reasons QDom accept them nevertheless.
2604
2605 \sa insertBefore() insertAfter() replaceChild() removeChild()
2606*/
2607QDomNode QDomNode::appendChild(const QDomNode& newChild)
2608{
2609 if (!impl) {
2610 qWarning("Calling appendChild() on a null node does nothing.");
2611 return QDomNode();
2612 }
2613 return QDomNode(IMPL->appendChild(newChild.impl));
2614}
2615
2616/*!
2617 Returns true if the node has one or more children; otherwise
2618 returns false.
2619*/
2620bool QDomNode::hasChildNodes() const
2621{
2622 if (!impl)
2623 return false;
2624 return IMPL->first != 0;
2625}
2626
2627/*!
2628 Returns true if this node is null (i.e. if it has no type or
2629 contents); otherwise returns false.
2630*/
2631bool QDomNode::isNull() const
2632{
2633 return (impl == 0);
2634}
2635
2636/*!
2637 Converts the node into a null node; if it was not a null node
2638 before, its type and contents are deleted.
2639
2640 \sa isNull()
2641*/
2642void QDomNode::clear()
2643{
2644 if (impl && !impl->ref.deref())
2645 delete impl;
2646 impl = 0;
2647}
2648
2649/*!
2650 Returns the first direct child node for which nodeName() equals \a
2651 name.
2652
2653 If no such direct child exists, a \link isNull() null node\endlink
2654 is returned.
2655
2656 \sa nodeName()
2657*/
2658QDomNode QDomNode::namedItem(const QString& name) const
2659{
2660 if (!impl)
2661 return QDomNode();
2662 return QDomNode(impl->namedItem(name));
2663}
2664
2665/*!
2666 Writes the XML representation of the node and all its children to
2667 the stream \a str. This function uses \a indent as the amount of
2668 space to indent the node.
2669
2670 If this node is a document node, the encoding of text stream \a str's encoding is
2671 set by treating a processing instruction by name "xml" as an XML declaration, if such a one exists,
2672 and otherwise defaults to UTF-8. XML declarations are not processing instructions, but this
2673 behavior exists for historical reasons. If this node is not a document node,
2674 the text stream's encoding is used.
2675
2676 If the document contains invalid XML characters or characters that cannot be
2677 encoded in the given encoding, the result and behavior is undefined.
2678
2679*/
2680void QDomNode::save(QTextStream& str, int indent) const
2681{
2682 save(str, indent, QDomNode::EncodingFromDocument);
2683}
2684
2685/*!
2686 If \a encodingPolicy is QDomNode::EncodingFromDocument, this function behaves as save(QTextStream &str, int indent).
2687
2688 If \a encodingPolicy is EncodingFromTextStream and this node is a document node, this
2689 function behaves as save(QTextStream &str, int indent) with the exception that the encoding
2690 specified in the text stream \a str is used.
2691
2692 If the document contains invalid XML characters or characters that cannot be
2693 encoded in the given encoding, the result and behavior is undefined.
2694
2695 \since 4.2
2696 */
2697void QDomNode::save(QTextStream& str, int indent, EncodingPolicy encodingPolicy) const
2698{
2699 if (!impl)
2700 return;
2701
2702 if(isDocument())
2703 static_cast<const QDomDocumentPrivate *>(impl)->saveDocument(str, indent, encodingPolicy);
2704 else
2705 IMPL->save(str, 1, indent);
2706}
2707
2708/*!
2709 \relates QDomNode
2710
2711 Writes the XML representation of the node \a node and all its
2712 children to the stream \a str.
2713*/
2714QTextStream& operator<<(QTextStream& str, const QDomNode& node)
2715{
2716 node.save(str, 1);
2717
2718 return str;
2719}
2720
2721/*!
2722 Returns true if the node is an attribute; otherwise returns false.
2723
2724 If this function returns true, it does not imply that this object
2725 is a QDomAttribute; you can get the QDomAttribute with
2726 toAttribute().
2727
2728 \sa toAttr()
2729*/
2730bool QDomNode::isAttr() const
2731{
2732 if(impl)
2733 return impl->isAttr();
2734 return false;
2735}
2736
2737/*!
2738 Returns true if the node is a CDATA section; otherwise returns
2739 false.
2740
2741 If this function returns true, it does not imply that this object
2742 is a QDomCDATASection; you can get the QDomCDATASection with
2743 toCDATASection().
2744
2745 \sa toCDATASection()
2746*/
2747bool QDomNode::isCDATASection() const
2748{
2749 if(impl)
2750 return impl->isCDATASection();
2751 return false;
2752}
2753
2754/*!
2755 Returns true if the node is a document fragment; otherwise returns
2756 false.
2757
2758 If this function returns true, it does not imply that this object
2759 is a QDomDocumentFragment; you can get the QDomDocumentFragment
2760 with toDocumentFragment().
2761
2762 \sa toDocumentFragment()
2763*/
2764bool QDomNode::isDocumentFragment() const
2765{
2766 if(impl)
2767 return impl->isDocumentFragment();
2768 return false;
2769}
2770
2771/*!
2772 Returns true if the node is a document; otherwise returns false.
2773
2774 If this function returns true, it does not imply that this object
2775 is a QDomDocument; you can get the QDomDocument with toDocument().
2776
2777 \sa toDocument()
2778*/
2779bool QDomNode::isDocument() const
2780{
2781 if(impl)
2782 return impl->isDocument();
2783 return false;
2784}
2785
2786/*!
2787 Returns true if the node is a document type; otherwise returns
2788 false.
2789
2790 If this function returns true, it does not imply that this object
2791 is a QDomDocumentType; you can get the QDomDocumentType with
2792 toDocumentType().
2793
2794 \sa toDocumentType()
2795*/
2796bool QDomNode::isDocumentType() const
2797{
2798 if(impl)
2799 return impl->isDocumentType();
2800 return false;
2801}
2802
2803/*!
2804 Returns true if the node is an element; otherwise returns false.
2805
2806 If this function returns true, it does not imply that this object
2807 is a QDomElement; you can get the QDomElement with toElement().
2808
2809 \sa toElement()
2810*/
2811bool QDomNode::isElement() const
2812{
2813 if(impl)
2814 return impl->isElement();
2815 return false;
2816}
2817
2818/*!
2819 Returns true if the node is an entity reference; otherwise returns
2820 false.
2821
2822 If this function returns true, it does not imply that this object
2823 is a QDomEntityReference; you can get the QDomEntityReference with
2824 toEntityReference().
2825
2826 \sa toEntityReference()
2827*/
2828bool QDomNode::isEntityReference() const
2829{
2830 if(impl)
2831 return impl->isEntityReference();
2832 return false;
2833}
2834
2835/*!
2836 Returns true if the node is a text node; otherwise returns false.
2837
2838 If this function returns true, it does not imply that this object
2839 is a QDomText; you can get the QDomText with toText().
2840
2841 \sa toText()
2842*/
2843bool QDomNode::isText() const
2844{
2845 if(impl)
2846 return impl->isText();
2847 return false;
2848}
2849
2850/*!
2851 Returns true if the node is an entity; otherwise returns false.
2852
2853 If this function returns true, it does not imply that this object
2854 is a QDomEntity; you can get the QDomEntity with toEntity().
2855
2856 \sa toEntity()
2857*/
2858bool QDomNode::isEntity() const
2859{
2860 if(impl)
2861 return impl->isEntity();
2862 return false;
2863}
2864
2865/*!
2866 Returns true if the node is a notation; otherwise returns false.
2867
2868 If this function returns true, it does not imply that this object
2869 is a QDomNotation; you can get the QDomNotation with toNotation().
2870
2871 \sa toNotation()
2872*/
2873bool QDomNode::isNotation() const
2874{
2875 if(impl)
2876 return impl->isNotation();
2877 return false;
2878}
2879
2880/*!
2881 Returns true if the node is a processing instruction; otherwise
2882 returns false.
2883
2884 If this function returns true, it does not imply that this object
2885 is a QDomProcessingInstruction; you can get the
2886 QProcessingInstruction with toProcessingInstruction().
2887
2888 \sa toProcessingInstruction()
2889*/
2890bool QDomNode::isProcessingInstruction() const
2891{
2892 if(impl)
2893 return impl->isProcessingInstruction();
2894 return false;
2895}
2896
2897/*!
2898 Returns true if the node is a character data node; otherwise
2899 returns false.
2900
2901 If this function returns true, it does not imply that this object
2902 is a QDomCharacterData; you can get the QDomCharacterData with
2903 toCharacterData().
2904
2905 \sa toCharacterData()
2906*/
2907bool QDomNode::isCharacterData() const
2908{
2909 if (impl)
2910 return impl->isCharacterData();
2911 return false;
2912}
2913
2914/*!
2915 Returns true if the node is a comment; otherwise returns false.
2916
2917 If this function returns true, it does not imply that this object
2918 is a QDomComment; you can get the QDomComment with toComment().
2919
2920 \sa toComment()
2921*/
2922bool QDomNode::isComment() const
2923{
2924 if (impl)
2925 return impl->isComment();
2926 return false;
2927}
2928
2929#undef IMPL
2930
2931/*!
2932 Returns the first child element with tag name \a tagName if tagName is non-empty;
2933 otherwise returns the first child element. Returns a null element if no
2934 such child exists.
2935
2936 \sa lastChildElement() previousSiblingElement() nextSiblingElement()
2937*/
2938
2939QDomElement QDomNode::firstChildElement(const QString &tagName) const
2940{
2941 for (QDomNode child = firstChild(); !child.isNull(); child = child.nextSibling()) {
2942 if (child.isElement()) {
2943 QDomElement elt = child.toElement();
2944 if (tagName.isEmpty() || elt.tagName() == tagName)
2945 return elt;
2946 }
2947 }
2948 return QDomElement();
2949}
2950
2951/*!
2952 Returns the last child element with tag name \a tagName if tagName is non-empty;
2953 otherwise returns the first child element. Returns a null element if no
2954 such child exists.
2955
2956 \sa firstChildElement() previousSiblingElement() nextSiblingElement()
2957*/
2958
2959QDomElement QDomNode::lastChildElement(const QString &tagName) const
2960{
2961 for (QDomNode child = lastChild(); !child.isNull(); child = child.previousSibling()) {
2962 if (child.isElement()) {
2963 QDomElement elt = child.toElement();
2964 if (tagName.isEmpty() || elt.tagName() == tagName)
2965 return elt;
2966 }
2967 }
2968 return QDomElement();
2969}
2970
2971/*!
2972 Returns the next sibilng element with tag name \a tagName if \a tagName
2973 is non-empty; otherwise returns any next sibling element.
2974 Returns a null element if no such sibling exists.
2975
2976 \sa firstChildElement() previousSiblingElement() lastChildElement()
2977*/
2978
2979QDomElement QDomNode::nextSiblingElement(const QString &tagName) const
2980{
2981 for (QDomNode sib = nextSibling(); !sib.isNull(); sib = sib.nextSibling()) {
2982 if (sib.isElement()) {
2983 QDomElement elt = sib.toElement();
2984 if (tagName.isEmpty() || elt.tagName() == tagName)
2985 return elt;
2986 }
2987 }
2988 return QDomElement();
2989}
2990
2991/*!
2992 Returns the previous sibilng element with tag name \a tagName if \a tagName
2993 is non-empty; otherwise returns any previous sibling element.
2994 Returns a null element if no such sibling exists.
2995
2996 \sa firstChildElement(), nextSiblingElement(), lastChildElement()
2997*/
2998
2999QDomElement QDomNode::previousSiblingElement(const QString &tagName) const
3000{
3001 for (QDomNode sib = previousSibling(); !sib.isNull(); sib = sib.previousSibling()) {
3002 if (sib.isElement()) {
3003 QDomElement elt = sib.toElement();
3004 if (tagName.isEmpty() || elt.tagName() == tagName)
3005 return elt;
3006 }
3007 }
3008 return QDomElement();
3009}
3010
3011/*!
3012 \since 4.1
3013
3014 For nodes created by QDomDocument::setContent(), this function
3015 returns the line number in the XML document where the node was parsed.
3016 Otherwise, -1 is returned.
3017
3018 \sa columnNumber(), QDomDocument::setContent()
3019*/
3020int QDomNode::lineNumber() const
3021{
3022 return impl ? impl->lineNumber : -1;
3023}
3024
3025/*!
3026 \since 4.1
3027
3028 For nodes created by QDomDocument::setContent(), this function
3029 returns the column number in the XML document where the node was parsed.
3030 Otherwise, -1 is returned.
3031
3032 \sa lineNumber(), QDomDocument::setContent()
3033*/
3034int QDomNode::columnNumber() const
3035{
3036 return impl ? impl->columnNumber : -1;
3037}
3038
3039
3040/**************************************************************
3041 *
3042 * QDomNamedNodeMapPrivate
3043 *
3044 **************************************************************/
3045
3046QDomNamedNodeMapPrivate::QDomNamedNodeMapPrivate(QDomNodePrivate* n)
3047{
3048 ref = 1;
3049 readonly = false;
3050 parent = n;
3051 appendToParent = false;
3052}
3053
3054QDomNamedNodeMapPrivate::~QDomNamedNodeMapPrivate()
3055{
3056 clearMap();
3057}
3058
3059QDomNamedNodeMapPrivate* QDomNamedNodeMapPrivate::clone(QDomNodePrivate* p)
3060{
3061 QScopedPointer<QDomNamedNodeMapPrivate> m(new QDomNamedNodeMapPrivate(p));
3062 m->readonly = readonly;
3063 m->appendToParent = appendToParent;
3064
3065 QHash<QString, QDomNodePrivate*>::const_iterator it = map.constBegin();
3066 for (; it != map.constEnd(); ++it) {
3067 QDomNodePrivate *new_node = (*it)->cloneNode();
3068 new_node->setParent(p);
3069 m->setNamedItem(new_node);
3070 }
3071
3072 // we are no longer interested in ownership
3073 m->ref.deref();
3074 return m.take();
3075}
3076
3077void QDomNamedNodeMapPrivate::clearMap()
3078{
3079 // Dereference all of our children if we took references
3080 if (!appendToParent) {
3081 QHash<QString, QDomNodePrivate *>::const_iterator it = map.constBegin();
3082 for (; it != map.constEnd(); ++it)
3083 if (!(*it)->ref.deref())
3084 delete *it;
3085 }
3086 map.clear();
3087}
3088
3089QDomNodePrivate* QDomNamedNodeMapPrivate::namedItem(const QString& name) const
3090{
3091 QDomNodePrivate* p = map[name];
3092 return p;
3093}
3094
3095QDomNodePrivate* QDomNamedNodeMapPrivate::namedItemNS(const QString& nsURI, const QString& localName) const
3096{
3097 QHash<QString, QDomNodePrivate *>::const_iterator it = map.constBegin();
3098 QDomNodePrivate *n;
3099 for (; it != map.constEnd(); ++it) {
3100 n = *it;
3101 if (!n->prefix.isNull()) {
3102 // node has a namespace
3103 if (n->namespaceURI == nsURI && n->name == localName)
3104 return n;
3105 }
3106 }
3107 return 0;
3108}
3109
3110QDomNodePrivate* QDomNamedNodeMapPrivate::setNamedItem(QDomNodePrivate* arg)
3111{
3112 if (readonly || !arg)
3113 return 0;
3114
3115 if (appendToParent)
3116 return parent->appendChild(arg);
3117
3118 QDomNodePrivate *n = map.value(arg->nodeName());
3119 // We take a reference
3120 arg->ref.ref();
3121 map.insertMulti(arg->nodeName(), arg);
3122 return n;
3123}
3124
3125QDomNodePrivate* QDomNamedNodeMapPrivate::setNamedItemNS(QDomNodePrivate* arg)
3126{
3127 if (readonly || !arg)
3128 return 0;
3129
3130 if (appendToParent)
3131 return parent->appendChild(arg);
3132
3133 if (!arg->prefix.isNull()) {
3134 // node has a namespace
3135 QDomNodePrivate *n = namedItemNS(arg->namespaceURI, arg->name);
3136 // We take a reference
3137 arg->ref.ref();
3138 map.insertMulti(arg->nodeName(), arg);
3139 return n;
3140 } else {
3141 // ### check the following code if it is ok
3142 return setNamedItem(arg);
3143 }
3144}
3145
3146QDomNodePrivate* QDomNamedNodeMapPrivate::removeNamedItem(const QString& name)
3147{
3148 if (readonly)
3149 return 0;
3150
3151 QDomNodePrivate* p = namedItem(name);
3152 if (p == 0)
3153 return 0;
3154 if (appendToParent)
3155 return parent->removeChild(p);
3156
3157 map.remove(p->nodeName());
3158 // We took a reference, so we have to free one here
3159 p->ref.deref();
3160 return p;
3161}
3162
3163QDomNodePrivate* QDomNamedNodeMapPrivate::item(int index) const
3164{
3165 if ((uint)index >= length())
3166 return 0;
3167 return *(map.constBegin() + index);
3168}
3169
3170// ### Qt 5: convert all length/size() functions in QDom to use int instead of uint.
3171uint QDomNamedNodeMapPrivate::length() const
3172{
3173 return map.count();
3174}
3175
3176bool QDomNamedNodeMapPrivate::contains(const QString& name) const
3177{
3178 return map.value(name) != 0;
3179}
3180
3181bool QDomNamedNodeMapPrivate::containsNS(const QString& nsURI, const QString & localName) const
3182{
3183 return namedItemNS(nsURI, localName) != 0;
3184}
3185
3186/**************************************************************
3187 *
3188 * QDomNamedNodeMap
3189 *
3190 **************************************************************/
3191
3192#define IMPL ((QDomNamedNodeMapPrivate*)impl)
3193
3194/*!
3195 \class QDomNamedNodeMap
3196 \reentrant
3197 \brief The QDomNamedNodeMap class contains a collection of nodes
3198 that can be accessed by name.
3199
3200 \inmodule QtXml
3201 \ingroup xml-tools
3202
3203 Note that QDomNamedNodeMap does not inherit from QDomNodeList.
3204 QDomNamedNodeMaps do not provide any specific node ordering.
3205 Although nodes in a QDomNamedNodeMap may be accessed by an ordinal
3206 index, this is simply to allow a convenient enumeration of the
3207 contents of a QDomNamedNodeMap, and does not imply that the DOM
3208 specifies an ordering of the nodes.
3209
3210 The QDomNamedNodeMap is used in three places:
3211 \list 1
3212 \i QDomDocumentType::entities() returns a map of all entities
3213 described in the DTD.
3214 \i QDomDocumentType::notations() returns a map of all notations
3215 described in the DTD.
3216 \i QDomNode::attributes() returns a map of all attributes of an
3217 element.
3218 \endlist
3219
3220 Items in the map are identified by the name which QDomNode::name()
3221 returns. Nodes are retrieved using namedItem(), namedItemNS() or
3222 item(). New nodes are inserted with setNamedItem() or
3223 setNamedItemNS() and removed with removeNamedItem() or
3224 removeNamedItemNS(). Use contains() to see if an item with the
3225 given name is in the named node map. The number of items is
3226 returned by length().
3227
3228 Terminology: in this class we use "item" and "node"
3229 interchangeably.
3230*/
3231
3232/*!
3233 Constructs an empty named node map.
3234*/
3235QDomNamedNodeMap::QDomNamedNodeMap()
3236{
3237 impl = 0;
3238}
3239
3240/*!
3241 Constructs a copy of \a n.
3242*/
3243QDomNamedNodeMap::QDomNamedNodeMap(const QDomNamedNodeMap &n)
3244{
3245 impl = n.impl;
3246 if (impl)
3247 impl->ref.ref();
3248}
3249
3250QDomNamedNodeMap::QDomNamedNodeMap(QDomNamedNodeMapPrivate *n)
3251{
3252 impl = n;
3253 if (impl)
3254 impl->ref.ref();
3255}
3256
3257/*!
3258 Assigns \a n to this named node map.
3259*/
3260QDomNamedNodeMap& QDomNamedNodeMap::operator=(const QDomNamedNodeMap &n)
3261{
3262 if (n.impl)
3263 n.impl->ref.ref();
3264 if (impl && !impl->ref.deref())
3265 delete impl;
3266 impl = n.impl;
3267 return *this;
3268}
3269
3270/*!
3271 Returns true if \a n and this named node map are equal; otherwise
3272 returns false.
3273*/
3274bool QDomNamedNodeMap::operator== (const QDomNamedNodeMap& n) const
3275{
3276 return (impl == n.impl);
3277}
3278
3279/*!
3280 Returns true if \a n and this named node map are not equal;
3281 otherwise returns false.
3282*/
3283bool QDomNamedNodeMap::operator!= (const QDomNamedNodeMap& n) const
3284{
3285 return (impl != n.impl);
3286}
3287
3288/*!
3289 Destroys the object and frees its resources.
3290*/
3291QDomNamedNodeMap::~QDomNamedNodeMap()
3292{
3293 if (impl && !impl->ref.deref())
3294 delete impl;
3295}
3296
3297/*!
3298 Returns the node called \a name.
3299
3300 If the named node map does not contain such a node, a \link
3301 QDomNode::isNull() null node\endlink is returned. A node's name is
3302 the name returned by QDomNode::nodeName().
3303
3304 \sa setNamedItem() namedItemNS()
3305*/
3306QDomNode QDomNamedNodeMap::namedItem(const QString& name) const
3307{
3308 if (!impl)
3309 return QDomNode();
3310 return QDomNode(IMPL->namedItem(name));
3311}
3312
3313/*!
3314 Inserts the node \a newNode into the named node map. The name used
3315 by the map is the node name of \a newNode as returned by
3316 QDomNode::nodeName().
3317
3318 If the new node replaces an existing node, i.e. the map contains a
3319 node with the same name, the replaced node is returned.
3320
3321 \sa namedItem() removeNamedItem() setNamedItemNS()
3322*/
3323QDomNode QDomNamedNodeMap::setNamedItem(const QDomNode& newNode)
3324{
3325 if (!impl)
3326 return QDomNode();
3327 return QDomNode(IMPL->setNamedItem((QDomNodePrivate*)newNode.impl));
3328}
3329
3330/*!
3331 Removes the node called \a name from the map.
3332
3333 The function returns the removed node or a \link
3334 QDomNode::isNull() null node\endlink if the map did not contain a
3335 node called \a name.
3336
3337 \sa setNamedItem() namedItem() removeNamedItemNS()
3338*/
3339QDomNode QDomNamedNodeMap::removeNamedItem(const QString& name)
3340{
3341 if (!impl)
3342 return QDomNode();
3343 return QDomNode(IMPL->removeNamedItem(name));
3344}
3345
3346/*!
3347 Retrieves the node at position \a index.
3348
3349 This can be used to iterate over the map. Note that the nodes in
3350 the map are ordered arbitrarily.
3351
3352 \sa length()
3353*/
3354QDomNode QDomNamedNodeMap::item(int index) const
3355{
3356 if (!impl)
3357 return QDomNode();
3358 return QDomNode(IMPL->item(index));
3359}
3360
3361/*!
3362 Returns the node associated with the local name \a localName and
3363 the namespace URI \a nsURI.
3364
3365 If the map does not contain such a node, a \link
3366 QDomNode::isNull() null node\endlink is returned.
3367
3368 \sa setNamedItemNS() namedItem()
3369*/
3370QDomNode QDomNamedNodeMap::namedItemNS(const QString& nsURI, const QString& localName) const
3371{
3372 if (!impl)
3373 return QDomNode();
3374 return QDomNode(IMPL->namedItemNS(nsURI, localName));
3375}
3376
3377/*!
3378 Inserts the node \a newNode in the map. If a node with the same
3379 namespace URI and the same local name already exists in the map,
3380 it is replaced by \a newNode. If the new node replaces an existing
3381 node, the replaced node is returned.
3382
3383 \sa namedItemNS() removeNamedItemNS() setNamedItem()
3384*/
3385QDomNode QDomNamedNodeMap::setNamedItemNS(const QDomNode& newNode)
3386{
3387 if (!impl)
3388 return QDomNode();
3389 return QDomNode(IMPL->setNamedItemNS((QDomNodePrivate*)newNode.impl));
3390}
3391
3392/*!
3393 Removes the node with the local name \a localName and the
3394 namespace URI \a nsURI from the map.
3395
3396 The function returns the removed node or a \link
3397 QDomNode::isNull() null node\endlink if the map did not contain a
3398 node with the local name \a localName and the namespace URI \a
3399 nsURI.
3400
3401 \sa setNamedItemNS() namedItemNS() removeNamedItem()
3402*/
3403QDomNode QDomNamedNodeMap::removeNamedItemNS(const QString& nsURI, const QString& localName)
3404{
3405 if (!impl)
3406 return QDomNode();
3407 QDomNodePrivate *n = IMPL->namedItemNS(nsURI, localName);
3408 if (!n)
3409 return QDomNode();
3410 return QDomNode(IMPL->removeNamedItem(n->name));
3411}
3412
3413/*!
3414 Returns the number of nodes in the map.
3415
3416 \sa item()
3417*/
3418uint QDomNamedNodeMap::length() const
3419{
3420 if (!impl)
3421 return 0;
3422 return IMPL->length();
3423}
3424
3425/*!
3426 \fn bool QDomNamedNodeMap::isEmpty() const
3427
3428 Returns true if the map is empty; otherwise returns false. This function is
3429 provided for Qt API consistency.
3430*/
3431
3432/*!
3433 \fn int QDomNamedNodeMap::count() const
3434
3435 This function is provided for Qt API consistency. It is equivalent to length().
3436*/
3437
3438/*!
3439 \fn int QDomNamedNodeMap::size() const
3440
3441 This function is provided for Qt API consistency. It is equivalent to length().
3442*/
3443
3444/*!
3445 Returns true if the map contains a node called \a name; otherwise
3446 returns false.
3447
3448 \bold{Note:} This function does not take the presence of namespaces into account.
3449 Use namedItemNS() to test whether the map contains a node with a specific namespace
3450 URI and name.
3451*/
3452bool QDomNamedNodeMap::contains(const QString& name) const
3453{
3454 if (!impl)
3455 return false;
3456 return IMPL->contains(name);
3457}
3458
3459#undef IMPL
3460
3461/**************************************************************
3462 *
3463 * QDomDocumentTypePrivate
3464 *
3465 **************************************************************/
3466
3467QDomDocumentTypePrivate::QDomDocumentTypePrivate(QDomDocumentPrivate* doc, QDomNodePrivate* parent)
3468 : QDomNodePrivate(doc, parent)
3469{
3470 init();
3471}
3472
3473QDomDocumentTypePrivate::QDomDocumentTypePrivate(QDomDocumentTypePrivate* n, bool deep)
3474 : QDomNodePrivate(n, deep)
3475{
3476 init();
3477 // Refill the maps with our new children
3478 QDomNodePrivate* p = first;
3479 while (p) {
3480 if (p->isEntity())
3481 // Dont use normal insert function since we would create infinite recursion
3482 entities->map.insertMulti(p->nodeName(), p);
3483 if (p->isNotation())
3484 // Dont use normal insert function since we would create infinite recursion
3485 notations->map.insertMulti(p->nodeName(), p);
3486 }
3487}
3488
3489QDomDocumentTypePrivate::~QDomDocumentTypePrivate()
3490{
3491 if (!entities->ref.deref())
3492 delete entities;
3493 if (!notations->ref.deref())
3494 delete notations;
3495}
3496
3497void QDomDocumentTypePrivate::init()
3498{
3499 entities = new QDomNamedNodeMapPrivate(this);
3500 QT_TRY {
3501 notations = new QDomNamedNodeMapPrivate(this);
3502 publicId.clear();
3503 systemId.clear();
3504 internalSubset.clear();
3505
3506 entities->setAppendToParent(true);
3507 notations->setAppendToParent(true);
3508 } QT_CATCH(...) {
3509 delete entities;
3510 QT_RETHROW;
3511 }
3512}
3513
3514QDomNodePrivate* QDomDocumentTypePrivate::cloneNode(bool deep)
3515{
3516 QDomNodePrivate* p = new QDomDocumentTypePrivate(this, deep);
3517 // We are not interested in this node
3518 p->ref.deref();
3519 return p;
3520}
3521
3522QDomNodePrivate* QDomDocumentTypePrivate::insertBefore(QDomNodePrivate* newChild, QDomNodePrivate* refChild)
3523{
3524 // Call the origianl implementation
3525 QDomNodePrivate* p = QDomNodePrivate::insertBefore(newChild, refChild);
3526 // Update the maps
3527 if (p && p->isEntity())
3528 entities->map.insertMulti(p->nodeName(), p);
3529 else if (p && p->isNotation())
3530 notations->map.insertMulti(p->nodeName(), p);
3531
3532 return p;
3533}
3534
3535QDomNodePrivate* QDomDocumentTypePrivate::insertAfter(QDomNodePrivate* newChild, QDomNodePrivate* refChild)
3536{
3537 // Call the origianl implementation
3538 QDomNodePrivate* p = QDomNodePrivate::insertAfter(newChild, refChild);
3539 // Update the maps
3540 if (p && p->isEntity())
3541 entities->map.insertMulti(p->nodeName(), p);
3542 else if (p && p->isNotation())
3543 notations->map.insertMulti(p->nodeName(), p);
3544
3545 return p;
3546}
3547
3548QDomNodePrivate* QDomDocumentTypePrivate::replaceChild(QDomNodePrivate* newChild, QDomNodePrivate* oldChild)
3549{
3550 // Call the origianl implementation
3551 QDomNodePrivate* p = QDomNodePrivate::replaceChild(newChild, oldChild);
3552 // Update the maps
3553 if (p) {
3554 if (oldChild && oldChild->isEntity())
3555 entities->map.remove(oldChild->nodeName());
3556 else if (oldChild && oldChild->isNotation())
3557 notations->map.remove(oldChild->nodeName());
3558
3559 if (p->isEntity())
3560 entities->map.insertMulti(p->nodeName(), p);
3561 else if (p->isNotation())
3562 notations->map.insertMulti(p->nodeName(), p);
3563 }
3564
3565 return p;
3566}
3567
3568QDomNodePrivate* QDomDocumentTypePrivate::removeChild(QDomNodePrivate* oldChild)
3569{
3570 // Call the origianl implementation
3571 QDomNodePrivate* p = QDomNodePrivate::removeChild( oldChild);
3572 // Update the maps
3573 if (p && p->isEntity())
3574 entities->map.remove(p->nodeName());
3575 else if (p && p->isNotation())
3576 notations->map.remove(p ->nodeName());
3577
3578 return p;
3579}
3580
3581QDomNodePrivate* QDomDocumentTypePrivate::appendChild(QDomNodePrivate* newChild)
3582{
3583 return insertAfter(newChild, 0);
3584}
3585
3586static QString quotedValue(const QString &data)
3587{
3588 QChar quote = data.indexOf(QLatin1Char('\'')) == -1
3589 ? QLatin1Char('\'')
3590 : QLatin1Char('"');
3591 return quote + data + quote;
3592}
3593
3594void QDomDocumentTypePrivate::save(QTextStream& s, int, int indent) const
3595{
3596 if (name.isEmpty())
3597 return;
3598
3599 s << "<!DOCTYPE " << name;
3600
3601 if (!publicId.isNull()) {
3602 s << " PUBLIC " << quotedValue(publicId);
3603 if (!systemId.isNull()) {
3604 s << ' ' << quotedValue(systemId);
3605 }
3606 } else if (!systemId.isNull()) {
3607 s << " SYSTEM " << quotedValue(systemId);
3608 }
3609
3610 if (entities->length()>0 || notations->length()>0) {
3611 s << " [" << endl;
3612
3613 QHash<QString, QDomNodePrivate *>::const_iterator it2 = notations->map.constBegin();
3614 for (; it2 != notations->map.constEnd(); ++it2)
3615 (*it2)->save(s, 0, indent);
3616
3617 QHash<QString, QDomNodePrivate *>::const_iterator it = entities->map.constBegin();
3618 for (; it != entities->map.constEnd(); ++it)
3619 (*it)->save(s, 0, indent);
3620
3621 s << ']';
3622 }
3623
3624 s << '>' << endl;
3625}
3626
3627/**************************************************************
3628 *
3629 * QDomDocumentType
3630 *
3631 **************************************************************/
3632
3633#define IMPL ((QDomDocumentTypePrivate*)impl)
3634
3635/*!
3636 \class QDomDocumentType
3637 \reentrant
3638 \brief The QDomDocumentType class is the representation of the DTD
3639 in the document tree.
3640
3641 \inmodule QtXml
3642 \ingroup xml-tools
3643
3644 The QDomDocumentType class allows read-only access to some of the
3645 data structures in the DTD: it can return a map of all entities()
3646 and notations(). In addition the function name() returns the name
3647 of the document type as specified in the &lt;!DOCTYPE name&gt;
3648 tag. This class also provides the publicId(), systemId() and
3649 internalSubset() functions.
3650
3651 \sa QDomDocument
3652*/
3653
3654/*!
3655 Creates an empty QDomDocumentType object.
3656*/
3657QDomDocumentType::QDomDocumentType() : QDomNode()
3658{
3659}
3660
3661/*!
3662 Constructs a copy of \a n.
3663
3664 The data of the copy is shared (shallow copy): modifying one node
3665 will also change the other. If you want to make a deep copy, use
3666 cloneNode().
3667*/
3668QDomDocumentType::QDomDocumentType(const QDomDocumentType& n)
3669 : QDomNode(n)
3670{
3671}
3672
3673QDomDocumentType::QDomDocumentType(QDomDocumentTypePrivate* n)
3674 : QDomNode(n)
3675{
3676}
3677
3678/*!
3679 Assigns \a n to this document type.
3680
3681 The data of the copy is shared (shallow copy): modifying one node
3682 will also change the other. If you want to make a deep copy, use
3683 cloneNode().
3684*/
3685QDomDocumentType& QDomDocumentType::operator= (const QDomDocumentType& n)
3686{
3687 return (QDomDocumentType&) QDomNode::operator=(n);
3688}
3689
3690/*!
3691 Returns the name of the document type as specified in the
3692 &lt;!DOCTYPE name&gt; tag.
3693
3694 \sa nodeName()
3695*/
3696QString QDomDocumentType::name() const
3697{
3698 if (!impl)
3699 return QString();
3700 return IMPL->nodeName();
3701}
3702
3703/*!
3704 Returns a map of all entities described in the DTD.
3705*/
3706QDomNamedNodeMap QDomDocumentType::entities() const
3707{
3708 if (!impl)
3709 return QDomNamedNodeMap();
3710 return QDomNamedNodeMap(IMPL->entities);
3711}
3712
3713/*!
3714 Returns a map of all notations described in the DTD.
3715*/
3716QDomNamedNodeMap QDomDocumentType::notations() const
3717{
3718 if (!impl)
3719 return QDomNamedNodeMap();
3720 return QDomNamedNodeMap(IMPL->notations);
3721}
3722
3723/*!
3724 Returns the public identifier of the external DTD subset or
3725 an empty string if there is no public identifier.
3726
3727 \sa systemId() internalSubset() QDomImplementation::createDocumentType()
3728*/
3729QString QDomDocumentType::publicId() const
3730{
3731 if (!impl)
3732 return QString();
3733 return IMPL->publicId;
3734}
3735
3736/*!
3737 Returns the system identifier of the external DTD subset or
3738 an empty string if there is no system identifier.
3739
3740 \sa publicId() internalSubset() QDomImplementation::createDocumentType()
3741*/
3742QString QDomDocumentType::systemId() const
3743{
3744 if (!impl)
3745 return QString();
3746 return IMPL->systemId;
3747}
3748
3749/*!
3750 Returns the internal subset of the document type or an empty
3751 string if there is no internal subset.
3752
3753 \sa publicId() systemId()
3754*/
3755QString QDomDocumentType::internalSubset() const
3756{
3757 if (!impl)
3758 return QString();
3759 return IMPL->internalSubset;
3760}
3761
3762/*
3763 Are these needed at all? The only difference when removing these
3764 two methods in all subclasses is that we'd get a different type
3765 for null nodes.
3766*/
3767
3768/*!
3769 \fn QDomNode::NodeType QDomDocumentType::nodeType() const
3770
3771 Returns \c DocumentTypeNode.
3772
3773 \sa isDocumentType() QDomNode::toDocumentType()
3774*/
3775
3776#undef IMPL
3777
3778/**************************************************************
3779 *
3780 * QDomDocumentFragmentPrivate
3781 *
3782 **************************************************************/
3783
3784QDomDocumentFragmentPrivate::QDomDocumentFragmentPrivate(QDomDocumentPrivate* doc, QDomNodePrivate* parent)
3785 : QDomNodePrivate(doc, parent)
3786{
3787 name = QLatin1String("#document-fragment");
3788}
3789
3790QDomDocumentFragmentPrivate::QDomDocumentFragmentPrivate(QDomNodePrivate* n, bool deep)
3791 : QDomNodePrivate(n, deep)
3792{
3793}
3794
3795QDomNodePrivate* QDomDocumentFragmentPrivate::cloneNode(bool deep)
3796{
3797 QDomNodePrivate* p = new QDomDocumentFragmentPrivate(this, deep);
3798 // We are not interested in this node
3799 p->ref.deref();
3800 return p;
3801}
3802
3803/**************************************************************
3804 *
3805 * QDomDocumentFragment
3806 *
3807 **************************************************************/
3808
3809/*!
3810 \class QDomDocumentFragment
3811 \reentrant
3812 \brief The QDomDocumentFragment class is a tree of QDomNodes which is not usually a complete QDomDocument.
3813
3814 \inmodule QtXml
3815 \ingroup xml-tools
3816
3817 If you want to do complex tree operations it is useful to have a
3818 lightweight class to store nodes and their relations.
3819 QDomDocumentFragment stores a subtree of a document which does not
3820 necessarily represent a well-formed XML document.
3821
3822 QDomDocumentFragment is also useful if you want to group several
3823 nodes in a list and insert them all together as children of some
3824 node. In these cases QDomDocumentFragment can be used as a
3825 temporary container for this list of children.
3826
3827 The most important feature of QDomDocumentFragment is that it is
3828 treated in a special way by QDomNode::insertAfter(),
3829 QDomNode::insertBefore(), QDomNode::replaceChild() and
3830 QDomNode::appendChild(): instead of inserting the fragment itself, all
3831 the fragment's children are inserted.
3832*/
3833
3834/*!
3835 Constructs an empty document fragment.
3836*/
3837QDomDocumentFragment::QDomDocumentFragment()
3838{
3839}
3840
3841QDomDocumentFragment::QDomDocumentFragment(QDomDocumentFragmentPrivate* n)
3842 : QDomNode(n)
3843{
3844}
3845
3846/*!
3847 Constructs a copy of \a x.
3848
3849 The data of the copy is shared (shallow copy): modifying one node
3850 will also change the other. If you want to make a deep copy, use
3851 cloneNode().
3852*/
3853QDomDocumentFragment::QDomDocumentFragment(const QDomDocumentFragment& x)
3854 : QDomNode(x)
3855{
3856}
3857
3858/*!
3859 Assigns \a x to this DOM document fragment.
3860
3861 The data of the copy is shared (shallow copy): modifying one node
3862 will also change the other. If you want to make a deep copy, use
3863 cloneNode().
3864*/
3865QDomDocumentFragment& QDomDocumentFragment::operator= (const QDomDocumentFragment& x)
3866{
3867 return (QDomDocumentFragment&) QDomNode::operator=(x);
3868}
3869
3870/*!
3871 \fn QDomNode::NodeType QDomDocumentFragment::nodeType() const
3872
3873 Returns \c DocumentFragment.
3874
3875 \sa isDocumentFragment() QDomNode::toDocumentFragment()
3876*/
3877
3878/**************************************************************
3879 *
3880 * QDomCharacterDataPrivate
3881 *
3882 **************************************************************/
3883
3884QDomCharacterDataPrivate::QDomCharacterDataPrivate(QDomDocumentPrivate* d, QDomNodePrivate* p,
3885 const QString& data)
3886 : QDomNodePrivate(d, p)
3887{
3888 value = data;
3889 name = QLatin1String("#character-data");
3890}
3891
3892QDomCharacterDataPrivate::QDomCharacterDataPrivate(QDomCharacterDataPrivate* n, bool deep)
3893 : QDomNodePrivate(n, deep)
3894{
3895}
3896
3897QDomNodePrivate* QDomCharacterDataPrivate::cloneNode(bool deep)
3898{
3899 QDomNodePrivate* p = new QDomCharacterDataPrivate(this, deep);
3900 // We are not interested in this node
3901 p->ref.deref();
3902 return p;
3903}
3904
3905uint QDomCharacterDataPrivate::dataLength() const
3906{
3907 return value.length();
3908}
3909
3910QString QDomCharacterDataPrivate::substringData(unsigned long offset, unsigned long n) const
3911{
3912 return value.mid(offset, n);
3913}
3914
3915void QDomCharacterDataPrivate::insertData(unsigned long offset, const QString& arg)
3916{
3917 value.insert(offset, arg);
3918}
3919
3920void QDomCharacterDataPrivate::deleteData(unsigned long offset, unsigned long n)
3921{
3922 value.remove(offset, n);
3923}
3924
3925void QDomCharacterDataPrivate::replaceData(unsigned long offset, unsigned long n, const QString& arg)
3926{
3927 value.replace(offset, n, arg);
3928}
3929
3930void QDomCharacterDataPrivate::appendData(const QString& arg)
3931{
3932 value += arg;
3933}
3934
3935/**************************************************************
3936 *
3937 * QDomCharacterData
3938 *
3939 **************************************************************/
3940
3941#define IMPL ((QDomCharacterDataPrivate*)impl)
3942
3943/*!
3944 \class QDomCharacterData
3945 \reentrant
3946 \brief The QDomCharacterData class represents a generic string in the DOM.
3947
3948 \inmodule QtXml
3949 \ingroup xml-tools
3950
3951 Character data as used in XML specifies a generic data string.
3952 More specialized versions of this class are QDomText, QDomComment
3953 and QDomCDATASection.
3954
3955 The data string is set with setData() and retrieved with data().
3956 You can retrieve a portion of the data string using
3957 substringData(). Extra data can be appended with appendData(), or
3958 inserted with insertData(). Portions of the data string can be
3959 deleted with deleteData() or replaced with replaceData(). The
3960 length of the data string is returned by length().
3961
3962 The node type of the node containing this character data is
3963 returned by nodeType().
3964
3965 \sa QDomText QDomComment QDomCDATASection
3966*/
3967
3968/*!
3969 Constructs an empty character data object.
3970*/
3971QDomCharacterData::QDomCharacterData()
3972{
3973}
3974
3975/*!
3976 Constructs a copy of \a x.
3977
3978 The data of the copy is shared (shallow copy): modifying one node
3979 will also change the other. If you want to make a deep copy, use
3980 cloneNode().
3981*/
3982QDomCharacterData::QDomCharacterData(const QDomCharacterData& x)
3983 : QDomNode(x)
3984{
3985}
3986
3987QDomCharacterData::QDomCharacterData(QDomCharacterDataPrivate* n)
3988 : QDomNode(n)
3989{
3990}
3991
3992/*!
3993 Assigns \a x to this character data.
3994
3995 The data of the copy is shared (shallow copy): modifying one node
3996 will also change the other. If you want to make a deep copy, use
3997 cloneNode().
3998*/
3999QDomCharacterData& QDomCharacterData::operator= (const QDomCharacterData& x)
4000{
4001 return (QDomCharacterData&) QDomNode::operator=(x);
4002}
4003
4004/*!
4005 Returns the string stored in this object.
4006
4007 If the node is a \link isNull() null node\endlink, it will return
4008 an empty string.
4009*/
4010QString QDomCharacterData::data() const
4011{
4012 if (!impl)
4013 return QString();
4014 return impl->nodeValue();
4015}
4016
4017/*!
4018 Sets this object's string to \a v.
4019*/
4020void QDomCharacterData::setData(const QString& v)
4021{
4022 if (impl)
4023 impl->setNodeValue(v);
4024}
4025
4026/*!
4027 Returns the length of the stored string.
4028*/
4029uint QDomCharacterData::length() const
4030{
4031 if (impl)
4032 return IMPL->dataLength();
4033 return 0;
4034}
4035
4036/*!
4037 Returns the substring of length \a count from position \a offset.
4038*/
4039QString QDomCharacterData::substringData(unsigned long offset, unsigned long count)
4040{
4041 if (!impl)
4042 return QString();
4043 return IMPL->substringData(offset, count);
4044}
4045
4046/*!
4047 Appends the string \a arg to the stored string.
4048*/
4049void QDomCharacterData::appendData(const QString& arg)
4050{
4051 if (impl)
4052 IMPL->appendData(arg);
4053}
4054
4055/*!
4056 Inserts the string \a arg into the stored string at position \a offset.
4057*/
4058void QDomCharacterData::insertData(unsigned long offset, const QString& arg)
4059{
4060 if (impl)
4061 IMPL->insertData(offset, arg);
4062}
4063
4064/*!
4065 Deletes a substring of length \a count from position \a offset.
4066*/
4067void QDomCharacterData::deleteData(unsigned long offset, unsigned long count)
4068{
4069 if (impl)
4070 IMPL->deleteData(offset, count);
4071}
4072
4073/*!
4074 Replaces the substring of length \a count starting at position \a
4075 offset with the string \a arg.
4076*/
4077void QDomCharacterData::replaceData(unsigned long offset, unsigned long count, const QString& arg)
4078{
4079 if (impl)
4080 IMPL->replaceData(offset, count, arg);
4081}
4082
4083/*!
4084 Returns the type of node this object refers to (i.e. \c TextNode,
4085 \c CDATASectionNode, \c CommentNode or \c CharacterDataNode). For
4086 a \link isNull() null node\endlink, returns \c CharacterDataNode.
4087*/
4088QDomNode::NodeType QDomCharacterData::nodeType() const
4089{
4090 if (!impl)
4091 return CharacterDataNode;
4092 return QDomNode::nodeType();
4093}
4094
4095#undef IMPL
4096
4097/**************************************************************
4098 *
4099 * QDomAttrPrivate
4100 *
4101 **************************************************************/
4102
4103QDomAttrPrivate::QDomAttrPrivate(QDomDocumentPrivate* d, QDomNodePrivate* parent, const QString& name_)
4104 : QDomNodePrivate(d, parent)
4105{
4106 name = name_;
4107 m_specified = false;
4108}
4109
4110QDomAttrPrivate::QDomAttrPrivate(QDomDocumentPrivate* d, QDomNodePrivate* p, const QString& nsURI, const QString& qName)
4111 : QDomNodePrivate(d, p)
4112{
4113 qt_split_namespace(prefix, name, qName, !nsURI.isNull());
4114 namespaceURI = nsURI;
4115 createdWithDom1Interface = false;
4116 m_specified = false;
4117}
4118
4119QDomAttrPrivate::QDomAttrPrivate(QDomAttrPrivate* n, bool deep)
4120 : QDomNodePrivate(n, deep)
4121{
4122 m_specified = n->specified();
4123}
4124
4125void QDomAttrPrivate::setNodeValue(const QString& v)
4126{
4127 value = v;
4128 QDomTextPrivate *t = new QDomTextPrivate(0, this, v);
4129 // keep the refcount balanced: appendChild() does a ref anyway.
4130 t->ref.deref();
4131 if (first) {
4132 delete removeChild(first);
4133 }
4134 appendChild(t);
4135}
4136
4137QDomNodePrivate* QDomAttrPrivate::cloneNode(bool deep)
4138{
4139 QDomNodePrivate* p = new QDomAttrPrivate(this, deep);
4140 // We are not interested in this node
4141 p->ref.deref();
4142 return p;
4143}
4144
4145bool QDomAttrPrivate::specified() const
4146{
4147 return m_specified;
4148}
4149
4150/* \internal
4151 Encode & escape \a str. Yes, it makes no sense to return a QString,
4152 but is so for legacy reasons.
4153
4154 Remember that content produced should be able to roundtrip with 2.11 End-of-Line Handling
4155 and 3.3.3 Attribute-Value Normalization.
4156
4157 If \a performAVN is true, characters will be escaped to survive Attribute Value Normalization.
4158 If \a encodeEOLs is true, characters will be escaped to survive End-of-Line Handling.
4159*/
4160static QString encodeText(const QString &str,
4161 QTextStream &s,
4162 const bool encodeQuotes = true,
4163 const bool performAVN = false,
4164 const bool encodeEOLs = false)
4165{
4166#ifdef QT_NO_TEXTCODEC
4167 Q_UNUSED(s);
4168#else
4169 const QTextCodec *const codec = s.codec();
4170 Q_ASSERT(codec);
4171#endif
4172 QString retval(str);
4173 int len = retval.length();
4174 int i = 0;
4175
4176 while (i < len) {
4177 const QChar ati(retval.at(i));
4178
4179 if (ati == QLatin1Char('<')) {
4180 retval.replace(i, 1, QLatin1String("&lt;"));
4181 len += 3;
4182 i += 4;
4183 } else if (encodeQuotes && (ati == QLatin1Char('"'))) {
4184 retval.replace(i, 1, QLatin1String("&quot;"));
4185 len += 5;
4186 i += 6;
4187 } else if (ati == QLatin1Char('&')) {
4188 retval.replace(i, 1, QLatin1String("&amp;"));
4189 len += 4;
4190 i += 5;
4191 } else if (ati == QLatin1Char('>') && i >= 2 && retval[i - 1] == QLatin1Char(']') && retval[i - 2] == QLatin1Char(']')) {
4192 retval.replace(i, 1, QLatin1String("&gt;"));
4193 len += 3;
4194 i += 4;
4195 } else if (performAVN &&
4196 (ati == QChar(0xA) ||
4197 ati == QChar(0xD) ||
4198 ati == QChar(0x9))) {
4199 const QString replacement(QLatin1String("&#x") + QString::number(ati.unicode(), 16) + QLatin1Char(';'));
4200 retval.replace(i, 1, replacement);
4201 i += replacement.length();
4202 len += replacement.length() - 1;
4203 } else if (encodeEOLs && ati == QChar(0xD)) {
4204 retval.replace(i, 1, QLatin1String("&#xd;")); // Replace a single 0xD with a ref for 0xD
4205 len += 4;
4206 i += 5;
4207 } else {
4208#ifndef QT_NO_TEXTCODEC
4209 if(codec->canEncode(ati))
4210 ++i;
4211 else
4212#endif
4213 {
4214 // We have to use a character reference to get it through.
4215 const ushort codepoint(ati.unicode());
4216 const QString replacement(QLatin1String("&#x") + QString::number(codepoint, 16) + QLatin1Char(';'));
4217 retval.replace(i, 1, replacement);
4218 i += replacement.length();
4219 len += replacement.length() - 1;
4220 }
4221 }
4222 }
4223
4224 return retval;
4225}
4226
4227void QDomAttrPrivate::save(QTextStream& s, int, int) const
4228{
4229 if (namespaceURI.isNull()) {
4230 s << name << "=\"" << encodeText(value, s, true, true) << '\"';
4231 } else {
4232 s << prefix << ':' << name << "=\"" << encodeText(value, s, true, true) << '\"';
4233 /* This is a fix for 138243, as good as it gets.
4234 *
4235 * QDomElementPrivate::save() output a namespace declaration if
4236 * the element is in a namespace, no matter what. This function do as well, meaning
4237 * that we get two identical namespace declaration if we don't have the if-
4238 * statement below.
4239 *
4240 * This doesn't work when the parent element has the same prefix as us but
4241 * a different namespace. However, this can only occur by the user modifying the element,
4242 * and we don't do fixups by that anyway, and hence it's the user responsibility to not
4243 * arrive in those situations. */
4244 if(!ownerNode ||
4245 ownerNode->prefix != prefix) {
4246 s << " xmlns:" << prefix << "=\"" << encodeText(namespaceURI, s, true, true) << '\"';
4247 }
4248 }
4249}
4250
4251/**************************************************************
4252 *
4253 * QDomAttr
4254 *
4255 **************************************************************/
4256
4257#define IMPL ((QDomAttrPrivate*)impl)
4258
4259/*!
4260 \class QDomAttr
4261 \reentrant
4262 \brief The QDomAttr class represents one attribute of a QDomElement.
4263
4264 \inmodule QtXml
4265 \ingroup xml-tools
4266
4267 For example, the following piece of XML produces an element with
4268 no children, but two attributes:
4269
4270 \snippet doc/src/snippets/code/src_xml_dom_qdom.cpp 7
4271
4272 You can access the attributes of an element with code like this:
4273
4274 \snippet doc/src/snippets/code/src_xml_dom_qdom.cpp 8
4275
4276 This example also shows that changing an attribute received from
4277 an element changes the attribute of the element. If you do not
4278 want to change the value of the element's attribute you must
4279 use cloneNode() to get an independent copy of the attribute.
4280
4281 QDomAttr can return the name() and value() of an attribute. An
4282 attribute's value is set with setValue(). If specified() returns
4283 true the value was set with setValue(). The node this
4284 attribute is attached to (if any) is returned by ownerElement().
4285
4286 For further information about the Document Object Model see
4287 \l{http://www.w3.org/TR/REC-DOM-Level-1/} and
4288 \l{http://www.w3.org/TR/DOM-Level-2-Core/}.
4289 For a more general introduction of the DOM implementation see the
4290 QDomDocument documentation.
4291*/
4292
4293
4294/*!
4295 Constructs an empty attribute.
4296*/
4297QDomAttr::QDomAttr()
4298{
4299}
4300
4301/*!
4302 Constructs a copy of \a x.
4303
4304 The data of the copy is shared (shallow copy): modifying one node
4305 will also change the other. If you want to make a deep copy, use
4306 cloneNode().
4307*/
4308QDomAttr::QDomAttr(const QDomAttr& x)
4309 : QDomNode(x)
4310{
4311}
4312
4313QDomAttr::QDomAttr(QDomAttrPrivate* n)
4314 : QDomNode(n)
4315{
4316}
4317
4318/*!
4319 Assigns \a x to this DOM attribute.
4320
4321 The data of the copy is shared (shallow copy): modifying one node
4322 will also change the other. If you want to make a deep copy, use
4323 cloneNode().
4324*/
4325QDomAttr& QDomAttr::operator= (const QDomAttr& x)
4326{
4327 return (QDomAttr&) QDomNode::operator=(x);
4328}
4329
4330/*!
4331 Returns the attribute's name.
4332*/
4333QString QDomAttr::name() const
4334{
4335 if (!impl)
4336 return QString();
4337 return impl->nodeName();
4338}
4339
4340/*!
4341 Returns true if the attribute has been set by the user with setValue().
4342 Returns false if the value hasn't been specified or set.
4343
4344 \sa setValue()
4345*/
4346bool QDomAttr::specified() const
4347{
4348 if (!impl)
4349 return false;
4350 return IMPL->specified();
4351}
4352
4353/*!
4354 Returns the element node this attribute is attached to or a \link
4355 QDomNode::isNull() null node\endlink if this attribute is not
4356 attached to any element.
4357*/
4358QDomElement QDomAttr::ownerElement() const
4359{
4360 Q_ASSERT(impl->parent());
4361 if (!impl->parent()->isElement())
4362 return QDomElement();
4363 return QDomElement((QDomElementPrivate*)(impl->parent()));
4364}
4365
4366/*!
4367 Returns the value of the attribute or an empty string if the
4368 attribute has not been specified.
4369
4370 \sa specified() setValue()
4371*/
4372QString QDomAttr::value() const
4373{
4374 if (!impl)
4375 return QString();
4376 return impl->nodeValue();
4377}
4378
4379/*!
4380 Sets the attribute's value to \a v.
4381
4382 \sa value()
4383*/
4384void QDomAttr::setValue(const QString& v)
4385{
4386 if (!impl)
4387 return;
4388 impl->setNodeValue(v);
4389 IMPL->m_specified = true;
4390}
4391
4392/*!
4393 \fn QDomNode::NodeType QDomAttr::nodeType() const
4394
4395 Returns \link QDomNode::NodeType AttributeNode\endlink.
4396*/
4397
4398#undef IMPL
4399
4400/**************************************************************
4401 *
4402 * QDomElementPrivate
4403 *
4404 **************************************************************/
4405
4406QDomElementPrivate::QDomElementPrivate(QDomDocumentPrivate* d, QDomNodePrivate* p,
4407 const QString& tagname)
4408 : QDomNodePrivate(d, p)
4409{
4410 name = tagname;
4411 m_attr = new QDomNamedNodeMapPrivate(this);
4412}
4413
4414QDomElementPrivate::QDomElementPrivate(QDomDocumentPrivate* d, QDomNodePrivate* p,
4415 const QString& nsURI, const QString& qName)
4416 : QDomNodePrivate(d, p)
4417{
4418 qt_split_namespace(prefix, name, qName, !nsURI.isNull());
4419 namespaceURI = nsURI;
4420 createdWithDom1Interface = false;
4421 m_attr = new QDomNamedNodeMapPrivate(this);
4422}
4423
4424QDomElementPrivate::QDomElementPrivate(QDomElementPrivate* n, bool deep) :
4425 QDomNodePrivate(n, deep)
4426{
4427 m_attr = n->m_attr->clone(this);
4428 // Reference is down to 0, so we set it to 1 here.
4429 m_attr->ref.ref();
4430}
4431
4432QDomElementPrivate::~QDomElementPrivate()
4433{
4434 if (!m_attr->ref.deref())
4435 delete m_attr;
4436}
4437
4438QDomNodePrivate* QDomElementPrivate::cloneNode(bool deep)
4439{
4440 QDomNodePrivate* p = new QDomElementPrivate(this, deep);
4441 // We are not interested in this node
4442 p->ref.deref();
4443 return p;
4444}
4445
4446QString QDomElementPrivate::attribute(const QString& name_, const QString& defValue) const
4447{
4448 QDomNodePrivate* n = m_attr->namedItem(name_);
4449 if (!n)
4450 return defValue;
4451
4452 return n->nodeValue();
4453}
4454
4455QString QDomElementPrivate::attributeNS(const QString& nsURI, const QString& localName, const QString& defValue) const
4456{
4457 QDomNodePrivate* n = m_attr->namedItemNS(nsURI, localName);
4458 if (!n)
4459 return defValue;
4460
4461 return n->nodeValue();
4462}
4463
4464void QDomElementPrivate::setAttribute(const QString& aname, const QString& newValue)
4465{
4466 QDomNodePrivate* n = m_attr->namedItem(aname);
4467 if (!n) {
4468 n = new QDomAttrPrivate(ownerDocument(), this, aname);
4469 n->setNodeValue(newValue);
4470
4471 // Referencing is done by the map, so we set the reference counter back
4472 // to 0 here. This is ok since we created the QDomAttrPrivate.
4473 n->ref.deref();
4474 m_attr->setNamedItem(n);
4475 } else {
4476 n->setNodeValue(newValue);
4477 }
4478}
4479
4480void QDomElementPrivate::setAttributeNS(const QString& nsURI, const QString& qName, const QString& newValue)
4481{
4482 QString prefix, localName;
4483 qt_split_namespace(prefix, localName, qName, true);
4484 QDomNodePrivate* n = m_attr->namedItemNS(nsURI, localName);
4485 if (!n) {
4486 n = new QDomAttrPrivate(ownerDocument(), this, nsURI, qName);
4487 n->setNodeValue(newValue);
4488
4489 // Referencing is done by the map, so we set the reference counter back
4490 // to 0 here. This is ok since we created the QDomAttrPrivate.
4491 n->ref.deref();
4492 m_attr->setNamedItem(n);
4493 } else {
4494 n->setNodeValue(newValue);
4495 n->prefix = prefix;
4496 }
4497}
4498
4499void QDomElementPrivate::removeAttribute(const QString& aname)
4500{
4501 QDomNodePrivate* p = m_attr->removeNamedItem(aname);
4502 if (p && p->ref == 0)
4503 delete p;
4504}
4505
4506QDomAttrPrivate* QDomElementPrivate::attributeNode(const QString& aname)
4507{
4508 return (QDomAttrPrivate*)m_attr->namedItem(aname);
4509}
4510
4511QDomAttrPrivate* QDomElementPrivate::attributeNodeNS(const QString& nsURI, const QString& localName)
4512{
4513 return (QDomAttrPrivate*)m_attr->namedItemNS(nsURI, localName);
4514}
4515
4516QDomAttrPrivate* QDomElementPrivate::setAttributeNode(QDomAttrPrivate* newAttr)
4517{
4518 QDomNodePrivate* n = m_attr->namedItem(newAttr->nodeName());
4519
4520 // Referencing is done by the maps
4521 m_attr->setNamedItem(newAttr);
4522
4523 newAttr->setParent(this);
4524
4525 return (QDomAttrPrivate*)n;
4526}
4527
4528QDomAttrPrivate* QDomElementPrivate::setAttributeNodeNS(QDomAttrPrivate* newAttr)
4529{
4530 QDomNodePrivate* n = 0;
4531 if (!newAttr->prefix.isNull())
4532 n = m_attr->namedItemNS(newAttr->namespaceURI, newAttr->name);
4533
4534 // Referencing is done by the maps
4535 m_attr->setNamedItem(newAttr);
4536
4537 return (QDomAttrPrivate*)n;
4538}
4539
4540QDomAttrPrivate* QDomElementPrivate::removeAttributeNode(QDomAttrPrivate* oldAttr)
4541{
4542 return (QDomAttrPrivate*)m_attr->removeNamedItem(oldAttr->nodeName());
4543}
4544
4545bool QDomElementPrivate::hasAttribute(const QString& aname)
4546{
4547 return m_attr->contains(aname);
4548}
4549
4550bool QDomElementPrivate::hasAttributeNS(const QString& nsURI, const QString& localName)
4551{
4552 return m_attr->containsNS(nsURI, localName);
4553}
4554
4555QString QDomElementPrivate::text()
4556{
4557 QString t(QLatin1String(""));
4558
4559 QDomNodePrivate* p = first;
4560 while (p) {
4561 if (p->isText() || p->isCDATASection())
4562 t += p->nodeValue();
4563 else if (p->isElement())
4564 t += ((QDomElementPrivate*)p)->text();
4565 p = p->next;
4566 }
4567
4568 return t;
4569}
4570
4571void QDomElementPrivate::save(QTextStream& s, int depth, int indent) const
4572{
4573 if (!(prev && prev->isText()))
4574 s << QString(indent < 1 ? 0 : depth * indent, QLatin1Char(' '));
4575
4576 QString qName(name);
4577 QString nsDecl(QLatin1String(""));
4578 if (!namespaceURI.isNull()) {
4579 /** ### Qt 5:
4580 *
4581 * If we still have QDom, optimize this so that we only declare namespaces that are not
4582 * yet declared. We loose default namespace mappings, so maybe we should rather store
4583 * the information that we get from startPrefixMapping()/endPrefixMapping() and use them.
4584 * Modifications becomes more complex then, however.
4585 *
4586 * We cannot do this during the Qt 4 series because it would require too invasive changes, and
4587 * hence possibly behavioral changes.
4588 */
4589 if (prefix.isEmpty()) {
4590 nsDecl = QLatin1String(" xmlns");
4591 } else {
4592 qName = prefix + QLatin1Char(':') + name;
4593 nsDecl = QLatin1String(" xmlns:") + prefix;
4594 }
4595 nsDecl += QLatin1String("=\"") + encodeText(namespaceURI, s) + QLatin1Char('\"');
4596 }
4597 s << '<' << qName << nsDecl;
4598
4599 QSet<QString> outputtedPrefixes;
4600
4601 /* Write out attributes. */
4602 if (!m_attr->map.isEmpty()) {
4603 QHash<QString, QDomNodePrivate *>::const_iterator it = m_attr->map.constBegin();
4604 for (; it != m_attr->map.constEnd(); ++it) {
4605 s << ' ';
4606 if (it.value()->namespaceURI.isNull()) {
4607 s << it.value()->name << "=\"" << encodeText(it.value()->value, s, true, true) << '\"';
4608 } else {
4609 s << it.value()->prefix << ':' << it.value()->name << "=\"" << encodeText(it.value()->value, s, true, true) << '\"';
4610 /* This is a fix for 138243, as good as it gets.
4611 *
4612 * QDomElementPrivate::save() output a namespace declaration if
4613 * the element is in a namespace, no matter what. This function do as well, meaning
4614 * that we get two identical namespace declaration if we don't have the if-
4615 * statement below.
4616 *
4617 * This doesn't work when the parent element has the same prefix as us but
4618 * a different namespace. However, this can only occur by the user modifying the element,
4619 * and we don't do fixups by that anyway, and hence it's the user responsibility to not
4620 * arrive in those situations. */
4621 if((!it.value()->ownerNode ||
4622 it.value()->ownerNode->prefix != it.value()->prefix) &&
4623 !outputtedPrefixes.contains(it.value()->prefix)) {
4624 s << " xmlns:" << it.value()->prefix << "=\"" << encodeText(it.value()->namespaceURI, s, true, true) << '\"';
4625 outputtedPrefixes.insert(it.value()->prefix);
4626 }
4627 }
4628 }
4629 }
4630
4631 if (last) {
4632 // has child nodes
4633 if (first->isText())
4634 s << '>';
4635 else {
4636 s << '>';
4637
4638 /* -1 disables new lines. */
4639 if (indent != -1)
4640 s << endl;
4641 }
4642 QDomNodePrivate::save(s, depth + 1, indent); if (!last->isText())
4643 s << QString(indent < 1 ? 0 : depth * indent, QLatin1Char(' '));
4644
4645 s << "</" << qName << '>';
4646 } else {
4647 s << "/>";
4648 }
4649 if (!(next && next->isText())) {
4650 /* -1 disables new lines. */
4651 if (indent != -1)
4652 s << endl;
4653 }
4654}
4655
4656/**************************************************************
4657 *
4658 * QDomElement
4659 *
4660 **************************************************************/
4661
4662#define IMPL ((QDomElementPrivate*)impl)
4663
4664/*!
4665 \class QDomElement
4666 \reentrant
4667 \brief The QDomElement class represents one element in the DOM tree.
4668
4669 \inmodule QtXml
4670 \ingroup xml-tools
4671
4672 Elements have a tagName() and zero or more attributes associated
4673 with them. The tag name can be changed with setTagName().
4674
4675 Element attributes are represented by QDomAttr objects that can
4676 be queried using the attribute() and attributeNode() functions.
4677 You can set attributes with the setAttribute() and
4678 setAttributeNode() functions. Attributes can be removed with
4679 removeAttribute(). There are namespace-aware equivalents to these
4680 functions, i.e. setAttributeNS(), setAttributeNodeNS() and
4681 removeAttributeNS().
4682
4683 If you want to access the text of a node use text(), e.g.
4684 \snippet doc/src/snippets/code/src_xml_dom_qdom.cpp 9
4685 The text() function operates recursively to find the text (since
4686 not all elements contain text). If you want to find all the text
4687 in all of a node's children, iterate over the children looking for
4688 QDomText nodes, e.g.
4689 \snippet doc/src/snippets/code/src_xml_dom_qdom.cpp 10
4690 Note that we attempt to convert each node to a text node and use
4691 text() rather than using firstChild().toText().data() or
4692 n.toText().data() directly on the node, because the node may not
4693 be a text element.
4694
4695 You can get a list of all the decendents of an element which have
4696 a specified tag name with elementsByTagName() or
4697 elementsByTagNameNS().
4698
4699 To browse the elements of a dom document use firstChildElement(), lastChildElement(),
4700 nextSiblingElement() and previousSiblingElement(). For example, to iterate over all
4701 child elements called "entry" in a root element called "database", you can use:
4702 \snippet doc/src/snippets/code/src_xml_dom_qdom.cpp 11
4703
4704 For further information about the Document Object Model see
4705 \l{http://www.w3.org/TR/REC-DOM-Level-1/}{Level 1} and
4706 \l{http://www.w3.org/TR/DOM-Level-2-Core/}{Level 2 Core}.
4707 For a more general introduction of the DOM implementation see the
4708 QDomDocument documentation.
4709*/
4710
4711/*!
4712 Constructs an empty element. Use the QDomDocument::createElement()
4713 function to construct elements with content.
4714*/
4715QDomElement::QDomElement()
4716 : QDomNode()
4717{
4718}
4719
4720/*!
4721 Constructs a copy of \a x.
4722
4723 The data of the copy is shared (shallow copy): modifying one node
4724 will also change the other. If you want to make a deep copy, use
4725 cloneNode().
4726*/
4727QDomElement::QDomElement(const QDomElement& x)
4728 : QDomNode(x)
4729{
4730}
4731
4732QDomElement::QDomElement(QDomElementPrivate* n)
4733 : QDomNode(n)
4734{
4735}
4736
4737/*!
4738 Assigns \a x to this DOM element.
4739
4740 The data of the copy is shared (shallow copy): modifying one node
4741 will also change the other. If you want to make a deep copy, use
4742 cloneNode().
4743*/
4744QDomElement& QDomElement::operator= (const QDomElement& x)
4745{
4746 return (QDomElement&) QDomNode::operator=(x);
4747}
4748
4749/*!
4750 \fn QDomNode::NodeType QDomElement::nodeType() const
4751
4752 Returns \c ElementNode.
4753*/
4754
4755/*!
4756 Sets this element's tag name to \a name.
4757
4758 \sa tagName()
4759*/
4760void QDomElement::setTagName(const QString& name)
4761{
4762 if (impl)
4763 impl->name = name;
4764}
4765
4766/*!
4767 Returns the tag name of this element. For an XML element like this:
4768
4769 \snippet doc/src/snippets/code/src_xml_dom_qdom.cpp 12
4770
4771 the tagname would return "img".
4772
4773 \sa setTagName()
4774*/
4775QString QDomElement::tagName() const
4776{
4777 if (!impl)
4778 return QString();
4779 return impl->nodeName();
4780}
4781
4782
4783/*!
4784 Returns a QDomNamedNodeMap containing all this element's attributes.
4785
4786 \sa attribute() setAttribute() attributeNode() setAttributeNode()
4787*/
4788QDomNamedNodeMap QDomElement::attributes() const
4789{
4790 if (!impl)
4791 return QDomNamedNodeMap();
4792 return QDomNamedNodeMap(IMPL->attributes());
4793}
4794
4795/*!
4796 Returns the attribute called \a name. If the attribute does not
4797 exist \a defValue is returned.
4798
4799 \sa setAttribute() attributeNode() setAttributeNode() attributeNS()
4800*/
4801QString QDomElement::attribute(const QString& name, const QString& defValue) const
4802{
4803 if (!impl)
4804 return defValue;
4805 return IMPL->attribute(name, defValue);
4806}
4807
4808/*!
4809 Adds an attribute called \a name with value \a value. If an
4810 attribute with the same name exists, its value is replaced by \a
4811 value.
4812
4813 \sa attribute() setAttributeNode() setAttributeNS()
4814*/
4815void QDomElement::setAttribute(const QString& name, const QString& value)
4816{
4817 if (!impl)
4818 return;
4819 IMPL->setAttribute(name, value);
4820}
4821
4822/*!
4823 \fn void QDomElement::setAttribute(const QString& name, int value)
4824
4825 \overload
4826 The number is formatted according to the current locale.
4827*/
4828
4829/*!
4830 \fn void QDomElement::setAttribute(const QString& name, uint value)
4831
4832 \overload
4833 The number is formatted according to the current locale.
4834*/
4835
4836/*!
4837 \overload
4838
4839 The number is formatted according to the current locale.
4840*/
4841void QDomElement::setAttribute(const QString& name, qlonglong value)
4842{
4843 if (!impl)
4844 return;
4845 QString x;
4846 x.setNum(value);
4847 IMPL->setAttribute(name, x);
4848}
4849
4850/*!
4851 \overload
4852
4853 The number is formatted according to the current locale.
4854*/
4855void QDomElement::setAttribute(const QString& name, qulonglong value)
4856{
4857 if (!impl)
4858 return;
4859 QString x;
4860 x.setNum(value);
4861 IMPL->setAttribute(name, x);
4862}
4863
4864/*!
4865 \overload
4866
4867 The number is formatted according to the current locale.
4868*/
4869void QDomElement::setAttribute(const QString& name, float value)
4870{
4871 if (!impl)
4872 return;
4873 QString x;
4874 x.setNum(value);
4875 IMPL->setAttribute(name, x);
4876}
4877
4878/*!
4879 \overload
4880
4881 The number is formatted according to the current locale.
4882*/
4883void QDomElement::setAttribute(const QString& name, double value)
4884{
4885 if (!impl)
4886 return;
4887 QString x;
4888 char buf[256];
4889 int count = qsnprintf(buf, sizeof(buf), "%.16g", value);
4890 if (count > 0)
4891 x = QString::fromLatin1(buf, count);
4892 else
4893 x.setNum(value); // Fallback
4894 IMPL->setAttribute(name, x);
4895}
4896
4897/*!
4898 Removes the attribute called name \a name from this element.
4899
4900 \sa setAttribute() attribute() removeAttributeNS()
4901*/
4902void QDomElement::removeAttribute(const QString& name)
4903{
4904 if (!impl)
4905 return;
4906 IMPL->removeAttribute(name);
4907}
4908
4909/*!
4910 Returns the QDomAttr object that corresponds to the attribute
4911 called \a name. If no such attribute exists a \link
4912 QDomNode::isNull() null attribute\endlink is returned.
4913
4914 \sa setAttributeNode() attribute() setAttribute() attributeNodeNS()
4915*/
4916QDomAttr QDomElement::attributeNode(const QString& name)
4917{
4918 if (!impl)
4919 return QDomAttr();
4920 return QDomAttr(IMPL->attributeNode(name));
4921}
4922
4923/*!
4924 Adds the attribute \a newAttr to this element.
4925
4926 If the element has another attribute that has the same name as \a
4927 newAttr, this function replaces that attribute and returns it;
4928 otherwise the function returns a \link QDomNode::isNull() null
4929 attribute\endlink.
4930
4931 \sa attributeNode() setAttribute() setAttributeNodeNS()
4932*/
4933QDomAttr QDomElement::setAttributeNode(const QDomAttr& newAttr)
4934{
4935 if (!impl)
4936 return QDomAttr();
4937 return QDomAttr(IMPL->setAttributeNode(((QDomAttrPrivate*)newAttr.impl)));
4938}
4939
4940/*!
4941 Removes the attribute \a oldAttr from the element and returns it.
4942
4943 \sa attributeNode() setAttributeNode()
4944*/
4945QDomAttr QDomElement::removeAttributeNode(const QDomAttr& oldAttr)
4946{
4947 if (!impl)
4948 return QDomAttr(); // ### should this return oldAttr?
4949 return QDomAttr(IMPL->removeAttributeNode(((QDomAttrPrivate*)oldAttr.impl)));
4950}
4951
4952/*!
4953 Returns a QDomNodeList containing all descendants of this element
4954 named \a tagname encountered during a preorder traversal of the
4955 element subtree with this element as its root. The order of the
4956 elements in the returned list is the order they are encountered
4957 during the preorder traversal.
4958
4959 \sa elementsByTagNameNS() QDomDocument::elementsByTagName()
4960*/
4961QDomNodeList QDomElement::elementsByTagName(const QString& tagname) const
4962{
4963 return QDomNodeList(new QDomNodeListPrivate(impl, tagname));
4964}
4965
4966/*!
4967 Returns true if this element has an attribute called \a name;
4968 otherwise returns false.
4969
4970 \bold{Note:} This function does not take the presence of namespaces
4971 into account. As a result, the specified name will be tested
4972 against fully-qualified attribute names that include any namespace
4973 prefixes that may be present.
4974
4975 Use hasAttributeNS() to explicitly test for attributes with specific
4976 namespaces and names.
4977*/
4978bool QDomElement::hasAttribute(const QString& name) const
4979{
4980 if (!impl)
4981 return false;
4982 return IMPL->hasAttribute(name);
4983}
4984
4985/*!
4986 Returns the attribute with the local name \a localName and the
4987 namespace URI \a nsURI. If the attribute does not exist \a
4988 defValue is returned.
4989
4990 \sa setAttributeNS() attributeNodeNS() setAttributeNodeNS() attribute()
4991*/
4992QString QDomElement::attributeNS(const QString nsURI, const QString& localName, const QString& defValue) const
4993{
4994 if (!impl)
4995 return defValue;
4996 return IMPL->attributeNS(nsURI, localName, defValue);
4997}
4998
4999/*!
5000 Adds an attribute with the qualified name \a qName and the
5001 namespace URI \a nsURI with the value \a value. If an attribute
5002 with the same local name and namespace URI exists, its prefix is
5003 replaced by the prefix of \a qName and its value is repaced by \a
5004 value.
5005
5006 Although \a qName is the qualified name, the local name is used to
5007 decide if an existing attribute's value should be replaced.
5008
5009 \sa attributeNS() setAttributeNodeNS() setAttribute()
5010*/
5011void QDomElement::setAttributeNS(const QString nsURI, const QString& qName, const QString& value)
5012{
5013 if (!impl)
5014 return;
5015 IMPL->setAttributeNS(nsURI, qName, value);
5016}
5017
5018/*!
5019 \fn void QDomElement::setAttributeNS(const QString nsURI, const QString& qName, int value)
5020
5021 \overload
5022*/
5023
5024/*!
5025 \fn void QDomElement::setAttributeNS(const QString nsURI, const QString& qName, uint value)
5026
5027 \overload
5028*/
5029
5030/*!
5031 \overload
5032*/
5033void QDomElement::setAttributeNS(const QString nsURI, const QString& qName, qlonglong value)
5034{
5035 if (!impl)
5036 return;
5037 QString x;
5038 x.setNum(value);
5039 IMPL->setAttributeNS(nsURI, qName, x);
5040}
5041
5042/*!
5043 \overload
5044*/
5045void QDomElement::setAttributeNS(const QString nsURI, const QString& qName, qulonglong value)
5046{
5047 if (!impl)
5048 return;
5049 QString x;
5050 x.setNum(value);
5051 IMPL->setAttributeNS(nsURI, qName, x);
5052}
5053
5054/*!
5055 \overload
5056*/
5057void QDomElement::setAttributeNS(const QString nsURI, const QString& qName, double value)
5058{
5059 if (!impl)
5060 return;
5061 QString x;
5062 x.setNum(value);
5063 IMPL->setAttributeNS(nsURI, qName, x);
5064}
5065
5066/*!
5067 Removes the attribute with the local name \a localName and the
5068 namespace URI \a nsURI from this element.
5069
5070 \sa setAttributeNS() attributeNS() removeAttribute()
5071*/
5072void QDomElement::removeAttributeNS(const QString& nsURI, const QString& localName)
5073{
5074 if (!impl)
5075 return;
5076 QDomNodePrivate *n = IMPL->attributeNodeNS(nsURI, localName);
5077 if (!n)
5078 return;
5079 IMPL->removeAttribute(n->nodeName());
5080}
5081
5082/*!
5083 Returns the QDomAttr object that corresponds to the attribute
5084 with the local name \a localName and the namespace URI \a nsURI.
5085 If no such attribute exists a \l{QDomNode::isNull()}{null
5086 attribute} is returned.
5087
5088 \sa setAttributeNode() attribute() setAttribute()
5089*/
5090QDomAttr QDomElement::attributeNodeNS(const QString& nsURI, const QString& localName)
5091{
5092 if (!impl)
5093 return QDomAttr();
5094 return QDomAttr(IMPL->attributeNodeNS(nsURI, localName));
5095}
5096
5097/*!
5098 Adds the attribute \a newAttr to this element.
5099
5100 If the element has another attribute that has the same local name
5101 and namespace URI as \a newAttr, this function replaces that
5102 attribute and returns it; otherwise the function returns a \link
5103 QDomNode::isNull() null attribute\endlink.
5104
5105 \sa attributeNodeNS() setAttributeNS() setAttributeNode()
5106*/
5107QDomAttr QDomElement::setAttributeNodeNS(const QDomAttr& newAttr)
5108{
5109 if (!impl)
5110 return QDomAttr();
5111 return QDomAttr(IMPL->setAttributeNodeNS(((QDomAttrPrivate*)newAttr.impl)));
5112}
5113
5114/*!
5115 Returns a QDomNodeList containing all descendants of this element
5116 with local name \a localName and namespace URI \a nsURI encountered
5117 during a preorder traversal of the element subtree with this element
5118 as its root. The order of the elements in the returned list is the
5119 order they are encountered during the preorder traversal.
5120
5121 \sa elementsByTagName() QDomDocument::elementsByTagNameNS()
5122*/
5123QDomNodeList QDomElement::elementsByTagNameNS(const QString& nsURI, const QString& localName) const
5124{
5125 return QDomNodeList(new QDomNodeListPrivate(impl, nsURI, localName));
5126}
5127
5128/*!
5129 Returns true if this element has an attribute with the local name
5130 \a localName and the namespace URI \a nsURI; otherwise returns
5131 false.
5132*/
5133bool QDomElement::hasAttributeNS(const QString& nsURI, const QString& localName) const
5134{
5135 if (!impl)
5136 return false;
5137 return IMPL->hasAttributeNS(nsURI, localName);
5138}
5139
5140/*!
5141 Returns the element's text or an empty string.
5142
5143 Example:
5144 \snippet doc/src/snippets/code/src_xml_dom_qdom.cpp 13
5145
5146 The function text() of the QDomElement for the \c{<h1>} tag,
5147 will return the following text:
5148
5149 \snippet doc/src/snippets/code/src_xml_dom_qdom.cpp 14
5150
5151 Comments are ignored by this function. It only evaluates QDomText
5152 and QDomCDATASection objects.
5153*/
5154QString QDomElement::text() const
5155{
5156 if (!impl)
5157 return QString();
5158 return IMPL->text();
5159}
5160
5161#undef IMPL
5162
5163/**************************************************************
5164 *
5165 * QDomTextPrivate
5166 *
5167 **************************************************************/
5168
5169QDomTextPrivate::QDomTextPrivate(QDomDocumentPrivate* d, QDomNodePrivate* parent, const QString& val)
5170 : QDomCharacterDataPrivate(d, parent, val)
5171{
5172 name = QLatin1String("#text");
5173}
5174
5175QDomTextPrivate::QDomTextPrivate(QDomTextPrivate* n, bool deep)
5176 : QDomCharacterDataPrivate(n, deep)
5177{
5178}
5179
5180QDomNodePrivate* QDomTextPrivate::cloneNode(bool deep)
5181{
5182 QDomNodePrivate* p = new QDomTextPrivate(this, deep);
5183 // We are not interested in this node
5184 p->ref.deref();
5185 return p;
5186}
5187
5188QDomTextPrivate* QDomTextPrivate::splitText(int offset)
5189{
5190 if (!parent()) {
5191 qWarning("QDomText::splitText The node has no parent. So I can not split");
5192 return 0;
5193 }
5194
5195 QDomTextPrivate* t = new QDomTextPrivate(ownerDocument(), 0, value.mid(offset));
5196 value.truncate(offset);
5197
5198 parent()->insertAfter(t, this);
5199
5200 return t;
5201}
5202
5203void QDomTextPrivate::save(QTextStream& s, int, int) const
5204{
5205 QDomTextPrivate *that = const_cast<QDomTextPrivate*>(this);
5206 s << encodeText(value, s, !(that->parent() && that->parent()->isElement()), false, true);
5207}
5208
5209/**************************************************************
5210 *
5211 * QDomText
5212 *
5213 **************************************************************/
5214
5215#define IMPL ((QDomTextPrivate*)impl)
5216
5217/*!
5218 \class QDomText
5219 \reentrant
5220 \brief The QDomText class represents text data in the parsed XML document.
5221
5222 \inmodule QtXml
5223 \ingroup xml-tools
5224
5225 You can split the text in a QDomText object over two QDomText
5226 objecs with splitText().
5227
5228 For further information about the Document Object Model see
5229 \l{http://www.w3.org/TR/REC-DOM-Level-1/}{Level 1} and
5230 \l{http://www.w3.org/TR/DOM-Level-2-Core/}{Level 2 Core}.
5231 For a more general introduction of the DOM implementation see the
5232 QDomDocument documentation.
5233*/
5234
5235/*!
5236 Constructs an empty QDomText object.
5237
5238 To construct a QDomText with content, use QDomDocument::createTextNode().
5239*/
5240QDomText::QDomText()
5241 : QDomCharacterData()
5242{
5243}
5244
5245/*!
5246 Constructs a copy of \a x.
5247
5248 The data of the copy is shared (shallow copy): modifying one node
5249 will also change the other. If you want to make a deep copy, use
5250 cloneNode().
5251*/
5252QDomText::QDomText(const QDomText& x)
5253 : QDomCharacterData(x)
5254{
5255}
5256
5257QDomText::QDomText(QDomTextPrivate* n)
5258 : QDomCharacterData(n)
5259{
5260}
5261
5262/*!
5263 Assigns \a x to this DOM text.
5264
5265 The data of the copy is shared (shallow copy): modifying one node
5266 will also change the other. If you want to make a deep copy, use
5267 cloneNode().
5268*/
5269QDomText& QDomText::operator= (const QDomText& x)
5270{
5271 return (QDomText&) QDomNode::operator=(x);
5272}
5273
5274/*!
5275 \fn QDomNode::NodeType QDomText::nodeType() const
5276
5277 Returns \c TextNode.
5278*/
5279
5280/*!
5281 Splits this DOM text object into two QDomText objects. This object
5282 keeps its first \a offset characters and the second (newly
5283 created) object is inserted into the document tree after this
5284 object with the remaining characters.
5285
5286 The function returns the newly created object.
5287
5288 \sa QDomNode::normalize()
5289*/
5290QDomText QDomText::splitText(int offset)
5291{
5292 if (!impl)
5293 return QDomText();
5294 return QDomText(IMPL->splitText(offset));
5295}
5296
5297#undef IMPL
5298
5299/**************************************************************
5300 *
5301 * QDomCommentPrivate
5302 *
5303 **************************************************************/
5304
5305QDomCommentPrivate::QDomCommentPrivate(QDomDocumentPrivate* d, QDomNodePrivate* parent, const QString& val)
5306 : QDomCharacterDataPrivate(d, parent, val)
5307{
5308 name = QLatin1String("#comment");
5309}
5310
5311QDomCommentPrivate::QDomCommentPrivate(QDomCommentPrivate* n, bool deep)
5312 : QDomCharacterDataPrivate(n, deep)
5313{
5314}
5315
5316
5317QDomNodePrivate* QDomCommentPrivate::cloneNode(bool deep)
5318{
5319 QDomNodePrivate* p = new QDomCommentPrivate(this, deep);
5320 // We are not interested in this node
5321 p->ref.deref();
5322 return p;
5323}
5324
5325void QDomCommentPrivate::save(QTextStream& s, int depth, int indent) const
5326{
5327 /* We don't output whitespace if we would pollute a text node. */
5328 if (!(prev && prev->isText()))
5329 s << QString(indent < 1 ? 0 : depth * indent, QLatin1Char(' '));
5330
5331 s << "<!--" << value;
5332 if (value.endsWith(QLatin1Char('-')))
5333 s << ' '; // Ensures that XML comment doesn't end with --->
5334 s << "-->";
5335
5336 if (!(next && next->isText()))
5337 s << endl;
5338}
5339
5340/**************************************************************
5341 *
5342 * QDomComment
5343 *
5344 **************************************************************/
5345
5346/*!
5347 \class QDomComment
5348 \reentrant
5349 \brief The QDomComment class represents an XML comment.
5350
5351 \inmodule QtXml
5352 \ingroup xml-tools
5353
5354 A comment in the parsed XML such as this:
5355 \snippet doc/src/snippets/code/src_xml_dom_qdom.cpp 15
5356 is represented by QDomComment objects in the parsed Dom tree.
5357
5358 For further information about the Document Object Model see
5359 \l{http://www.w3.org/TR/REC-DOM-Level-1/} and
5360 \l{http://www.w3.org/TR/DOM-Level-2-Core/}.
5361 For a more general introduction of the DOM implementation see the
5362 QDomDocument documentation.
5363*/
5364
5365/*!
5366 Constructs an empty comment. To construct a comment with content,
5367 use the QDomDocument::createComment() function.
5368*/
5369QDomComment::QDomComment()
5370 : QDomCharacterData()
5371{
5372}
5373
5374/*!
5375 Constructs a copy of \a x.
5376
5377 The data of the copy is shared (shallow copy): modifying one node
5378 will also change the other. If you want to make a deep copy, use
5379 cloneNode().
5380*/
5381QDomComment::QDomComment(const QDomComment& x)
5382 : QDomCharacterData(x)
5383{
5384}
5385
5386QDomComment::QDomComment(QDomCommentPrivate* n)
5387 : QDomCharacterData(n)
5388{
5389}
5390
5391/*!
5392 Assigns \a x to this DOM comment.
5393
5394 The data of the copy is shared (shallow copy): modifying one node
5395 will also change the other. If you want to make a deep copy, use
5396 cloneNode().
5397*/
5398QDomComment& QDomComment::operator= (const QDomComment& x)
5399{
5400 return (QDomComment&) QDomNode::operator=(x);
5401}
5402
5403/*!
5404 \fn QDomNode::NodeType QDomComment::nodeType() const
5405
5406 Returns \c CommentNode.
5407*/
5408
5409/**************************************************************
5410 *
5411 * QDomCDATASectionPrivate
5412 *
5413 **************************************************************/
5414
5415QDomCDATASectionPrivate::QDomCDATASectionPrivate(QDomDocumentPrivate* d, QDomNodePrivate* parent,
5416 const QString& val)
5417 : QDomTextPrivate(d, parent, val)
5418{
5419 name = QLatin1String("#cdata-section");
5420}
5421
5422QDomCDATASectionPrivate::QDomCDATASectionPrivate(QDomCDATASectionPrivate* n, bool deep)
5423 : QDomTextPrivate(n, deep)
5424{
5425}
5426
5427QDomNodePrivate* QDomCDATASectionPrivate::cloneNode(bool deep)
5428{
5429 QDomNodePrivate* p = new QDomCDATASectionPrivate(this, deep);
5430 // We are not interested in this node
5431 p->ref.deref();
5432 return p;
5433}
5434
5435void QDomCDATASectionPrivate::save(QTextStream& s, int, int) const
5436{
5437 // ### How do we escape "]]>" ?
5438 // "]]>" is not allowed; so there should be none in value anyway
5439 s << "<![CDATA[" << value << "]]>";
5440}
5441
5442/**************************************************************
5443 *
5444 * QDomCDATASection
5445 *
5446 **************************************************************/
5447
5448/*!
5449 \class QDomCDATASection
5450 \reentrant
5451 \brief The QDomCDATASection class represents an XML CDATA section.
5452
5453 \inmodule QtXml
5454 \ingroup xml-tools
5455
5456 CDATA sections are used to escape blocks of text containing
5457 characters that would otherwise be regarded as markup. The only
5458 delimiter that is recognized in a CDATA section is the "]]&gt;"
5459 string that terminates the CDATA section. CDATA sections cannot be
5460 nested. Their primary purpose is for including material such as
5461 XML fragments, without needing to escape all the delimiters.
5462
5463 Adjacent QDomCDATASection nodes are not merged by the
5464 QDomNode::normalize() function.
5465
5466 For further information about the Document Object Model see
5467 \l{http://www.w3.org/TR/REC-DOM-Level-1/} and
5468 \l{http://www.w3.org/TR/DOM-Level-2-Core/}.
5469 For a more general introduction of the DOM implementation see the
5470 QDomDocument documentation.
5471*/
5472
5473/*!
5474 Constructs an empty CDATA section. To create a CDATA section with
5475 content, use the QDomDocument::createCDATASection() function.
5476*/
5477QDomCDATASection::QDomCDATASection()
5478 : QDomText()
5479{
5480}
5481
5482/*!
5483 Constructs a copy of \a x.
5484
5485 The data of the copy is shared (shallow copy): modifying one node
5486 will also change the other. If you want to make a deep copy, use
5487 cloneNode().
5488*/
5489QDomCDATASection::QDomCDATASection(const QDomCDATASection& x)
5490 : QDomText(x)
5491{
5492}
5493
5494QDomCDATASection::QDomCDATASection(QDomCDATASectionPrivate* n)
5495 : QDomText(n)
5496{
5497}
5498
5499/*!
5500 Assigns \a x to this CDATA section.
5501
5502 The data of the copy is shared (shallow copy): modifying one node
5503 will also change the other. If you want to make a deep copy, use
5504 cloneNode().
5505*/
5506QDomCDATASection& QDomCDATASection::operator= (const QDomCDATASection& x)
5507{
5508 return (QDomCDATASection&) QDomNode::operator=(x);
5509}
5510
5511/*!
5512 \fn QDomNode::NodeType QDomCDATASection::nodeType() const
5513
5514 Returns \c CDATASection.
5515*/
5516
5517/**************************************************************
5518 *
5519 * QDomNotationPrivate
5520 *
5521 **************************************************************/
5522
5523QDomNotationPrivate::QDomNotationPrivate(QDomDocumentPrivate* d, QDomNodePrivate* parent,
5524 const QString& aname,
5525 const QString& pub, const QString& sys)
5526 : QDomNodePrivate(d, parent)
5527{
5528 name = aname;
5529 m_pub = pub;
5530 m_sys = sys;
5531}
5532
5533QDomNotationPrivate::QDomNotationPrivate(QDomNotationPrivate* n, bool deep)
5534 : QDomNodePrivate(n, deep)
5535{
5536 m_sys = n->m_sys;
5537 m_pub = n->m_pub;
5538}
5539
5540QDomNodePrivate* QDomNotationPrivate::cloneNode(bool deep)
5541{
5542 QDomNodePrivate* p = new QDomNotationPrivate(this, deep);
5543 // We are not interested in this node
5544 p->ref.deref();
5545 return p;
5546}
5547
5548void QDomNotationPrivate::save(QTextStream& s, int, int) const
5549{
5550 s << "<!NOTATION " << name << ' ';
5551 if (!m_pub.isNull()) {
5552 s << "PUBLIC " << quotedValue(m_pub);
5553 if (!m_sys.isNull())
5554 s << ' ' << quotedValue(m_sys);
5555 } else {
5556 s << "SYSTEM " << quotedValue(m_sys);
5557 }
5558 s << '>' << endl;
5559}
5560
5561/**************************************************************
5562 *
5563 * QDomNotation
5564 *
5565 **************************************************************/
5566
5567#define IMPL ((QDomNotationPrivate*)impl)
5568
5569/*!
5570 \class QDomNotation
5571 \reentrant
5572 \brief The QDomNotation class represents an XML notation.
5573
5574 \inmodule QtXml
5575 \ingroup xml-tools
5576
5577 A notation either declares, by name, the format of an unparsed
5578 entity (see section 4.7 of the XML 1.0 specification), or is used
5579 for formal declaration of processing instruction targets (see
5580 section 2.6 of the XML 1.0 specification).
5581
5582 DOM does not support editing notation nodes; they are therefore
5583 read-only.
5584
5585 A notation node does not have any parent.
5586
5587 You can retrieve the publicId() and systemId() from a notation
5588 node.
5589
5590 For further information about the Document Object Model see
5591 \l{http://www.w3.org/TR/REC-DOM-Level-1/}{Level 1} and
5592 \l{http://www.w3.org/TR/DOM-Level-2-Core/}{Level 2 Core}.
5593 For a more general introduction of the DOM implementation see the
5594 QDomDocument documentation.
5595*/
5596
5597
5598/*!
5599 Constructor.
5600*/
5601QDomNotation::QDomNotation()
5602 : QDomNode()
5603{
5604}
5605
5606/*!
5607 Constructs a copy of \a x.
5608
5609 The data of the copy is shared (shallow copy): modifying one node
5610 will also change the other. If you want to make a deep copy, use
5611 cloneNode().
5612*/
5613QDomNotation::QDomNotation(const QDomNotation& x)
5614 : QDomNode(x)
5615{
5616}
5617
5618QDomNotation::QDomNotation(QDomNotationPrivate* n)
5619 : QDomNode(n)
5620{
5621}
5622
5623/*!
5624 Assigns \a x to this DOM notation.
5625
5626 The data of the copy is shared (shallow copy): modifying one node
5627 will also change the other. If you want to make a deep copy, use
5628 cloneNode().
5629*/
5630QDomNotation& QDomNotation::operator= (const QDomNotation& x)
5631{
5632 return (QDomNotation&) QDomNode::operator=(x);
5633}
5634
5635/*!
5636 \fn QDomNode::NodeType QDomNotation::nodeType() const
5637
5638 Returns \c NotationNode.
5639*/
5640
5641/*!
5642 Returns the public identifier of this notation.
5643*/
5644QString QDomNotation::publicId() const
5645{
5646 if (!impl)
5647 return QString();
5648 return IMPL->m_pub;
5649}
5650
5651/*!
5652 Returns the system identifier of this notation.
5653*/
5654QString QDomNotation::systemId() const
5655{
5656 if (!impl)
5657 return QString();
5658 return IMPL->m_sys;
5659}
5660
5661#undef IMPL
5662
5663/**************************************************************
5664 *
5665 * QDomEntityPrivate
5666 *
5667 **************************************************************/
5668
5669QDomEntityPrivate::QDomEntityPrivate(QDomDocumentPrivate* d, QDomNodePrivate* parent,
5670 const QString& aname,
5671 const QString& pub, const QString& sys, const QString& notation)
5672 : QDomNodePrivate(d, parent)
5673{
5674 name = aname;
5675 m_pub = pub;
5676 m_sys = sys;
5677 m_notationName = notation;
5678}
5679
5680QDomEntityPrivate::QDomEntityPrivate(QDomEntityPrivate* n, bool deep)
5681 : QDomNodePrivate(n, deep)
5682{
5683 m_sys = n->m_sys;
5684 m_pub = n->m_pub;
5685 m_notationName = n->m_notationName;
5686}
5687
5688QDomNodePrivate* QDomEntityPrivate::cloneNode(bool deep)
5689{
5690 QDomNodePrivate* p = new QDomEntityPrivate(this, deep);
5691 // We are not interested in this node
5692 p->ref.deref();
5693 return p;
5694}
5695
5696/*
5697 Encode an entity value upon saving.
5698*/
5699static QByteArray encodeEntity(const QByteArray& str)
5700{
5701 QByteArray tmp(str);
5702 uint len = tmp.size();
5703 uint i = 0;
5704 const char* d = tmp.data();
5705 while (i < len) {
5706 if (d[i] == '%'){
5707 tmp.replace(i, 1, "&#60;");
5708 d = tmp;
5709 len += 4;
5710 i += 5;
5711 }
5712 else if (d[i] == '"') {
5713 tmp.replace(i, 1, "&#34;");
5714 d = tmp;
5715 len += 4;
5716 i += 5;
5717 } else if (d[i] == '&' && i + 1 < len && d[i+1] == '#') {
5718 // Dont encode &lt; or &quot; or &custom;.
5719 // Only encode character references
5720 tmp.replace(i, 1, "&#38;");
5721 d = tmp;
5722 len += 4;
5723 i += 5;
5724 } else {
5725 ++i;
5726 }
5727 }
5728
5729 return tmp;
5730}
5731
5732void QDomEntityPrivate::save(QTextStream& s, int, int) const
5733{
5734 QString _name = name;
5735 if (_name.startsWith(QLatin1Char('%')))
5736 _name = QLatin1String("% ") + _name.mid(1);
5737
5738 if (m_sys.isNull() && m_pub.isNull()) {
5739 s << "<!ENTITY " << _name << " \"" << encodeEntity(value.toUtf8()) << "\">" << endl;
5740 } else {
5741 s << "<!ENTITY " << _name << ' ';
5742 if (m_pub.isNull()) {
5743 s << "SYSTEM " << quotedValue(m_sys);
5744 } else {
5745 s << "PUBLIC " << quotedValue(m_pub) << ' ' << quotedValue(m_sys);
5746 }
5747 if (! m_notationName.isNull()) {
5748 s << " NDATA " << m_notationName;
5749 }
5750 s << '>' << endl;
5751 }
5752}
5753
5754/**************************************************************
5755 *
5756 * QDomEntity
5757 *
5758 **************************************************************/
5759
5760#define IMPL ((QDomEntityPrivate*)impl)
5761
5762/*!
5763 \class QDomEntity
5764 \reentrant
5765 \brief The QDomEntity class represents an XML entity.
5766
5767 \inmodule QtXml
5768 \ingroup xml-tools
5769
5770 This class represents an entity in an XML document, either parsed
5771 or unparsed. Note that this models the entity itself not the
5772 entity declaration.
5773
5774 DOM does not support editing entity nodes; if a user wants to make
5775 changes to the contents of an entity, every related
5776 QDomEntityReference node must be replaced in the DOM tree by a
5777 clone of the entity's contents, and then the desired changes must
5778 be made to each of the clones instead. All the descendants of an
5779 entity node are read-only.
5780
5781 An entity node does not have any parent.
5782
5783 You can access the entity's publicId(), systemId() and
5784 notationName() when available.
5785
5786 For further information about the Document Object Model see
5787 \l{http://www.w3.org/TR/REC-DOM-Level-1/}{Level 1} and
5788 \l{http://www.w3.org/TR/DOM-Level-2-Core/}{Level 2 Core}.
5789 For a more general introduction of the DOM implementation see the
5790 QDomDocument documentation.
5791*/
5792
5793
5794/*!
5795 Constructs an empty entity.
5796*/
5797QDomEntity::QDomEntity()
5798 : QDomNode()
5799{
5800}
5801
5802
5803/*!
5804 Constructs a copy of \a x.
5805
5806 The data of the copy is shared (shallow copy): modifying one node
5807 will also change the other. If you want to make a deep copy, use
5808 cloneNode().
5809*/
5810QDomEntity::QDomEntity(const QDomEntity& x)
5811 : QDomNode(x)
5812{
5813}
5814
5815QDomEntity::QDomEntity(QDomEntityPrivate* n)
5816 : QDomNode(n)
5817{
5818}
5819
5820/*!
5821 Assigns \a x to this DOM entity.
5822
5823 The data of the copy is shared (shallow copy): modifying one node
5824 will also change the other. If you want to make a deep copy, use
5825 cloneNode().
5826*/
5827QDomEntity& QDomEntity::operator= (const QDomEntity& x)
5828{
5829 return (QDomEntity&) QDomNode::operator=(x);
5830}
5831
5832/*!
5833 \fn QDomNode::NodeType QDomEntity::nodeType() const
5834
5835 Returns \c EntityNode.
5836*/
5837
5838/*!
5839 Returns the public identifier associated with this entity. If the
5840 public identifier was not specified an empty string is returned.
5841*/
5842QString QDomEntity::publicId() const
5843{
5844 if (!impl)
5845 return QString();
5846 return IMPL->m_pub;
5847}
5848
5849/*!
5850 Returns the system identifier associated with this entity. If the
5851 system identifier was not specified an empty string is returned.
5852*/
5853QString QDomEntity::systemId() const
5854{
5855 if (!impl)
5856 return QString();
5857 return IMPL->m_sys;
5858}
5859
5860/*!
5861 For unparsed entities this function returns the name of the
5862 notation for the entity. For parsed entities this function returns
5863 an empty string.
5864*/
5865QString QDomEntity::notationName() const
5866{
5867 if (!impl)
5868 return QString();
5869 return IMPL->m_notationName;
5870}
5871
5872#undef IMPL
5873
5874/**************************************************************
5875 *
5876 * QDomEntityReferencePrivate
5877 *
5878 **************************************************************/
5879
5880QDomEntityReferencePrivate::QDomEntityReferencePrivate(QDomDocumentPrivate* d, QDomNodePrivate* parent, const QString& aname)
5881 : QDomNodePrivate(d, parent)
5882{
5883 name = aname;
5884}
5885
5886QDomEntityReferencePrivate::QDomEntityReferencePrivate(QDomNodePrivate* n, bool deep)
5887 : QDomNodePrivate(n, deep)
5888{
5889}
5890
5891QDomNodePrivate* QDomEntityReferencePrivate::cloneNode(bool deep)
5892{
5893 QDomNodePrivate* p = new QDomEntityReferencePrivate(this, deep);
5894 // We are not interested in this node
5895 p->ref.deref();
5896 return p;
5897}
5898
5899void QDomEntityReferencePrivate::save(QTextStream& s, int, int) const
5900{
5901 s << '&' << name << ';';
5902}
5903
5904/**************************************************************
5905 *
5906 * QDomEntityReference
5907 *
5908 **************************************************************/
5909
5910/*!
5911 \class QDomEntityReference
5912 \reentrant
5913 \brief The QDomEntityReference class represents an XML entity reference.
5914
5915 \inmodule QtXml
5916 \ingroup xml-tools
5917
5918 A QDomEntityReference object may be inserted into the DOM tree
5919 when an entity reference is in the source document, or when the
5920 user wishes to insert an entity reference.
5921
5922 Note that character references and references to predefined
5923 entities are expanded by the XML processor so that characters are
5924 represented by their Unicode equivalent rather than by an entity
5925 reference.
5926
5927 Moreover, the XML processor may completely expand references to
5928 entities while building the DOM tree, instead of providing
5929 QDomEntityReference objects.
5930
5931 If it does provide such objects, then for a given entity reference
5932 node, it may be that there is no entity node representing the
5933 referenced entity; but if such an entity exists, then the child
5934 list of the entity reference node is the same as that of the
5935 entity node. As with the entity node, all descendants of the
5936 entity reference are read-only.
5937
5938 For further information about the Document Object Model see
5939 \l{http://www.w3.org/TR/REC-DOM-Level-1/}{Level 1} and
5940 \l{http://www.w3.org/TR/DOM-Level-2-Core/}{Level 2 Core}.
5941 For a more general introduction of the DOM implementation see the
5942 QDomDocument documentation.
5943*/
5944
5945/*!
5946 Constructs an empty entity reference. Use
5947 QDomDocument::createEntityReference() to create a entity reference
5948 with content.
5949*/
5950QDomEntityReference::QDomEntityReference()
5951 : QDomNode()
5952{
5953}
5954
5955/*!
5956 Constructs a copy of \a x.
5957
5958 The data of the copy is shared (shallow copy): modifying one node
5959 will also change the other. If you want to make a deep copy, use
5960 cloneNode().
5961*/
5962QDomEntityReference::QDomEntityReference(const QDomEntityReference& x)
5963 : QDomNode(x)
5964{
5965}
5966
5967QDomEntityReference::QDomEntityReference(QDomEntityReferencePrivate* n)
5968 : QDomNode(n)
5969{
5970}
5971
5972/*!
5973 Assigns \a x to this entity reference.
5974
5975 The data of the copy is shared (shallow copy): modifying one node
5976 will also change the other. If you want to make a deep copy, use
5977 cloneNode().
5978*/
5979QDomEntityReference& QDomEntityReference::operator= (const QDomEntityReference& x)
5980{
5981 return (QDomEntityReference&) QDomNode::operator=(x);
5982}
5983
5984/*!
5985 \fn QDomNode::NodeType QDomEntityReference::nodeType() const
5986
5987 Returns \c EntityReference.
5988*/
5989
5990/**************************************************************
5991 *
5992 * QDomProcessingInstructionPrivate
5993 *
5994 **************************************************************/
5995
5996QDomProcessingInstructionPrivate::QDomProcessingInstructionPrivate(QDomDocumentPrivate* d,
5997 QDomNodePrivate* parent, const QString& target, const QString& data)
5998 : QDomNodePrivate(d, parent)
5999{
6000 name = target;
6001 value = data;
6002}
6003
6004QDomProcessingInstructionPrivate::QDomProcessingInstructionPrivate(QDomProcessingInstructionPrivate* n, bool deep)
6005 : QDomNodePrivate(n, deep)
6006{
6007}
6008
6009
6010QDomNodePrivate* QDomProcessingInstructionPrivate::cloneNode(bool deep)
6011{
6012 QDomNodePrivate* p = new QDomProcessingInstructionPrivate(this, deep);
6013 // We are not interested in this node
6014 p->ref.deref();
6015 return p;
6016}
6017
6018void QDomProcessingInstructionPrivate::save(QTextStream& s, int, int) const
6019{
6020 s << "<?" << name << ' ' << value << "?>" << endl;
6021}
6022
6023/**************************************************************
6024 *
6025 * QDomProcessingInstruction
6026 *
6027 **************************************************************/
6028
6029/*!
6030 \class QDomProcessingInstruction
6031 \reentrant
6032 \brief The QDomProcessingInstruction class represents an XML processing
6033 instruction.
6034
6035 \inmodule QtXml
6036 \ingroup xml-tools
6037
6038 Processing instructions are used in XML to keep processor-specific
6039 information in the text of the document.
6040
6041 The XML declaration that appears at the top of an XML document,
6042 typically \tt{<?xml version='1.0' encoding='UTF-8'?>}, is treated by QDom as a
6043 processing instruction. This is unfortunate, since the XML declaration is
6044 not a processing instruction; among other differences, it cannot be
6045 inserted into a document anywhere but on the first line.
6046
6047 Do not use this function to create an xml declaration, since although it
6048 has the same syntax as a processing instruction, it isn't, and might not
6049 be treated by QDom as such.
6050
6051 The content of the processing instruction is retrieved with data()
6052 and set with setData(). The processing instruction's target is
6053 retrieved with target().
6054
6055 For further information about the Document Object Model see
6056 \l{http://www.w3.org/TR/REC-DOM-Level-1/}{Level 1} and
6057 \l{http://www.w3.org/TR/DOM-Level-2-Core/}{Level 2 Core}.
6058 For a more general introduction of the DOM implementation see the
6059 QDomDocument documentation.
6060*/
6061
6062/*!
6063 Constructs an empty processing instruction. Use
6064 QDomDocument::createProcessingInstruction() to create a processing
6065 instruction with content.
6066*/
6067QDomProcessingInstruction::QDomProcessingInstruction()
6068 : QDomNode()
6069{
6070}
6071
6072/*!
6073 Constructs a copy of \a x.
6074
6075 The data of the copy is shared (shallow copy): modifying one node
6076 will also change the other. If you want to make a deep copy, use
6077 cloneNode().
6078*/
6079QDomProcessingInstruction::QDomProcessingInstruction(const QDomProcessingInstruction& x)
6080 : QDomNode(x)
6081{
6082}
6083
6084QDomProcessingInstruction::QDomProcessingInstruction(QDomProcessingInstructionPrivate* n)
6085 : QDomNode(n)
6086{
6087}
6088
6089/*!
6090 Assigns \a x to this processing instruction.
6091
6092 The data of the copy is shared (shallow copy): modifying one node
6093 will also change the other. If you want to make a deep copy, use
6094 cloneNode().
6095*/
6096QDomProcessingInstruction& QDomProcessingInstruction::operator= (const QDomProcessingInstruction& x)
6097{
6098 return (QDomProcessingInstruction&) QDomNode::operator=(x);
6099}
6100
6101/*!
6102 \fn QDomNode::NodeType QDomProcessingInstruction::nodeType() const
6103
6104 Returns \c ProcessingInstructionNode.
6105*/
6106
6107/*!
6108 Returns the target of this processing instruction.
6109
6110 \sa data()
6111*/
6112QString QDomProcessingInstruction::target() const
6113{
6114 if (!impl)
6115 return QString();
6116 return impl->nodeName();
6117}
6118
6119/*!
6120 Returns the content of this processing instruction.
6121
6122 \sa setData() target()
6123*/
6124QString QDomProcessingInstruction::data() const
6125{
6126 if (!impl)
6127 return QString();
6128 return impl->nodeValue();
6129}
6130
6131/*!
6132 Sets the data contained in the processing instruction to \a d.
6133
6134 \sa data()
6135*/
6136void QDomProcessingInstruction::setData(const QString& d)
6137{
6138 if (!impl)
6139 return;
6140 impl->setNodeValue(d);
6141}
6142
6143/**************************************************************
6144 *
6145 * QDomDocumentPrivate
6146 *
6147 **************************************************************/
6148
6149QDomDocumentPrivate::QDomDocumentPrivate()
6150 : QDomNodePrivate(0),
6151 impl(new QDomImplementationPrivate),
6152 nodeListTime(1)
6153{
6154 type = new QDomDocumentTypePrivate(this, this);
6155 type->ref.deref();
6156
6157 name = QLatin1String("#document");
6158}
6159
6160QDomDocumentPrivate::QDomDocumentPrivate(const QString& aname)
6161 : QDomNodePrivate(0),
6162 impl(new QDomImplementationPrivate),
6163 nodeListTime(1)
6164{
6165 type = new QDomDocumentTypePrivate(this, this);
6166 type->ref.deref();
6167 type->name = aname;
6168
6169 name = QLatin1String("#document");
6170}
6171
6172QDomDocumentPrivate::QDomDocumentPrivate(QDomDocumentTypePrivate* dt)
6173 : QDomNodePrivate(0),
6174 impl(new QDomImplementationPrivate),
6175 nodeListTime(1)
6176{
6177 if (dt != 0) {
6178 type = dt;
6179 } else {
6180 type = new QDomDocumentTypePrivate(this, this);
6181 type->ref.deref();
6182 }
6183
6184 name = QLatin1String("#document");
6185}
6186
6187QDomDocumentPrivate::QDomDocumentPrivate(QDomDocumentPrivate* n, bool deep)
6188 : QDomNodePrivate(n, deep),
6189 impl(n->impl->clone()),
6190 nodeListTime(1)
6191{
6192 type = static_cast<QDomDocumentTypePrivate*>(n->type->cloneNode());
6193 type->setParent(this);
6194}
6195
6196QDomDocumentPrivate::~QDomDocumentPrivate()
6197{
6198}
6199
6200void QDomDocumentPrivate::clear()
6201{
6202 impl.reset();
6203 type.reset();
6204 QDomNodePrivate::clear();
6205}
6206
6207static void initializeReader(QXmlSimpleReader &reader, bool namespaceProcessing)
6208{
6209 reader.setFeature(QLatin1String("http://xml.org/sax/features/namespaces"), namespaceProcessing);
6210 reader.setFeature(QLatin1String("http://xml.org/sax/features/namespace-prefixes"), !namespaceProcessing);
6211 reader.setFeature(QLatin1String("http://trolltech.com/xml/features/report-whitespace-only-CharData"), false); // Shouldn't change in Qt 4
6212}
6213
6214bool QDomDocumentPrivate::setContent(QXmlInputSource *source, bool namespaceProcessing, QString *errorMsg, int *errorLine, int *errorColumn)
6215{
6216 QXmlSimpleReader reader;
6217 initializeReader(reader, namespaceProcessing);
6218 return setContent(source, &reader, errorMsg, errorLine, errorColumn);
6219}
6220
6221bool QDomDocumentPrivate::setContent(QXmlInputSource *source, QXmlReader *reader, QString *errorMsg, int *errorLine, int *errorColumn)
6222{
6223 clear();
6224 impl = new QDomImplementationPrivate;
6225 type = new QDomDocumentTypePrivate(this, this);
6226 type->ref.deref();
6227
6228 bool namespaceProcessing = reader->feature(QLatin1String("http://xml.org/sax/features/namespaces"))
6229 && !reader->feature(QLatin1String("http://xml.org/sax/features/namespace-prefixes"));
6230
6231 QDomHandler hnd(this, namespaceProcessing);
6232 reader->setContentHandler(&hnd);
6233 reader->setErrorHandler(&hnd);
6234 reader->setLexicalHandler(&hnd);
6235 reader->setDeclHandler(&hnd);
6236 reader->setDTDHandler(&hnd);
6237
6238 if (!reader->parse(source)) {
6239 if (errorMsg)
6240 *errorMsg = hnd.errorMsg;
6241 if (errorLine)
6242 *errorLine = hnd.errorLine;
6243 if (errorColumn)
6244 *errorColumn = hnd.errorColumn;
6245 return false;
6246 }
6247
6248 return true;
6249}
6250
6251QDomNodePrivate* QDomDocumentPrivate::cloneNode(bool deep)
6252{
6253 QDomNodePrivate *p = new QDomDocumentPrivate(this, deep);
6254 // We are not interested in this node
6255 p->ref.deref();
6256 return p;
6257}
6258
6259QDomElementPrivate* QDomDocumentPrivate::documentElement()
6260{
6261 QDomNodePrivate *p = first;
6262 while (p && !p->isElement())
6263 p = p->next;
6264
6265 return static_cast<QDomElementPrivate *>(p);
6266}
6267
6268QDomElementPrivate* QDomDocumentPrivate::createElement(const QString &tagName)
6269{
6270 bool ok;
6271 QString fixedName = fixedXmlName(tagName, &ok);
6272 if (!ok)
6273 return 0;
6274
6275 QDomElementPrivate *e = new QDomElementPrivate(this, 0, fixedName);
6276 e->ref.deref();
6277 return e;
6278}
6279
6280QDomElementPrivate* QDomDocumentPrivate::createElementNS(const QString &nsURI, const QString &qName)
6281{
6282 bool ok;
6283 QString fixedName = fixedXmlName(qName, &ok, true);
6284 if (!ok)
6285 return 0;
6286
6287 QDomElementPrivate *e = new QDomElementPrivate(this, 0, nsURI, fixedName);
6288 e->ref.deref();
6289 return e;
6290}
6291
6292QDomDocumentFragmentPrivate* QDomDocumentPrivate::createDocumentFragment()
6293{
6294 QDomDocumentFragmentPrivate *f = new QDomDocumentFragmentPrivate(this, (QDomNodePrivate*)0);
6295 f->ref.deref();
6296 return f;
6297}
6298
6299QDomTextPrivate* QDomDocumentPrivate::createTextNode(const QString &data)
6300{
6301 bool ok;
6302 QString fixedData = fixedCharData(data, &ok);
6303 if (!ok)
6304 return 0;
6305
6306 QDomTextPrivate *t = new QDomTextPrivate(this, 0, fixedData);
6307 t->ref.deref();
6308 return t;
6309}
6310
6311QDomCommentPrivate* QDomDocumentPrivate::createComment(const QString &data)
6312{
6313 bool ok;
6314 QString fixedData = fixedComment(data, &ok);
6315 if (!ok)
6316 return 0;
6317
6318 QDomCommentPrivate *c = new QDomCommentPrivate(this, 0, fixedData);
6319 c->ref.deref();
6320 return c;
6321}
6322
6323QDomCDATASectionPrivate* QDomDocumentPrivate::createCDATASection(const QString &data)
6324{
6325 bool ok;
6326 QString fixedData = fixedCDataSection(data, &ok);
6327 if (!ok)
6328 return 0;
6329
6330 QDomCDATASectionPrivate *c = new QDomCDATASectionPrivate(this, 0, fixedData);
6331 c->ref.deref();
6332 return c;
6333}
6334
6335QDomProcessingInstructionPrivate* QDomDocumentPrivate::createProcessingInstruction(const QString &target,
6336 const QString &data)
6337{
6338 bool ok;
6339 QString fixedData = fixedPIData(data, &ok);
6340 if (!ok)
6341 return 0;
6342 // [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
6343 QString fixedTarget = fixedXmlName(target, &ok);
6344 if (!ok)
6345 return 0;
6346
6347 QDomProcessingInstructionPrivate *p = new QDomProcessingInstructionPrivate(this, 0, fixedTarget, fixedData);
6348 p->ref.deref();
6349 return p;
6350}
6351QDomAttrPrivate* QDomDocumentPrivate::createAttribute(const QString &aname)
6352{
6353 bool ok;
6354 QString fixedName = fixedXmlName(aname, &ok);
6355 if (!ok)
6356 return 0;
6357
6358 QDomAttrPrivate *a = new QDomAttrPrivate(this, 0, fixedName);
6359 a->ref.deref();
6360 return a;
6361}
6362
6363QDomAttrPrivate* QDomDocumentPrivate::createAttributeNS(const QString &nsURI, const QString &qName)
6364{
6365 bool ok;
6366 QString fixedName = fixedXmlName(qName, &ok, true);
6367 if (!ok)
6368 return 0;
6369
6370 QDomAttrPrivate *a = new QDomAttrPrivate(this, 0, nsURI, fixedName);
6371 a->ref.deref();
6372 return a;
6373}
6374
6375QDomEntityReferencePrivate* QDomDocumentPrivate::createEntityReference(const QString &aname)
6376{
6377 bool ok;
6378 QString fixedName = fixedXmlName(aname, &ok);
6379 if (!ok)
6380 return 0;
6381
6382 QDomEntityReferencePrivate *e = new QDomEntityReferencePrivate(this, 0, fixedName);
6383 e->ref.deref();
6384 return e;
6385}
6386
6387QDomNodePrivate* QDomDocumentPrivate::importNode(const QDomNodePrivate *importedNode, bool deep)
6388{
6389 QDomNodePrivate *node = 0;
6390 switch (importedNode->nodeType()) {
6391 case QDomNode::AttributeNode:
6392 node = new QDomAttrPrivate((QDomAttrPrivate*)importedNode, true);
6393 break;
6394 case QDomNode::DocumentFragmentNode:
6395 node = new QDomDocumentFragmentPrivate((QDomDocumentFragmentPrivate*)importedNode, deep);
6396 break;
6397 case QDomNode::ElementNode:
6398 node = new QDomElementPrivate((QDomElementPrivate*)importedNode, deep);
6399 break;
6400 case QDomNode::EntityNode:
6401 node = new QDomEntityPrivate((QDomEntityPrivate*)importedNode, deep);
6402 break;
6403 case QDomNode::EntityReferenceNode:
6404 node = new QDomEntityReferencePrivate((QDomEntityReferencePrivate*)importedNode, false);
6405 break;
6406 case QDomNode::NotationNode:
6407 node = new QDomNotationPrivate((QDomNotationPrivate*)importedNode, deep);
6408 break;
6409 case QDomNode::ProcessingInstructionNode:
6410 node = new QDomProcessingInstructionPrivate((QDomProcessingInstructionPrivate*)importedNode, deep);
6411 break;
6412 case QDomNode::TextNode:
6413 node = new QDomTextPrivate((QDomTextPrivate*)importedNode, deep);
6414 break;
6415 case QDomNode::CDATASectionNode:
6416 node = new QDomCDATASectionPrivate((QDomCDATASectionPrivate*)importedNode, deep);
6417 break;
6418 case QDomNode::CommentNode:
6419 node = new QDomCommentPrivate((QDomCommentPrivate*)importedNode, deep);
6420 break;
6421 default:
6422 break;
6423 }
6424 if (node) {
6425 node->setOwnerDocument(this);
6426 // The QDomNode constructor increases the refcount, so deref first to
6427 // keep refcount balanced.
6428 node->ref.deref();
6429 }
6430 return node;
6431}
6432
6433void QDomDocumentPrivate::saveDocument(QTextStream& s, const int indent, QDomNode::EncodingPolicy encUsed) const
6434{
6435 const QDomNodePrivate* n = first;
6436
6437 if(encUsed == QDomNode::EncodingFromDocument) {
6438#ifndef QT_NO_TEXTCODEC
6439 const QDomNodePrivate* n = first;
6440
6441 QTextCodec *codec = 0;
6442
6443 if (n && n->isProcessingInstruction() && n->nodeName() == QLatin1String("xml")) {
6444 // we have an XML declaration
6445 QString data = n->nodeValue();
6446 QRegExp encoding(QString::fromLatin1("encoding\\s*=\\s*((\"([^\"]*)\")|('([^']*)'))"));
6447 encoding.indexIn(data);
6448 QString enc = encoding.cap(3);
6449 if (enc.isEmpty())
6450 enc = encoding.cap(5);
6451 if (!enc.isEmpty())
6452 codec = QTextCodec::codecForName(enc.toLatin1().data());
6453 }
6454 if (!codec)
6455 codec = QTextCodec::codecForName("UTF-8");
6456 if (codec)
6457 s.setCodec(codec);
6458#endif
6459 bool doc = false;
6460
6461 while (n) {
6462 if (!doc && !(n->isProcessingInstruction() && n->nodeName() == QLatin1String("xml"))) {
6463 // save doctype after XML declaration
6464 type->save(s, 0, indent);
6465 doc = true;
6466 }
6467 n->save(s, 0, indent);
6468 n = n->next;
6469 }
6470 }
6471 else {
6472
6473 // Write out the XML declaration.
6474#ifdef QT_NO_TEXTCODEC
6475 const QLatin1String codecName("iso-8859-1");
6476#else
6477 const QTextCodec *const codec = s.codec();
6478 Q_ASSERT_X(codec, "QDomNode::save()", "A codec must be specified in the text stream.");
6479 const QByteArray codecName = codec->name();
6480#endif
6481
6482 s << "<?xml version=\"1.0\" encoding=\""
6483 << codecName
6484 << "\"?>\n";
6485
6486 // Skip the first processing instruction by name "xml", if any such exists.
6487 const QDomNodePrivate* startNode = n;
6488
6489 // First, we try to find the PI and sets the startNode to the one appearing after it.
6490 while (n) {
6491 if(n->isProcessingInstruction() && n->nodeName() == QLatin1String("xml")) {
6492 startNode = n->next;
6493 break;
6494 }
6495 else
6496 n = n->next;
6497 }
6498
6499 // Now we serialize all the nodes after the faked XML declaration(the PI).
6500 while(startNode) {
6501 startNode->save(s, 0, indent);
6502 startNode = startNode->next;
6503 }
6504 }
6505}
6506
6507/**************************************************************
6508 *
6509 * QDomDocument
6510 *
6511 **************************************************************/
6512
6513#define IMPL ((QDomDocumentPrivate*)impl)
6514
6515/*!
6516 \class QDomDocument
6517 \reentrant
6518 \brief The QDomDocument class represents an XML document.
6519
6520 \inmodule QtXml
6521
6522 \ingroup xml-tools
6523
6524 The QDomDocument class represents the entire XML document.
6525 Conceptually, it is the root of the document tree, and provides
6526 the primary access to the document's data.
6527
6528 Since elements, text nodes, comments, processing instructions,
6529 etc., cannot exist outside the context of a document, the document
6530 class also contains the factory functions needed to create these
6531 objects. The node objects created have an ownerDocument() function
6532 which associates them with the document within whose context they
6533 were created. The DOM classes that will be used most often are
6534 QDomNode, QDomDocument, QDomElement and QDomText.
6535
6536 The parsed XML is represented internally by a tree of objects that
6537 can be accessed using the various QDom classes. All QDom classes
6538 only \e reference objects in the internal tree. The internal
6539 objects in the DOM tree will get deleted once the last QDom
6540 object referencing them and the QDomDocument itself are deleted.
6541
6542 Creation of elements, text nodes, etc. is done using the various
6543 factory functions provided in this class. Using the default
6544 constructors of the QDom classes will only result in empty
6545 objects that cannot be manipulated or inserted into the Document.
6546
6547 The QDomDocument class has several functions for creating document
6548 data, for example, createElement(), createTextNode(),
6549 createComment(), createCDATASection(),
6550 createProcessingInstruction(), createAttribute() and
6551 createEntityReference(). Some of these functions have versions
6552 that support namespaces, i.e. createElementNS() and
6553 createAttributeNS(). The createDocumentFragment() function is used
6554 to hold parts of the document; this is useful for manipulating for
6555 complex documents.
6556
6557 The entire content of the document is set with setContent(). This
6558 function parses the string it is passed as an XML document and
6559 creates the DOM tree that represents the document. The root
6560 element is available using documentElement(). The textual
6561 representation of the document can be obtained using toString().
6562
6563 It is possible to insert a node from another document into the
6564 document using importNode().
6565
6566 You can obtain a list of all the elements that have a particular
6567 tag with elementsByTagName() or with elementsByTagNameNS().
6568
6569 The QDom classes are typically used as follows:
6570 \snippet doc/src/snippets/code/src_xml_dom_qdom.cpp 16
6571
6572 Once \c doc and \c elem go out of scope, the whole internal tree
6573 representing the XML document is deleted.
6574
6575 To create a document using DOM use code like this:
6576 \snippet doc/src/snippets/code/src_xml_dom_qdom.cpp 17
6577
6578 For further information about the Document Object Model see
6579 the Document Object Model (DOM)
6580 \l{http://www.w3.org/TR/REC-DOM-Level-1/}{Level 1} and
6581 \l{http://www.w3.org/TR/DOM-Level-2-Core/}{Level 2 Core}
6582 Specifications.
6583
6584 \sa {DOM Bookmarks Example}, {Simple DOM Model Example}
6585*/
6586
6587
6588/*!
6589 Constructs an empty document.
6590*/
6591QDomDocument::QDomDocument()
6592{
6593 impl = 0;
6594}
6595
6596/*!
6597 Creates a document and sets the name of the document type to \a
6598 name.
6599*/
6600QDomDocument::QDomDocument(const QString& name)
6601{
6602 // We take over ownership
6603 impl = new QDomDocumentPrivate(name);
6604}
6605
6606/*!
6607 Creates a document with the document type \a doctype.
6608
6609 \sa QDomImplementation::createDocumentType()
6610*/
6611QDomDocument::QDomDocument(const QDomDocumentType& doctype)
6612{
6613 impl = new QDomDocumentPrivate((QDomDocumentTypePrivate*)(doctype.impl));
6614}
6615
6616/*!
6617 Constructs a copy of \a x.
6618
6619 The data of the copy is shared (shallow copy): modifying one node
6620 will also change the other. If you want to make a deep copy, use
6621 cloneNode().
6622*/
6623QDomDocument::QDomDocument(const QDomDocument& x)
6624 : QDomNode(x)
6625{
6626}
6627
6628QDomDocument::QDomDocument(QDomDocumentPrivate* x)
6629 : QDomNode(x)
6630{
6631}
6632
6633/*!
6634 Assigns \a x to this DOM document.
6635
6636 The data of the copy is shared (shallow copy): modifying one node
6637 will also change the other. If you want to make a deep copy, use
6638 cloneNode().
6639*/
6640QDomDocument& QDomDocument::operator= (const QDomDocument& x)
6641{
6642 return (QDomDocument&) QDomNode::operator=(x);
6643}
6644
6645/*!
6646 Destroys the object and frees its resources.
6647*/
6648QDomDocument::~QDomDocument()
6649{
6650}
6651
6652/*!
6653 \overload
6654
6655 This function reads the XML document from the string \a text, returning
6656 true if the content was successfully parsed; otherwise returns false.
6657 Since \a text is already a Unicode string, no encoding detection
6658 is done.
6659*/
6660bool QDomDocument::setContent(const QString& text, bool namespaceProcessing, QString *errorMsg, int *errorLine, int *errorColumn)
6661{
6662 if (!impl)
6663 impl = new QDomDocumentPrivate();
6664 QXmlInputSource source;
6665 source.setData(text);
6666 return IMPL->setContent(&source, namespaceProcessing, errorMsg, errorLine, errorColumn);
6667}
6668
6669/*!
6670 \nonreentrant
6671
6672 This function parses the XML document from the byte array \a
6673 data and sets it as the content of the document. It tries to
6674 detect the encoding of the document as required by the XML
6675 specification.
6676
6677 If \a namespaceProcessing is true, the parser recognizes
6678 namespaces in the XML file and sets the prefix name, local name
6679 and namespace URI to appropriate values. If \a namespaceProcessing
6680 is false, the parser does no namespace processing when it reads
6681 the XML file.
6682
6683 If a parse error occurs, this function returns false and the error
6684 message is placed in \c{*}\a{errorMsg}, the line number in
6685 \c{*}\a{errorLine} and the column number in \c{*}\a{errorColumn}
6686 (unless the associated pointer is set to 0); otherwise this
6687 function returns true. The various error messages are described in
6688 the QXmlParseException class documentation. Note that, if you
6689 want to display these error messages to your application's users,
6690 they will be displayed in English unless they are explicitly
6691 translated.
6692
6693 If \a namespaceProcessing is true, the function QDomNode::prefix()
6694 returns a string for all elements and attributes. It returns an
6695 empty string if the element or attribute has no prefix.
6696
6697 Text nodes consisting only of whitespace are stripped and won't
6698 appear in the QDomDocument. If this behavior is not desired,
6699 one can use the setContent() overload that allows a QXmlReader to be
6700 supplied.
6701
6702 If \a namespaceProcessing is false, the functions
6703 QDomNode::prefix(), QDomNode::localName() and
6704 QDomNode::namespaceURI() return an empty string.
6705
6706 Entity references are handled as follows:
6707 \list
6708 \o References to internal general entities and character entities occurring in the
6709 content are included. The result is a QDomText node with the references replaced
6710 by their corresponding entity values.
6711 \o References to parameter entities occurring in the internal subset are included.
6712 The result is a QDomDocumentType node which contains entity and notation declarations
6713 with the references replaced by their corresponding entity values.
6714 \o Any general parsed entity reference which is not defined in the internal subset and
6715 which occurs in the content is represented as a QDomEntityReference node.
6716 \o Any parsed entity reference which is not defined in the internal subset and which
6717 occurs outside of the content is replaced with an empty string.
6718 \o Any unparsed entity reference is replaced with an empty string.
6719 \endlist
6720
6721 \sa QDomNode::namespaceURI() QDomNode::localName()
6722 QDomNode::prefix() QString::isNull() QString::isEmpty()
6723*/
6724bool QDomDocument::setContent(const QByteArray &data, bool namespaceProcessing, QString *errorMsg, int *errorLine, int *errorColumn)
6725{
6726 if (!impl)
6727 impl = new QDomDocumentPrivate();
6728 QBuffer buf;
6729 buf.setData(data);
6730 QXmlInputSource source(&buf);
6731 return IMPL->setContent(&source, namespaceProcessing, errorMsg, errorLine, errorColumn);
6732}
6733
6734/*!
6735 \overload
6736
6737 This function reads the XML document from the IO device \a dev, returning
6738 true if the content was successfully parsed; otherwise returns false.
6739*/
6740bool QDomDocument::setContent(QIODevice* dev, bool namespaceProcessing, QString *errorMsg, int *errorLine, int *errorColumn)
6741{
6742 if (!impl)
6743 impl = new QDomDocumentPrivate();
6744 QXmlInputSource source(dev);
6745 return IMPL->setContent(&source, namespaceProcessing, errorMsg, errorLine, errorColumn);
6746}
6747
6748/*!
6749 \overload
6750 \since 4.5
6751
6752 This function reads the XML document from the QXmlInputSource \a source,
6753 returning true if the content was successfully parsed; otherwise returns false.
6754
6755*/
6756bool QDomDocument::setContent(QXmlInputSource *source, bool namespaceProcessing, QString *errorMsg, int *errorLine, int *errorColumn )
6757{
6758 if (!impl)
6759 impl = new QDomDocumentPrivate();
6760 QXmlSimpleReader reader;
6761 initializeReader(reader, namespaceProcessing);
6762 return IMPL->setContent(source, &reader, errorMsg, errorLine, errorColumn);
6763}
6764
6765/*!
6766 \overload
6767
6768 This function reads the XML document from the string \a text, returning
6769 true if the content was successfully parsed; otherwise returns false.
6770 Since \a text is already a Unicode string, no encoding detection
6771 is performed.
6772
6773 No namespace processing is performed either.
6774*/
6775bool QDomDocument::setContent(const QString& text, QString *errorMsg, int *errorLine, int *errorColumn)
6776{
6777 return setContent(text, false, errorMsg, errorLine, errorColumn);
6778}
6779
6780/*!
6781 \overload
6782
6783 This function reads the XML document from the byte array \a buffer,
6784 returning true if the content was successfully parsed; otherwise returns
6785 false.
6786
6787 No namespace processing is performed.
6788*/
6789bool QDomDocument::setContent(const QByteArray& buffer, QString *errorMsg, int *errorLine, int *errorColumn )
6790{
6791 return setContent(buffer, false, errorMsg, errorLine, errorColumn);
6792}
6793
6794/*!
6795 \overload
6796
6797 This function reads the XML document from the IO device \a dev, returning
6798 true if the content was successfully parsed; otherwise returns false.
6799
6800 No namespace processing is performed.
6801*/
6802bool QDomDocument::setContent(QIODevice* dev, QString *errorMsg, int *errorLine, int *errorColumn )
6803{
6804 return setContent(dev, false, errorMsg, errorLine, errorColumn);
6805}
6806
6807/*!
6808 \overload
6809
6810 This function reads the XML document from the QXmlInputSource \a source and
6811 parses it with the QXmlReader \a reader, returning true if the content was
6812 successfully parsed; otherwise returns false.
6813
6814 This function doesn't change the features of the \a reader. If you want to
6815 use certain features for parsing you can use this function to set up the
6816 reader appropriately.
6817
6818 \sa QXmlSimpleReader
6819*/
6820bool QDomDocument::setContent(QXmlInputSource *source, QXmlReader *reader, QString *errorMsg, int *errorLine, int *errorColumn )
6821{
6822 if (!impl)
6823 impl = new QDomDocumentPrivate();
6824 return IMPL->setContent(source, reader, errorMsg, errorLine, errorColumn);
6825}
6826
6827/*!
6828 Converts the parsed document back to its textual representation.
6829
6830 This function uses \a indent as the amount of space to indent
6831 subelements.
6832
6833 If \a indent is -1, no whitespace at all is added.
6834*/
6835QString QDomDocument::toString(int indent) const
6836{
6837 QString str;
6838 QTextStream s(&str, QIODevice::WriteOnly);
6839 save(s, indent);
6840 return str;
6841}
6842
6843/*!
6844 Converts the parsed document back to its textual representation
6845 and returns a QByteArray containing the data encoded as UTF-8.
6846
6847 This function uses \a indent as the amount of space to indent
6848 subelements.
6849
6850 \sa toString()
6851*/
6852QByteArray QDomDocument::toByteArray(int indent) const
6853{
6854 // ### if there is an encoding specified in the xml declaration, this
6855 // encoding declaration should be changed to utf8
6856 return toString(indent).toUtf8();
6857}
6858
6859
6860/*!
6861 Returns the document type of this document.
6862*/
6863QDomDocumentType QDomDocument::doctype() const
6864{
6865 if (!impl)
6866 return QDomDocumentType();
6867 return QDomDocumentType(IMPL->doctype());
6868}
6869
6870/*!
6871 Returns a QDomImplementation object.
6872*/
6873QDomImplementation QDomDocument::implementation() const
6874{
6875 if (!impl)
6876 return QDomImplementation();
6877 return QDomImplementation(IMPL->implementation());
6878}
6879
6880/*!
6881 Returns the root element of the document.
6882*/
6883QDomElement QDomDocument::documentElement() const
6884{
6885 if (!impl)
6886 return QDomElement();
6887 return QDomElement(IMPL->documentElement());
6888}
6889
6890/*!
6891 Creates a new element called \a tagName that can be inserted into
6892 the DOM tree, e.g. using QDomNode::appendChild().
6893
6894 If \a tagName is not a valid XML name, the behavior of this function is governed
6895 by QDomImplementation::InvalidDataPolicy.
6896
6897 \sa createElementNS() QDomNode::appendChild() QDomNode::insertBefore()
6898 QDomNode::insertAfter()
6899*/
6900QDomElement QDomDocument::createElement(const QString& tagName)
6901{
6902 if (!impl)
6903 impl = new QDomDocumentPrivate();
6904 return QDomElement(IMPL->createElement(tagName));
6905}
6906
6907/*!
6908 Creates a new document fragment, that can be used to hold parts of
6909 the document, e.g. when doing complex manipulations of the
6910 document tree.
6911*/
6912QDomDocumentFragment QDomDocument::createDocumentFragment()
6913{
6914 if (!impl)
6915 impl = new QDomDocumentPrivate();
6916 return QDomDocumentFragment(IMPL->createDocumentFragment());
6917}
6918
6919/*!
6920 Creates a text node for the string \a value that can be inserted
6921 into the document tree, e.g. using QDomNode::appendChild().
6922
6923 If \a value contains characters which cannot be stored as character
6924 data of an XML document (even in the form of character references), the
6925 behavior of this function is governed by QDomImplementation::InvalidDataPolicy.
6926
6927 \sa QDomNode::appendChild() QDomNode::insertBefore() QDomNode::insertAfter()
6928*/
6929QDomText QDomDocument::createTextNode(const QString& value)
6930{
6931 if (!impl)
6932 impl = new QDomDocumentPrivate();
6933 return QDomText(IMPL->createTextNode(value));
6934}
6935
6936/*!
6937 Creates a new comment for the string \a value that can be inserted
6938 into the document, e.g. using QDomNode::appendChild().
6939
6940 If \a value contains characters which cannot be stored in an XML comment,
6941 the behavior of this function is governed by QDomImplementation::InvalidDataPolicy.
6942
6943 \sa QDomNode::appendChild() QDomNode::insertBefore() QDomNode::insertAfter()
6944*/
6945QDomComment QDomDocument::createComment(const QString& value)
6946{
6947 if (!impl)
6948 impl = new QDomDocumentPrivate();
6949 return QDomComment(IMPL->createComment(value));
6950}
6951
6952/*!
6953 Creates a new CDATA section for the string \a value that can be
6954 inserted into the document, e.g. using QDomNode::appendChild().
6955
6956 If \a value contains characters which cannot be stored in a CDATA section,
6957 the behavior of this function is governed by
6958 QDomImplementation::InvalidDataPolicy.
6959
6960 \sa QDomNode::appendChild() QDomNode::insertBefore() QDomNode::insertAfter()
6961*/
6962QDomCDATASection QDomDocument::createCDATASection(const QString& value)
6963{
6964 if (!impl)
6965 impl = new QDomDocumentPrivate();
6966 return QDomCDATASection(IMPL->createCDATASection(value));
6967}
6968
6969/*!
6970 Creates a new processing instruction that can be inserted into the
6971 document, e.g. using QDomNode::appendChild(). This function sets
6972 the target for the processing instruction to \a target and the
6973 data to \a data.
6974
6975 If \a target is not a valid XML name, or data if contains characters which cannot
6976 appear in a processing instruction, the behavior of this function is governed by
6977 QDomImplementation::InvalidDataPolicy.
6978
6979 \sa QDomNode::appendChild() QDomNode::insertBefore() QDomNode::insertAfter()
6980*/
6981QDomProcessingInstruction QDomDocument::createProcessingInstruction(const QString& target,
6982 const QString& data)
6983{
6984 if (!impl)
6985 impl = new QDomDocumentPrivate();
6986 return QDomProcessingInstruction(IMPL->createProcessingInstruction(target, data));
6987}
6988
6989
6990/*!
6991 Creates a new attribute called \a name that can be inserted into
6992 an element, e.g. using QDomElement::setAttributeNode().
6993
6994 If \a name is not a valid XML name, the behavior of this function is governed by
6995 QDomImplementation::InvalidDataPolicy.
6996
6997 \sa createAttributeNS()
6998*/
6999QDomAttr QDomDocument::createAttribute(const QString& name)
7000{
7001 if (!impl)
7002 impl = new QDomDocumentPrivate();
7003 return QDomAttr(IMPL->createAttribute(name));
7004}
7005
7006/*!
7007 Creates a new entity reference called \a name that can be inserted
7008 into the document, e.g. using QDomNode::appendChild().
7009
7010 If \a name is not a valid XML name, the behavior of this function is governed by
7011 QDomImplementation::InvalidDataPolicy.
7012
7013 \sa QDomNode::appendChild() QDomNode::insertBefore() QDomNode::insertAfter()
7014*/
7015QDomEntityReference QDomDocument::createEntityReference(const QString& name)
7016{
7017 if (!impl)
7018 impl = new QDomDocumentPrivate();
7019 return QDomEntityReference(IMPL->createEntityReference(name));
7020}
7021
7022/*!
7023 Returns a QDomNodeList, that contains all the elements in the
7024 document with the name \a tagname. The order of the node list is
7025 the order they are encountered in a preorder traversal of the
7026 element tree.
7027
7028 \sa elementsByTagNameNS() QDomElement::elementsByTagName()
7029*/
7030QDomNodeList QDomDocument::elementsByTagName(const QString& tagname) const
7031{
7032 return QDomNodeList(new QDomNodeListPrivate(impl, tagname));
7033}
7034
7035/*!
7036 Imports the node \a importedNode from another document to this
7037 document. \a importedNode remains in the original document; this
7038 function creates a copy that can be used within this document.
7039
7040 This function returns the imported node that belongs to this
7041 document. The returned node has no parent. It is not possible to
7042 import QDomDocument and QDomDocumentType nodes. In those cases
7043 this function returns a \link QDomNode::isNull() null node\endlink.
7044
7045 If \a deep is true, this function imports not only the node \a
7046 importedNode but its whole subtree; if it is false, only the \a
7047 importedNode is imported. The argument \a deep has no effect on
7048 QDomAttr and QDomEntityReference nodes, since the descendants of
7049 QDomAttr nodes are always imported and those of
7050 QDomEntityReference nodes are never imported.
7051
7052 The behavior of this function is slightly different depending on
7053 the node types:
7054 \table
7055 \header \i Node Type \i Behavior
7056 \row \i QDomAttr
7057 \i The owner element is set to 0 and the specified flag is
7058 set to true in the generated attribute. The whole subtree
7059 of \a importedNode is always imported for attribute nodes:
7060 \a deep has no effect.
7061 \row \i QDomDocument
7062 \i Document nodes cannot be imported.
7063 \row \i QDomDocumentFragment
7064 \i If \a deep is true, this function imports the whole
7065 document fragment; otherwise it only generates an empty
7066 document fragment.
7067 \row \i QDomDocumentType
7068 \i Document type nodes cannot be imported.
7069 \row \i QDomElement
7070 \i Attributes for which QDomAttr::specified() is true are
7071 also imported, other attributes are not imported. If \a
7072 deep is true, this function also imports the subtree of \a
7073 importedNode; otherwise it imports only the element node
7074 (and some attributes, see above).
7075 \row \i QDomEntity
7076 \i Entity nodes can be imported, but at the moment there is
7077 no way to use them since the document type is read-only in
7078 DOM level 2.
7079 \row \i QDomEntityReference
7080 \i Descendants of entity reference nodes are never imported:
7081 \a deep has no effect.
7082 \row \i QDomNotation
7083 \i Notation nodes can be imported, but at the moment there is
7084 no way to use them since the document type is read-only in
7085 DOM level 2.
7086 \row \i QDomProcessingInstruction
7087 \i The target and value of the processing instruction is
7088 copied to the new node.
7089 \row \i QDomText
7090 \i The text is copied to the new node.
7091 \row \i QDomCDATASection
7092 \i The text is copied to the new node.
7093 \row \i QDomComment
7094 \i The text is copied to the new node.
7095 \endtable
7096
7097 \sa QDomElement::setAttribute() QDomNode::insertBefore()
7098 QDomNode::insertAfter() QDomNode::replaceChild() QDomNode::removeChild()
7099 QDomNode::appendChild()
7100*/
7101QDomNode QDomDocument::importNode(const QDomNode& importedNode, bool deep)
7102{
7103 if (!impl)
7104 impl = new QDomDocumentPrivate();
7105 return QDomNode(IMPL->importNode(importedNode.impl, deep));
7106}
7107
7108/*!
7109 Creates a new element with namespace support that can be inserted
7110 into the DOM tree. The name of the element is \a qName and the
7111 namespace URI is \a nsURI. This function also sets
7112 QDomNode::prefix() and QDomNode::localName() to appropriate values
7113 (depending on \a qName).
7114
7115 If \a qName is an empty string, returns a null element regardless of
7116 whether the invalid data policy is set.
7117
7118 \sa createElement()
7119*/
7120QDomElement QDomDocument::createElementNS(const QString& nsURI, const QString& qName)
7121{
7122 if (!impl)
7123 impl = new QDomDocumentPrivate();
7124 return QDomElement(IMPL->createElementNS(nsURI, qName));
7125}
7126
7127/*!
7128 Creates a new attribute with namespace support that can be
7129 inserted into an element. The name of the attribute is \a qName
7130 and the namespace URI is \a nsURI. This function also sets
7131 QDomNode::prefix() and QDomNode::localName() to appropriate values
7132 (depending on \a qName).
7133
7134 If \a qName is not a valid XML name, the behavior of this function is governed by
7135 QDomImplementation::InvalidDataPolicy.
7136
7137 \sa createAttribute()
7138*/
7139QDomAttr QDomDocument::createAttributeNS(const QString& nsURI, const QString& qName)
7140{
7141 if (!impl)
7142 impl = new QDomDocumentPrivate();
7143 return QDomAttr(IMPL->createAttributeNS(nsURI, qName));
7144}
7145
7146/*!
7147 Returns a QDomNodeList that contains all the elements in the
7148 document with the local name \a localName and a namespace URI of
7149 \a nsURI. The order of the node list is the order they are
7150 encountered in a preorder traversal of the element tree.
7151
7152 \sa elementsByTagName() QDomElement::elementsByTagNameNS()
7153*/
7154QDomNodeList QDomDocument::elementsByTagNameNS(const QString& nsURI, const QString& localName)
7155{
7156 return QDomNodeList(new QDomNodeListPrivate(impl, nsURI, localName));
7157}
7158
7159/*!
7160 Returns the element whose ID is equal to \a elementId. If no
7161 element with the ID was found, this function returns a \link
7162 QDomNode::isNull() null element\endlink.
7163
7164 Since the QDomClasses do not know which attributes are element
7165 IDs, this function returns always a \link QDomNode::isNull() null
7166 element\endlink. This may change in a future version.
7167*/
7168QDomElement QDomDocument::elementById(const QString& /*elementId*/)
7169{
7170 qWarning("elementById() is not implemented and will always return a null node.");
7171 return QDomElement();
7172}
7173
7174/*!
7175 \fn QDomNode::NodeType QDomDocument::nodeType() const
7176
7177 Returns \c DocumentNode.
7178*/
7179
7180#undef IMPL
7181
7182/**************************************************************
7183 *
7184 * Node casting functions
7185 *
7186 **************************************************************/
7187
7188/*!
7189 Converts a QDomNode into a QDomAttr. If the node is not an
7190 attribute, the returned object will be \link QDomNode::isNull()
7191 null\endlink.
7192
7193 \sa isAttr()
7194*/
7195QDomAttr QDomNode::toAttr() const
7196{
7197 if (impl && impl->isAttr())
7198 return QDomAttr(((QDomAttrPrivate*)impl));
7199 return QDomAttr();
7200}
7201
7202/*!
7203 Converts a QDomNode into a QDomCDATASection. If the node is not a
7204 CDATA section, the returned object will be \link
7205 QDomNode::isNull() null\endlink.
7206
7207 \sa isCDATASection()
7208*/
7209QDomCDATASection QDomNode::toCDATASection() const
7210{
7211 if (impl && impl->isCDATASection())
7212 return QDomCDATASection(((QDomCDATASectionPrivate*)impl));
7213 return QDomCDATASection();
7214}
7215
7216/*!
7217 Converts a QDomNode into a QDomDocumentFragment. If the node is
7218 not a document fragment the returned object will be \link
7219 QDomNode::isNull() null\endlink.
7220
7221 \sa isDocumentFragment()
7222*/
7223QDomDocumentFragment QDomNode::toDocumentFragment() const
7224{
7225 if (impl && impl->isDocumentFragment())
7226 return QDomDocumentFragment(((QDomDocumentFragmentPrivate*)impl));
7227 return QDomDocumentFragment();
7228}
7229
7230/*!
7231 Converts a QDomNode into a QDomDocument. If the node is not a
7232 document the returned object will be \link QDomNode::isNull()
7233 null\endlink.
7234
7235 \sa isDocument()
7236*/
7237QDomDocument QDomNode::toDocument() const
7238{
7239 if (impl && impl->isDocument())
7240 return QDomDocument(((QDomDocumentPrivate*)impl));
7241 return QDomDocument();
7242}
7243
7244/*!
7245 Converts a QDomNode into a QDomDocumentType. If the node is not a
7246 document type the returned object will be \link QDomNode::isNull()
7247 null\endlink.
7248
7249 \sa isDocumentType()
7250*/
7251QDomDocumentType QDomNode::toDocumentType() const
7252{
7253 if (impl && impl->isDocumentType())
7254 return QDomDocumentType(((QDomDocumentTypePrivate*)impl));
7255 return QDomDocumentType();
7256}
7257
7258/*!
7259 Converts a QDomNode into a QDomElement. If the node is not an
7260 element the returned object will be \link QDomNode::isNull()
7261 null\endlink.
7262
7263 \sa isElement()
7264*/
7265QDomElement QDomNode::toElement() const
7266{
7267 if (impl && impl->isElement())
7268 return QDomElement(((QDomElementPrivate*)impl));
7269 return QDomElement();
7270}
7271
7272/*!
7273 Converts a QDomNode into a QDomEntityReference. If the node is not
7274 an entity reference, the returned object will be \link
7275 QDomNode::isNull() null\endlink.
7276
7277 \sa isEntityReference()
7278*/
7279QDomEntityReference QDomNode::toEntityReference() const
7280{
7281 if (impl && impl->isEntityReference())
7282 return QDomEntityReference(((QDomEntityReferencePrivate*)impl));
7283 return QDomEntityReference();
7284}
7285
7286/*!
7287 Converts a QDomNode into a QDomText. If the node is not a text,
7288 the returned object will be \link QDomNode::isNull() null\endlink.
7289
7290 \sa isText()
7291*/
7292QDomText QDomNode::toText() const
7293{
7294 if (impl && impl->isText())
7295 return QDomText(((QDomTextPrivate*)impl));
7296 return QDomText();
7297}
7298
7299/*!
7300 Converts a QDomNode into a QDomEntity. If the node is not an
7301 entity the returned object will be \link QDomNode::isNull()
7302 null\endlink.
7303
7304 \sa isEntity()
7305*/
7306QDomEntity QDomNode::toEntity() const
7307{
7308 if (impl && impl->isEntity())
7309 return QDomEntity(((QDomEntityPrivate*)impl));
7310 return QDomEntity();
7311}
7312
7313/*!
7314 Converts a QDomNode into a QDomNotation. If the node is not a
7315 notation the returned object will be \link QDomNode::isNull()
7316 null\endlink.
7317
7318 \sa isNotation()
7319*/
7320QDomNotation QDomNode::toNotation() const
7321{
7322 if (impl && impl->isNotation())
7323 return QDomNotation(((QDomNotationPrivate*)impl));
7324 return QDomNotation();
7325}
7326
7327/*!
7328 Converts a QDomNode into a QDomProcessingInstruction. If the node
7329 is not a processing instruction the returned object will be \link
7330 QDomNode::isNull() null\endlink.
7331
7332 \sa isProcessingInstruction()
7333*/
7334QDomProcessingInstruction QDomNode::toProcessingInstruction() const
7335{
7336 if (impl && impl->isProcessingInstruction())
7337 return QDomProcessingInstruction(((QDomProcessingInstructionPrivate*)impl));
7338 return QDomProcessingInstruction();
7339}
7340
7341/*!
7342 Converts a QDomNode into a QDomCharacterData. If the node is not a
7343 character data node the returned object will be \link
7344 QDomNode::isNull() null\endlink.
7345
7346 \sa isCharacterData()
7347*/
7348QDomCharacterData QDomNode::toCharacterData() const
7349{
7350 if (impl && impl->isCharacterData())
7351 return QDomCharacterData(((QDomCharacterDataPrivate*)impl));
7352 return QDomCharacterData();
7353}
7354
7355/*!
7356 Converts a QDomNode into a QDomComment. If the node is not a
7357 comment the returned object will be \link QDomNode::isNull()
7358 null\endlink.
7359
7360 \sa isComment()
7361*/
7362QDomComment QDomNode::toComment() const
7363{
7364 if (impl && impl->isComment())
7365 return QDomComment(((QDomCommentPrivate*)impl));
7366 return QDomComment();
7367}
7368
7369/**************************************************************
7370 *
7371 * QDomHandler
7372 *
7373 **************************************************************/
7374
7375QDomHandler::QDomHandler(QDomDocumentPrivate* adoc, bool namespaceProcessing)
7376 : errorLine(0), errorColumn(0), doc(adoc), node(adoc), cdata(false),
7377 nsProcessing(namespaceProcessing), locator(0)
7378{
7379}
7380
7381QDomHandler::~QDomHandler()
7382{
7383}
7384
7385bool QDomHandler::endDocument()
7386{
7387 // ### is this really necessary? (rms)
7388 if (node != doc)
7389 return false;
7390 return true;
7391}
7392
7393bool QDomHandler::startDTD(const QString& name, const QString& publicId, const QString& systemId)
7394{
7395 doc->doctype()->name = name;
7396 doc->doctype()->publicId = publicId;
7397 doc->doctype()->systemId = systemId;
7398 return true;
7399}
7400
7401bool QDomHandler::startElement(const QString& nsURI, const QString&, const QString& qName, const QXmlAttributes& atts)
7402{
7403 // tag name
7404 QDomNodePrivate* n;
7405 if (nsProcessing) {
7406 n = doc->createElementNS(nsURI, qName);
7407 } else {
7408 n = doc->createElement(qName);
7409 }
7410
7411 if (n)
7412 n->setLocation(locator->lineNumber(), locator->columnNumber());
7413
7414 node->appendChild(n);
7415 node = n;
7416
7417 // attributes
7418 for (int i=0; i<atts.length(); i++)
7419 {
7420 if (nsProcessing) {
7421 ((QDomElementPrivate*)node)->setAttributeNS(atts.uri(i), atts.qName(i), atts.value(i));
7422 } else {
7423 ((QDomElementPrivate*)node)->setAttribute(atts.qName(i), atts.value(i));
7424 }
7425 }
7426
7427 return true;
7428}
7429
7430bool QDomHandler::endElement(const QString&, const QString&, const QString&)
7431{
7432 if (!node || node == doc)
7433 return false;
7434 node = node->parent();
7435
7436 return true;
7437}
7438
7439bool QDomHandler::characters(const QString& ch)
7440{
7441 // No text as child of some document
7442 if (node == doc)
7443 return false;
7444
7445 QScopedPointer<QDomNodePrivate> n;
7446 if (cdata) {
7447 n.reset(doc->createCDATASection(ch));
7448 } else if (!entityName.isEmpty()) {
7449 QScopedPointer<QDomEntityPrivate> e(new QDomEntityPrivate(doc, 0, entityName,
7450 QString(), QString(), QString()));
7451 e->value = ch;
7452 doc->doctype()->appendChild(e.data());
7453 e.take();
7454 n.reset(doc->createEntityReference(entityName));
7455 } else {
7456 n.reset(doc->createTextNode(ch));
7457 }
7458 n->setLocation(locator->lineNumber(), locator->columnNumber());
7459 node->appendChild(n.data());
7460 n.take();
7461
7462 return true;
7463}
7464
7465bool QDomHandler::processingInstruction(const QString& target, const QString& data)
7466{
7467 QDomNodePrivate *n;
7468 n = doc->createProcessingInstruction(target, data);
7469 if (n) {
7470 n->setLocation(locator->lineNumber(), locator->columnNumber());
7471 node->appendChild(n);
7472 return true;
7473 }
7474 else
7475 return false;
7476}
7477
7478extern bool qt_xml_skipped_entity_in_content;
7479bool QDomHandler::skippedEntity(const QString& name)
7480{
7481 // we can only handle inserting entity references into content
7482 if (!qt_xml_skipped_entity_in_content)
7483 return true;
7484
7485 QDomNodePrivate *n = doc->createEntityReference(name);
7486 n->setLocation(locator->lineNumber(), locator->columnNumber());
7487 node->appendChild(n);
7488 return true;
7489}
7490
7491bool QDomHandler::fatalError(const QXmlParseException& exception)
7492{
7493 errorMsg = exception.message();
7494 errorLine = exception.lineNumber();
7495 errorColumn = exception.columnNumber();
7496 return QXmlDefaultHandler::fatalError(exception);
7497}
7498
7499bool QDomHandler::startCDATA()
7500{
7501 cdata = true;
7502 return true;
7503}
7504
7505bool QDomHandler::endCDATA()
7506{
7507 cdata = false;
7508 return true;
7509}
7510
7511bool QDomHandler::startEntity(const QString &name)
7512{
7513 entityName = name;
7514 return true;
7515}
7516
7517bool QDomHandler::endEntity(const QString &)
7518{
7519 entityName.clear();
7520 return true;
7521}
7522
7523bool QDomHandler::comment(const QString& ch)
7524{
7525 QDomNodePrivate *n;
7526 n = doc->createComment(ch);
7527 n->setLocation(locator->lineNumber(), locator->columnNumber());
7528 node->appendChild(n);
7529 return true;
7530}
7531
7532bool QDomHandler::unparsedEntityDecl(const QString &name, const QString &publicId, const QString &systemId, const QString &notationName)
7533{
7534 QDomEntityPrivate* e = new QDomEntityPrivate(doc, 0, name,
7535 publicId, systemId, notationName);
7536 doc->doctype()->appendChild(e);
7537 return true;
7538}
7539
7540bool QDomHandler::externalEntityDecl(const QString &name, const QString &publicId, const QString &systemId)
7541{
7542 return unparsedEntityDecl(name, publicId, systemId, QString());
7543}
7544
7545bool QDomHandler::notationDecl(const QString & name, const QString & publicId, const QString & systemId)
7546{
7547 QDomNotationPrivate* n = new QDomNotationPrivate(doc, 0, name, publicId, systemId);
7548 doc->doctype()->appendChild(n);
7549 return true;
7550}
7551
7552void QDomHandler::setDocumentLocator(QXmlLocator *locator)
7553{
7554 this->locator = locator;
7555}
7556
7557QT_END_NAMESPACE
7558
7559#endif // QT_NO_DOM
Note: See TracBrowser for help on using the repository browser.