|
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 test suite of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
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 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #ifndef PatternistSDK_XMLWriter_H |
|
43 #define PatternistSDK_XMLWriter_H |
|
44 |
|
45 #include "Global.h" |
|
46 |
|
47 #include <QtXml/QXmlContentHandler> |
|
48 #include <QtXml/QXmlLexicalHandler> |
|
49 |
|
50 QT_BEGIN_HEADER |
|
51 |
|
52 QT_BEGIN_NAMESPACE |
|
53 |
|
54 class QIODevice; |
|
55 |
|
56 namespace QPatternistSDK |
|
57 { |
|
58 /** |
|
59 * @short Serializes a stream of SAX events into XML, sent to a QIODevice. |
|
60 * |
|
61 * XMLWriter is a fast and simple XML serializer which takes care of |
|
62 * all the low level details of well-formedness and character escaping, allowing |
|
63 * the user to focus on higher level issues and increasing the chances of producing |
|
64 * valid, interoperable XML. |
|
65 * |
|
66 * The content XMLWriter produces is sent to a QIODevice, which is either |
|
67 * specified in XMLWriter's constructor or via setDevice(). If writing to |
|
68 * the device fails, the content functions such as startElement() returns @c false. |
|
69 * |
|
70 * XMLWriter sub-classes QXmlContentHandler meaning it can serialize content |
|
71 * from any code that produces SAX events. The class can also be used manually, |
|
72 * by calling startElement(), endCDATA(), and so forth. |
|
73 * |
|
74 * XMLWriter cannot be used to serialize multiple documents. One instance per |
|
75 * document must be used. |
|
76 * |
|
77 * XMLWriter takes care of escaping content into character references as necessary. Thus, |
|
78 * it should not be done manually. In fact, it would most likely |
|
79 * result in invalid XML or an unintended result. XMLWriter always serializes into UTF-8. |
|
80 * |
|
81 * When compiled in debug mode, XMLWriter contains several tests that helps |
|
82 * ensuring that XMLWriter produces valid XML. Some of these tests ensures that: |
|
83 * |
|
84 * - The @c xmlns and @c xml prefixes are used properly |
|
85 * - Content of comments and processing instructions is valid |
|
86 * - Element, attribute and DOCTYPE names are sensible |
|
87 * - Elements are properly nested and balanced |
|
88 * - To some extent that things occur in the proper order. For example, that |
|
89 * the document type definition isn't added inside an element |
|
90 * - That namespaces prefixes are declared |
|
91 * |
|
92 * Not triggering XMLWriter's tests does not guarantee valid XML is produced, |
|
93 * but they do help catching common mistakes and some of the corner cases in the |
|
94 * specifications. When XMLWriter is compiled in release mode, these tests are not enabled |
|
95 * and the error handling in effect is concerning writing to the QIODevice. |
|
96 * |
|
97 * Often it is of interest to add a note at the beginning of the file communicating |
|
98 * it is auto-generated. setMessage() and setAddMessage() provides |
|
99 * a convenient way of doing that. |
|
100 * |
|
101 * Namespace declarations are added with startPrefixMapping(), not by sending attributes |
|
102 * with name <tt>xmlns:*</tt> to startElement(). |
|
103 * |
|
104 * @see <a href="http://hsivonen.iki.fi/producing-xml/">HOWTO Avoid Being |
|
105 * Called a Bozo When Producing XML</a> |
|
106 * @see <a href="http://www.w3.org/TR/REC-xml/">Extensible Markup |
|
107 * Language (XML) 1.0 (Third Edition)</a> |
|
108 * @see <a href="http://www.w3.org/TR/REC-xml-names/">Namespaces in XML</a> |
|
109 * @todo Replace this class with QXmlStreamWriter |
|
110 * @author Frans Englich <frans.englich@nokia.com> |
|
111 * @ingroup PatternistSDK |
|
112 */ |
|
113 class Q_PATTERNISTSDK_EXPORT XMLWriter : public QXmlContentHandler |
|
114 , public QXmlLexicalHandler |
|
115 { |
|
116 public: |
|
117 /** |
|
118 * Creates a XMLWriter which serializes its received events |
|
119 * to @p outStream. |
|
120 * |
|
121 * @note XMLWriter does not claim ownership of @p outStream. Thus, |
|
122 * @p outStream may not be destroyed as long as |
|
123 * this XMLWriter instance uses it. |
|
124 */ |
|
125 XMLWriter(QIODevice *outStream = 0); |
|
126 |
|
127 virtual ~XMLWriter(); |
|
128 |
|
129 /** |
|
130 * @returns @c true if opening the output device succeeds, otherwise @c false |
|
131 */ |
|
132 virtual bool startDocument(); |
|
133 |
|
134 /** |
|
135 * @returns @c false if failure occurs in writing to the QIODevice, otherwise |
|
136 * @c true |
|
137 */ |
|
138 virtual bool characters(const QString &ch); |
|
139 |
|
140 /** |
|
141 * Starts an element with name @p qName and attributes @p atts. The prefix |
|
142 * in @p qName must first be declared with startPrefixMapping(), if it has one. |
|
143 * |
|
144 * A call to startElement() must always at some point be balanced with a call |
|
145 * to endElement(). |
|
146 * |
|
147 * To declare namespaces, don't put attributes with name <tt>xmlns:*</tt> in @p atts, |
|
148 * but use startPrefixMapping(). |
|
149 */ |
|
150 virtual bool startElement(const QString &qName, const QXmlAttributes &atts = QXmlAttributes()); |
|
151 |
|
152 /** |
|
153 * |
|
154 * Behaves essentially as startElement(const QString &qName, const QXmlAttributes &atts). This |
|
155 * function is used in conjunction with other SAX classes. |
|
156 * |
|
157 * The call: |
|
158 * |
|
159 * @code |
|
160 * startElement(QString(), QString(), qName, atts); |
|
161 * @endcode |
|
162 * |
|
163 * is equivalent to: |
|
164 * |
|
165 * @code |
|
166 * startElement(qName, atts); |
|
167 * @endcode |
|
168 * |
|
169 * @p namespaceURI and @p localName are not used. This function is |
|
170 * used in conjunction with other SAX classes. |
|
171 * |
|
172 * @returns @c false if failure occurs in writing to the QIODevice, otherwise |
|
173 * @c true |
|
174 */ |
|
175 virtual bool startElement(const QString &namespaceURI, |
|
176 const QString &localName, |
|
177 const QString &qName, |
|
178 const QXmlAttributes &atts); |
|
179 |
|
180 /** |
|
181 * Signals the end of an element with name @p qName. @p qName must |
|
182 * be supplied. |
|
183 * |
|
184 * Calls to startElement() and endElement() must always be balanced. |
|
185 * |
|
186 * @returns @c false if failure occurs in writing to the QIODevice, otherwise |
|
187 * @c true |
|
188 */ |
|
189 virtual bool endElement(const QString &qName); |
|
190 |
|
191 /** |
|
192 * Behaves essentially as endElement(const QString &qName). This function |
|
193 * is used when XMLWriter is used in SAX code. |
|
194 * |
|
195 * @p namespaceURI and @p localName are not used. |
|
196 * |
|
197 * The call: |
|
198 * |
|
199 * @code |
|
200 * endElement(QString(), QString(), qName); |
|
201 * @endcode |
|
202 * |
|
203 * is equivalent to: |
|
204 * |
|
205 * @code |
|
206 * endElement(qName); |
|
207 * @endcode |
|
208 * |
|
209 * @returns @c false if failure occurs in writing to the QIODevice, otherwise |
|
210 * @c true |
|
211 */ |
|
212 virtual bool endElement(const QString &namespaceURI, |
|
213 const QString &localName, |
|
214 const QString &qName); |
|
215 |
|
216 /** |
|
217 * A description of an error if it occurred. This is typically |
|
218 * QIODevice::errorString(). If no error has occurred, an empty |
|
219 * string is returned. |
|
220 */ |
|
221 virtual QString errorString() const; |
|
222 |
|
223 /** |
|
224 * Starts a CDATA section. Content sent with characters() will not be escaped |
|
225 * except for ">" if occurring in "]]>". |
|
226 * |
|
227 * @returns @c false if failure occurs in writing to the QIODevice, otherwise |
|
228 * @c true |
|
229 */ |
|
230 virtual bool startCDATA(); |
|
231 |
|
232 /** |
|
233 * @returns @c false if failure occurs in writing to the QIODevice, otherwise |
|
234 * @c true |
|
235 */ |
|
236 virtual bool endCDATA(); |
|
237 |
|
238 /** |
|
239 * Creates a document type definition. |
|
240 * |
|
241 * For example, the code snippet: |
|
242 * |
|
243 * @code |
|
244 * writer.startDTD("html", "-//W3C//DTD XHTML 1.0 Strict//EN", |
|
245 * "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"); |
|
246 * writer.endDTD(); |
|
247 * @endcode |
|
248 * |
|
249 * would create: |
|
250 * @verbatim |
|
251 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> |
|
252 @endverbatim |
|
253 * |
|
254 * @note A system identifier must always be specified, but a public identifier may |
|
255 * be left out. |
|
256 * |
|
257 * A call to startDTD() must be followed by a call to endDTD(). |
|
258 */ |
|
259 virtual bool startDTD(const QString &name, |
|
260 const QString &publicId, |
|
261 const QString &systemId); |
|
262 |
|
263 /** |
|
264 * Apart from closing the DTD, an new line is also added at end. |
|
265 */ |
|
266 virtual bool endDTD(); |
|
267 |
|
268 /** |
|
269 * Creates a processing instruction by name @p target, and content |
|
270 * @p data. |
|
271 * |
|
272 * @returns @c false if failure occurs in writing to the QIODevice, otherwise |
|
273 * @c true |
|
274 */ |
|
275 virtual bool processingInstruction(const QString &target, |
|
276 const QString &data); |
|
277 |
|
278 /** |
|
279 * Declares a namespace which maps @p prefix to @p namespaceURI. For example, the call: |
|
280 * |
|
281 * @code |
|
282 * startPrefixMapping("xhtml", "http://www.w3.org/1999/xhtml"); |
|
283 * @endcode |
|
284 * |
|
285 * would result in: |
|
286 * |
|
287 * @code |
|
288 * xmlns="http://www.w3.org/1999/xhtml" |
|
289 * @endcode |
|
290 */ |
|
291 virtual bool startPrefixMapping(const QString &prefix, |
|
292 const QString &namespaceURI); |
|
293 |
|
294 /** |
|
295 * Creates a comment with content @p ch. @p ch is escaped, there's |
|
296 * no need to do it manually. For example, calling comment() with @p ch |
|
297 * set to "my comment", results in "<!--my comment-->" in the output. |
|
298 * |
|
299 * @note if @p ch contains double hyphen("--"), the produced XML will |
|
300 * not be well formed. |
|
301 * |
|
302 * @returns @c false if failure occurs in writing to the QIODevice, otherwise |
|
303 * @c true |
|
304 */ |
|
305 virtual bool comment(const QString &ch); |
|
306 |
|
307 virtual bool startEntity(const QString &name); |
|
308 virtual bool endEntity(const QString &name); |
|
309 |
|
310 /** |
|
311 * Sets the message which is added as a comment if addModificationMessage() |
|
312 * is set to @c true. If no message is specified and addModificationMessage() |
|
313 * is set to @c true, a default message is used. |
|
314 * |
|
315 * @see modificationMessage(), setAddMessage() |
|
316 */ |
|
317 virtual void setMessage(const QString &msg); |
|
318 |
|
319 /** |
|
320 * The message that is added at the beginning of the XML events |
|
321 * in a comment node. If no modificationMessage is set via modificationMessage(), |
|
322 * and addModificationMessage is set to @c true, this message will be used: |
|
323 * "NOTE: This file was automatically generated by [the application name] at |
|
324 * [the current date time]. All changes to this file will be lost." |
|
325 * |
|
326 * @see setMessage() |
|
327 */ |
|
328 virtual QString modificationMessage() const; |
|
329 |
|
330 /** |
|
331 * Closes the QIODevice XMLWriter writes to. |
|
332 */ |
|
333 virtual bool endDocument(); |
|
334 |
|
335 /** |
|
336 * Serializes @p ch as if it was sent to characters(). |
|
337 * |
|
338 * @returns @c false if failure occurs in writing to the QIODevice, otherwise |
|
339 * @c true |
|
340 */ |
|
341 virtual bool ignorableWhitespace(const QString &ch); |
|
342 |
|
343 /** |
|
344 * This function is not used by XMLWriter, but is implemented |
|
345 * in order to satisfy QXmlContentHandler's interface. |
|
346 */ |
|
347 virtual bool endPrefixMapping(const QString &prefix); |
|
348 |
|
349 /** |
|
350 * This function is not used by XMLWriter, but is implemented |
|
351 * in order to satisfy QXmlContentHandler's interface. |
|
352 */ |
|
353 virtual bool skippedEntity(const QString &name); |
|
354 |
|
355 /** |
|
356 * This function is not used by XMLWriter, but is implemented |
|
357 * in order to satisfy QXmlContentHandler's interface. |
|
358 */ |
|
359 virtual void setDocumentLocator(QXmlLocator *); |
|
360 |
|
361 /** |
|
362 * @returns the device XMLWriter writes its output to. |
|
363 * XMLWriter does not own the device. |
|
364 */ |
|
365 virtual QIODevice *device() const; |
|
366 |
|
367 /** |
|
368 * Sets the QIODevice XMLWriter writes to, to @p device. A device must be specified |
|
369 * either via this function or in the constructor before XMLWriter is used. |
|
370 * |
|
371 * XMLWriter does not claim ownership of @p device. |
|
372 */ |
|
373 virtual void setDevice(QIODevice *device); |
|
374 |
|
375 /** |
|
376 * Determines whether the modification message should be inserted as a comment |
|
377 * before the document element. The message returned by modificationMessage() is used. |
|
378 * |
|
379 * If @p toggle is @c true, the message will be added, otherwise not. |
|
380 */ |
|
381 virtual void setAddMessage(const bool toggle); |
|
382 |
|
383 /** |
|
384 * Tells whether a modification message will be added. |
|
385 * |
|
386 * @see setAddMessage(), modificationMessage() |
|
387 */ |
|
388 virtual bool addModificationMessage() const; |
|
389 |
|
390 private: |
|
391 Q_DISABLE_COPY(XMLWriter) |
|
392 |
|
393 class Private; |
|
394 Private *d; |
|
395 }; |
|
396 } |
|
397 |
|
398 QT_END_NAMESPACE |
|
399 |
|
400 QT_END_HEADER |
|
401 |
|
402 #endif |
|
403 // vim: et:ts=4:sw=4:sts=4 |