blob: 0051d66699c0845a687cc8a20a8eb63f85a7959e [file] [log] [blame]
/****************************************************************************
**
** 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 <QtXml/QXmlContentHandler>
#include <QtXml/QXmlLexicalHandler>
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 sub-classes QXmlContentHandler meaning it can serialize content
* from any code that produces SAX events. The class can also be used manually,
* by calling startElement(), endCDATA(), and so forth.
*
* 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 <tt>xmlns:*</tt> to startElement().
*
* @see <a href="http://hsivonen.iki.fi/producing-xml/">HOWTO Avoid Being
* Called a Bozo When Producing XML</a>
* @see <a href="http://www.w3.org/TR/REC-xml/">Extensible Markup
* Language (XML) 1.0 (Third Edition)</a>
* @see <a href="http://www.w3.org/TR/REC-xml-names/">Namespaces in XML</a>
* @todo Replace this class with QXmlStreamWriter
* @author Frans Englich <frans.englich@nokia.com>
* @ingroup PatternistSDK
*/
class XMLWriter : public QXmlContentHandler
, public QXmlLexicalHandler
{
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 <tt>xmlns:*</tt> in @p atts,
* but use startPrefixMapping().
*/
virtual bool startElement(const QString &qName, const QXmlAttributes &atts = QXmlAttributes());
/**
*
* Behaves essentially as startElement(const QString &qName, const QXmlAttributes &atts). This
* function is used in conjunction with other SAX classes.
*
* The call:
*
* @code
* startElement(QString(), QString(), qName, atts);
* @endcode
*
* is equivalent to:
*
* @code
* startElement(qName, atts);
* @endcode
*
* @p namespaceURI and @p localName are not used. This function is
* used in conjunction with other SAX classes.
*
* @returns @c false if failure occurs in writing to the QIODevice, otherwise
* @c true
*/
virtual bool startElement(const QString &namespaceURI,
const QString &localName,
const QString &qName,
const QXmlAttributes &atts);
/**
* 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);
/**
* Behaves essentially as endElement(const QString &qName). This function
* is used when XMLWriter is used in SAX code.
*
* @p namespaceURI and @p localName are not used.
*
* The call:
*
* @code
* endElement(QString(), QString(), qName);
* @endcode
*
* is equivalent to:
*
* @code
* endElement(qName);
* @endcode
*
* @returns @c false if failure occurs in writing to the QIODevice, otherwise
* @c true
*/
virtual bool endElement(const QString &namespaceURI,
const QString &localName,
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
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
@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 "<!--my comment-->" 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);
/**
* This function is not used by XMLWriter, but is implemented
* in order to satisfy QXmlContentHandler's interface.
*/
virtual bool endPrefixMapping(const QString &prefix);
/**
* This function is not used by XMLWriter, but is implemented
* in order to satisfy QXmlContentHandler's interface.
*/
virtual bool skippedEntity(const QString &name);
/**
* This function is not used by XMLWriter, but is implemented
* in order to satisfy QXmlContentHandler's interface.
*/
virtual void setDocumentLocator(QXmlLocator *);
/**
* @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