1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the test suite of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
21 | ** included in the packaging of this file. Please review the following |
22 | ** information to ensure the GNU General Public License requirements will |
23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
24 | ** |
25 | ** $QT_END_LICENSE$ |
26 | ** |
27 | ****************************************************************************/ |
28 | |
29 | #ifndef PatternistSDK_XMLWriter_H |
30 | #define PatternistSDK_XMLWriter_H |
31 | |
32 | #include "Global.h" |
33 | |
34 | #include <QXmlStreamAttributes> |
35 | |
36 | QT_BEGIN_NAMESPACE |
37 | |
38 | class QIODevice; |
39 | |
40 | namespace QPatternistSDK |
41 | { |
42 | /** |
43 | * @short Serializes a stream of SAX events into XML, sent to a QIODevice. |
44 | * |
45 | * XMLWriter is a fast and simple XML serializer which takes care of |
46 | * all the low level details of well-formedness and character escaping, allowing |
47 | * the user to focus on higher level issues and increasing the chances of producing |
48 | * valid, interoperable XML. |
49 | * |
50 | * The content XMLWriter produces is sent to a QIODevice, which is either |
51 | * specified in XMLWriter's constructor or via setDevice(). If writing to |
52 | * the device fails, the content functions such as startElement() returns @c false. |
53 | * |
54 | * XMLWriter cannot be used to serialize multiple documents. One instance per |
55 | * document must be used. |
56 | * |
57 | * XMLWriter takes care of escaping content into character references as necessary. Thus, |
58 | * it should not be done manually. In fact, it would most likely |
59 | * result in invalid XML or an unintended result. XMLWriter always serializes into UTF-8. |
60 | * |
61 | * When compiled in debug mode, XMLWriter contains several tests that helps |
62 | * ensuring that XMLWriter produces valid XML. Some of these tests ensures that: |
63 | * |
64 | * - The @c xmlns and @c xml prefixes are used properly |
65 | * - Content of comments and processing instructions is valid |
66 | * - Element, attribute and DOCTYPE names are sensible |
67 | * - Elements are properly nested and balanced |
68 | * - To some extent that things occur in the proper order. For example, that |
69 | * the document type definition isn't added inside an element |
70 | * - That namespaces prefixes are declared |
71 | * |
72 | * Not triggering XMLWriter's tests does not guarantee valid XML is produced, |
73 | * but they do help catching common mistakes and some of the corner cases in the |
74 | * specifications. When XMLWriter is compiled in release mode, these tests are not enabled |
75 | * and the error handling in effect is concerning writing to the QIODevice. |
76 | * |
77 | * Often it is of interest to add a note at the beginning of the file communicating |
78 | * it is auto-generated. setMessage() and setAddMessage() provides |
79 | * a convenient way of doing that. |
80 | * |
81 | * Namespace declarations are added with startPrefixMapping(), not by sending attributes |
82 | * with name <tt>xmlns:*</tt> to startElement(). |
83 | * |
84 | * @see <a href="http://hsivonen.iki.fi/producing-xml/">HOWTO Avoid Being |
85 | * Called a Bozo When Producing XML</a> |
86 | * @see <a href="http://www.w3.org/TR/REC-xml/">Extensible Markup |
87 | * Language (XML) 1.0 (Third Edition)</a> |
88 | * @see <a href="http://www.w3.org/TR/REC-xml-names/">Namespaces in XML</a> |
89 | * @todo Replace this class with QXmlStreamWriter |
90 | * @author Frans Englich <frans.englich@nokia.com> |
91 | * @ingroup PatternistSDK |
92 | */ |
93 | class XMLWriter |
94 | { |
95 | public: |
96 | /** |
97 | * Creates a XMLWriter which serializes its received events |
98 | * to @p outStream. |
99 | * |
100 | * @note XMLWriter does not claim ownership of @p outStream. Thus, |
101 | * @p outStream may not be destroyed as long as |
102 | * this XMLWriter instance uses it. |
103 | */ |
104 | XMLWriter(QIODevice *outStream = 0); |
105 | |
106 | virtual ~XMLWriter(); |
107 | |
108 | /** |
109 | * @returns @c true if opening the output device succeeds, otherwise @c false |
110 | */ |
111 | virtual bool startDocument(); |
112 | |
113 | /** |
114 | * @returns @c false if failure occurs in writing to the QIODevice, otherwise |
115 | * @c true |
116 | */ |
117 | virtual bool characters(const QString &ch); |
118 | |
119 | /** |
120 | * Starts an element with name @p qName and attributes @p atts. The prefix |
121 | * in @p qName must first be declared with startPrefixMapping(), if it has one. |
122 | * |
123 | * A call to startElement() must always at some point be balanced with a call |
124 | * to endElement(). |
125 | * |
126 | * To declare namespaces, don't put attributes with name <tt>xmlns:*</tt> in @p atts, |
127 | * but use startPrefixMapping(). |
128 | */ |
129 | virtual bool startElement(const QString &qName, |
130 | const QXmlStreamAttributes &atts = QXmlStreamAttributes()); |
131 | |
132 | /** |
133 | * Signals the end of an element with name @p qName. @p qName must |
134 | * be supplied. |
135 | * |
136 | * Calls to startElement() and endElement() must always be balanced. |
137 | * |
138 | * @returns @c false if failure occurs in writing to the QIODevice, otherwise |
139 | * @c true |
140 | */ |
141 | virtual bool endElement(const QString &qName); |
142 | |
143 | /** |
144 | * A description of an error if it occurred. This is typically |
145 | * QIODevice::errorString(). If no error has occurred, an empty |
146 | * string is returned. |
147 | */ |
148 | virtual QString errorString() const; |
149 | |
150 | /** |
151 | * Starts a CDATA section. Content sent with characters() will not be escaped |
152 | * except for ">" if occurring in "]]>". |
153 | * |
154 | * @returns @c false if failure occurs in writing to the QIODevice, otherwise |
155 | * @c true |
156 | */ |
157 | virtual bool startCDATA(); |
158 | |
159 | /** |
160 | * @returns @c false if failure occurs in writing to the QIODevice, otherwise |
161 | * @c true |
162 | */ |
163 | virtual bool endCDATA(); |
164 | |
165 | /** |
166 | * Creates a document type definition. |
167 | * |
168 | * For example, the code snippet: |
169 | * |
170 | * @code |
171 | * writer.startDTD("html", "-//W3C//DTD XHTML 1.0 Strict//EN", |
172 | * "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"); |
173 | * writer.endDTD(); |
174 | * @endcode |
175 | * |
176 | * would create: |
177 | * @verbatim |
178 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> |
179 | @endverbatim |
180 | * |
181 | * @note A system identifier must always be specified, but a public identifier may |
182 | * be left out. |
183 | * |
184 | * A call to startDTD() must be followed by a call to endDTD(). |
185 | */ |
186 | virtual bool startDTD(const QString &name, |
187 | const QString &publicId, |
188 | const QString &systemId); |
189 | |
190 | /** |
191 | * Apart from closing the DTD, an new line is also added at end. |
192 | */ |
193 | virtual bool endDTD(); |
194 | |
195 | /** |
196 | * Creates a processing instruction by name @p target, and content |
197 | * @p data. |
198 | * |
199 | * @returns @c false if failure occurs in writing to the QIODevice, otherwise |
200 | * @c true |
201 | */ |
202 | virtual bool processingInstruction(const QString &target, |
203 | const QString &data); |
204 | |
205 | /** |
206 | * Declares a namespace which maps @p prefix to @p namespaceURI. For example, the call: |
207 | * |
208 | * @code |
209 | * startPrefixMapping("xhtml", "http://www.w3.org/1999/xhtml"); |
210 | * @endcode |
211 | * |
212 | * would result in: |
213 | * |
214 | * @code |
215 | * xmlns="http://www.w3.org/1999/xhtml" |
216 | * @endcode |
217 | */ |
218 | virtual bool startPrefixMapping(const QString &prefix, |
219 | const QString &namespaceURI); |
220 | |
221 | /** |
222 | * Creates a comment with content @p ch. @p ch is escaped, there's |
223 | * no need to do it manually. For example, calling comment() with @p ch |
224 | * set to "my comment", results in "<!--my comment-->" in the output. |
225 | * |
226 | * @note if @p ch contains double hyphen("--"), the produced XML will |
227 | * not be well formed. |
228 | * |
229 | * @returns @c false if failure occurs in writing to the QIODevice, otherwise |
230 | * @c true |
231 | */ |
232 | virtual bool (const QString &ch); |
233 | |
234 | virtual bool startEntity(const QString &name); |
235 | virtual bool endEntity(const QString &name); |
236 | |
237 | /** |
238 | * Sets the message which is added as a comment if addModificationMessage() |
239 | * is set to @c true. If no message is specified and addModificationMessage() |
240 | * is set to @c true, a default message is used. |
241 | * |
242 | * @see modificationMessage(), setAddMessage() |
243 | */ |
244 | virtual void setMessage(const QString &msg); |
245 | |
246 | /** |
247 | * The message that is added at the beginning of the XML events |
248 | * in a comment node. If no modificationMessage is set via modificationMessage(), |
249 | * and addModificationMessage is set to @c true, this message will be used: |
250 | * "NOTE: This file was automatically generated by [the application name] at |
251 | * [the current date time]. All changes to this file will be lost." |
252 | * |
253 | * @see setMessage() |
254 | */ |
255 | virtual QString modificationMessage() const; |
256 | |
257 | /** |
258 | * Closes the QIODevice XMLWriter writes to. |
259 | */ |
260 | virtual bool endDocument(); |
261 | |
262 | /** |
263 | * Serializes @p ch as if it was sent to characters(). |
264 | * |
265 | * @returns @c false if failure occurs in writing to the QIODevice, otherwise |
266 | * @c true |
267 | */ |
268 | virtual bool ignorableWhitespace(const QString &ch); |
269 | |
270 | /** |
271 | * @returns the device XMLWriter writes its output to. |
272 | * XMLWriter does not own the device. |
273 | */ |
274 | virtual QIODevice *device() const; |
275 | |
276 | /** |
277 | * Sets the QIODevice XMLWriter writes to, to @p device. A device must be specified |
278 | * either via this function or in the constructor before XMLWriter is used. |
279 | * |
280 | * XMLWriter does not claim ownership of @p device. |
281 | */ |
282 | virtual void setDevice(QIODevice *device); |
283 | |
284 | /** |
285 | * Determines whether the modification message should be inserted as a comment |
286 | * before the document element. The message returned by modificationMessage() is used. |
287 | * |
288 | * If @p toggle is @c true, the message will be added, otherwise not. |
289 | */ |
290 | virtual void setAddMessage(const bool toggle); |
291 | |
292 | /** |
293 | * Tells whether a modification message will be added. |
294 | * |
295 | * @see setAddMessage(), modificationMessage() |
296 | */ |
297 | virtual bool addModificationMessage() const; |
298 | |
299 | private: |
300 | Q_DISABLE_COPY(XMLWriter) |
301 | |
302 | class Private; |
303 | Private *d; |
304 | }; |
305 | } |
306 | |
307 | QT_END_NAMESPACE |
308 | |
309 | #endif |
310 | // vim: et:ts=4:sw=4:sts=4 |
311 | |