| 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 | |