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

source code of qtbase/src/xml/dom/qdom.cpp