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