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

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

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