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

Last change on this file since 5 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

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