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