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

Last change on this file since 769 was 769, checked in by Dmitry A. Kuminov, 15 years ago

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

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