/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef PatternistSDK_XMLWriter_H #define PatternistSDK_XMLWriter_H #include "Global.h" #include QT_BEGIN_NAMESPACE class QIODevice; namespace QPatternistSDK { /** * @short Serializes a stream of SAX events into XML, sent to a QIODevice. * * XMLWriter is a fast and simple XML serializer which takes care of * all the low level details of well-formedness and character escaping, allowing * the user to focus on higher level issues and increasing the chances of producing * valid, interoperable XML. * * The content XMLWriter produces is sent to a QIODevice, which is either * specified in XMLWriter's constructor or via setDevice(). If writing to * the device fails, the content functions such as startElement() returns @c false. * * XMLWriter cannot be used to serialize multiple documents. One instance per * document must be used. * * XMLWriter takes care of escaping content into character references as necessary. Thus, * it should not be done manually. In fact, it would most likely * result in invalid XML or an unintended result. XMLWriter always serializes into UTF-8. * * When compiled in debug mode, XMLWriter contains several tests that helps * ensuring that XMLWriter produces valid XML. Some of these tests ensures that: * * - The @c xmlns and @c xml prefixes are used properly * - Content of comments and processing instructions is valid * - Element, attribute and DOCTYPE names are sensible * - Elements are properly nested and balanced * - To some extent that things occur in the proper order. For example, that * the document type definition isn't added inside an element * - That namespaces prefixes are declared * * Not triggering XMLWriter's tests does not guarantee valid XML is produced, * but they do help catching common mistakes and some of the corner cases in the * specifications. When XMLWriter is compiled in release mode, these tests are not enabled * and the error handling in effect is concerning writing to the QIODevice. * * Often it is of interest to add a note at the beginning of the file communicating * it is auto-generated. setMessage() and setAddMessage() provides * a convenient way of doing that. * * Namespace declarations are added with startPrefixMapping(), not by sending attributes * with name xmlns:* to startElement(). * * @see HOWTO Avoid Being * Called a Bozo When Producing XML * @see Extensible Markup * Language (XML) 1.0 (Third Edition) * @see Namespaces in XML * @todo Replace this class with QXmlStreamWriter * @author Frans Englich * @ingroup PatternistSDK */ class XMLWriter { public: /** * Creates a XMLWriter which serializes its received events * to @p outStream. * * @note XMLWriter does not claim ownership of @p outStream. Thus, * @p outStream may not be destroyed as long as * this XMLWriter instance uses it. */ XMLWriter(QIODevice *outStream = 0); virtual ~XMLWriter(); /** * @returns @c true if opening the output device succeeds, otherwise @c false */ virtual bool startDocument(); /** * @returns @c false if failure occurs in writing to the QIODevice, otherwise * @c true */ virtual bool characters(const QString &ch); /** * Starts an element with name @p qName and attributes @p atts. The prefix * in @p qName must first be declared with startPrefixMapping(), if it has one. * * A call to startElement() must always at some point be balanced with a call * to endElement(). * * To declare namespaces, don't put attributes with name xmlns:* in @p atts, * but use startPrefixMapping(). */ virtual bool startElement(const QString &qName, const QXmlStreamAttributes &atts = QXmlStreamAttributes()); /** * Signals the end of an element with name @p qName. @p qName must * be supplied. * * Calls to startElement() and endElement() must always be balanced. * * @returns @c false if failure occurs in writing to the QIODevice, otherwise * @c true */ virtual bool endElement(const QString &qName); /** * A description of an error if it occurred. This is typically * QIODevice::errorString(). If no error has occurred, an empty * string is returned. */ virtual QString errorString() const; /** * Starts a CDATA section. Content sent with characters() will not be escaped * except for ">" if occurring in "]]>". * * @returns @c false if failure occurs in writing to the QIODevice, otherwise * @c true */ virtual bool startCDATA(); /** * @returns @c false if failure occurs in writing to the QIODevice, otherwise * @c true */ virtual bool endCDATA(); /** * Creates a document type definition. * * For example, the code snippet: * * @code * writer.startDTD("html", "-//W3C//DTD XHTML 1.0 Strict//EN", * "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"); * writer.endDTD(); * @endcode * * would create: * @verbatim @endverbatim * * @note A system identifier must always be specified, but a public identifier may * be left out. * * A call to startDTD() must be followed by a call to endDTD(). */ virtual bool startDTD(const QString &name, const QString &publicId, const QString &systemId); /** * Apart from closing the DTD, an new line is also added at end. */ virtual bool endDTD(); /** * Creates a processing instruction by name @p target, and content * @p data. * * @returns @c false if failure occurs in writing to the QIODevice, otherwise * @c true */ virtual bool processingInstruction(const QString &target, const QString &data); /** * Declares a namespace which maps @p prefix to @p namespaceURI. For example, the call: * * @code * startPrefixMapping("xhtml", "http://www.w3.org/1999/xhtml"); * @endcode * * would result in: * * @code * xmlns="http://www.w3.org/1999/xhtml" * @endcode */ virtual bool startPrefixMapping(const QString &prefix, const QString &namespaceURI); /** * Creates a comment with content @p ch. @p ch is escaped, there's * no need to do it manually. For example, calling comment() with @p ch * set to "my comment", results in "" in the output. * * @note if @p ch contains double hyphen("--"), the produced XML will * not be well formed. * * @returns @c false if failure occurs in writing to the QIODevice, otherwise * @c true */ virtual bool comment(const QString &ch); virtual bool startEntity(const QString &name); virtual bool endEntity(const QString &name); /** * Sets the message which is added as a comment if addModificationMessage() * is set to @c true. If no message is specified and addModificationMessage() * is set to @c true, a default message is used. * * @see modificationMessage(), setAddMessage() */ virtual void setMessage(const QString &msg); /** * The message that is added at the beginning of the XML events * in a comment node. If no modificationMessage is set via modificationMessage(), * and addModificationMessage is set to @c true, this message will be used: * "NOTE: This file was automatically generated by [the application name] at * [the current date time]. All changes to this file will be lost." * * @see setMessage() */ virtual QString modificationMessage() const; /** * Closes the QIODevice XMLWriter writes to. */ virtual bool endDocument(); /** * Serializes @p ch as if it was sent to characters(). * * @returns @c false if failure occurs in writing to the QIODevice, otherwise * @c true */ virtual bool ignorableWhitespace(const QString &ch); /** * @returns the device XMLWriter writes its output to. * XMLWriter does not own the device. */ virtual QIODevice *device() const; /** * Sets the QIODevice XMLWriter writes to, to @p device. A device must be specified * either via this function or in the constructor before XMLWriter is used. * * XMLWriter does not claim ownership of @p device. */ virtual void setDevice(QIODevice *device); /** * Determines whether the modification message should be inserted as a comment * before the document element. The message returned by modificationMessage() is used. * * If @p toggle is @c true, the message will be added, otherwise not. */ virtual void setAddMessage(const bool toggle); /** * Tells whether a modification message will be added. * * @see setAddMessage(), modificationMessage() */ virtual bool addModificationMessage() const; private: Q_DISABLE_COPY(XMLWriter) class Private; Private *d; }; } QT_END_NAMESPACE #endif // vim: et:ts=4:sw=4:sts=4