source: trunk/src/xml/dom/qdom.cpp@ 1147

Last change on this file since 1147 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

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