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