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