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