Your IP : 216.73.216.48
/* This file is part of the KDE project
Copyright (C) 2013 Inge Wallin <inge@lysator.liu.se>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef KOXMLSTREAMREADER_H
#define KOXMLSTREAMREADER_H
#include "KoXmlStreamReader.h"
#include <QXmlStreamReader>
#include <QStringRef>
#include <QVector>
#include <QSharedData>
#include "koodf_export.h"
class QByteArray;
class QString;
class QIODevice;
class KoXmlStreamAttributes;
/**
* @brief An XML stream reader based on QXmlStreamReader and with namespace handling better suited to use for ODF in Calligra.
*
* Opendocument uses an XML encoding which makes heavy use of
* namespaces. So normally you would want to compare the qualified
* name when accessing tagnames and attributes.
*
* However, in QXmlStreamReader you have to either make an explicit
* comparison with the namespace URI for every element and attribute
* or risk that documents that use the correct namespaces but not the
* normal namespace prefixes are wrongly interpreted. This is because
* the prefix (e.g. "fo" in "fo:border-width") is declared at the
* beginning of the document using a namespace declaration attribute
* such as: xmlns:fo="http://www.w3.org/1999/XSL/Format". In this case
* xmlns:fo could just as well be xmlns:xxx which makes the expected
* fo:border-width become xxx:border-width in the rest of this
* document.
*
* However, it is extremely rare to find document that uses such
* non-standard namespace prefixes. This gives us the opportunity to
* optimize for the common case, which is exactly what
* KoXmlStreamReader does.
*
* The way to use this class is to tell it which namespaces and
* prefixes that you expect before you open the XML stream. Then it
* checks if the namespaces and prefixes in the document are the same
* as the expected ones. If they are in fact the same, the document
* is pronounced "sound", and for the rest of the processing you can
* use the qualified name with the expected prefix ("fo:border-width")
* with the maximum performance.
*
* If the namespace(s) in the document are the expected ones but the
* prefix(es) are not, you can still compare the qualified name to
* your expected ones. But in this case the document is deemed
* "unsound" and for every access to attributes or calls to
* qualifiedName(), KoXmlStreamReader will rewrite the actual name in
* the document to become what you expect. The functions
* namespaceUri() and name() are not affected, only the prefixes.
*/
class KOODF_EXPORT KoXmlStreamReader : public QXmlStreamReader
{
friend class KoXmlStreamAttribute;
friend class KoXmlStreamAttributes;
public:
KoXmlStreamReader();
KoXmlStreamReader(QIODevice *device);
KoXmlStreamReader(const QByteArray &data);
KoXmlStreamReader(const QString &data);
KoXmlStreamReader(const char *data);
~KoXmlStreamReader();
void clear();
void addExpectedNamespace(QString prefix, QString namespaceUri);
void addExtraNamespace(QString prefix, QString namespaceUri);
// --------------------------------
// Reimplemented from QXmlStreamReader
QStringRef prefix() const;
QStringRef qualifiedName() const;
void setDevice(QIODevice *device);
KoXmlStreamAttributes attributes() const;
private:
// No copying
KoXmlStreamReader(KoXmlStreamReader &other);
KoXmlStreamReader &operator=(KoXmlStreamReader &other);
// Only for friend classes KoXmlStreamAttributes and KoXmlStreamAttribute.
bool isSound() const;
class Private;
Private * const d;
};
/**
* @brief KoXmlStreamAttribute is a source-compatible replacement for QXmlStreamAttribute.
*
* In addition to the API from QXmlStreamAttribute, it offers the same
* advantages that KoXmlStreamReader does over QXmlStreamReader: when
* asked for the qualified name of an attribute it will return the
* expected one even if the prefix declared in the namespace
* declaration of the document is different.
*
* @see KoXmlStreamReader
*/
class KoXmlStreamAttribute
{
friend class QVector<KoXmlStreamAttribute>; // For the default constructor
friend class KoXmlStreamAttributes; // For the normal constructor
friend class KoXmlStreamReader;
public:
~KoXmlStreamAttribute();
// API taken from QXmlStreamAttribute
bool isDefault() const;
QStringRef name() const;
QStringRef namespaceUri() const;
QStringRef prefix() const;
QStringRef qualifiedName() const;
QStringRef value() const;
bool operator==(const KoXmlStreamAttribute &other) const;
bool operator!=(const KoXmlStreamAttribute &other) const;
KoXmlStreamAttribute &operator=(const KoXmlStreamAttribute &other);
private:
// Only for friend classes.
KoXmlStreamAttribute();
KoXmlStreamAttribute(const KoXmlStreamAttribute &other);
KoXmlStreamAttribute(const QXmlStreamAttribute *attr, const KoXmlStreamReader *reader);
class Private;
Private * const d;
};
/**
* @brief KoXmlStreamAttributes is a mostly source-compatible replacement for QXmlStreamAttributes.
*
* All the convenience functions of KoXmlStreamAttributes work exactly
* like the counterparts of QXmlStreamAttributes but they give the
* expected prefix for the registered expected namespaces.
*
* Not all functions from QVector are implemented but the ones that
* make sense for this read-only class are. This class can only be
* used in connection with KoXmlStreamReader.
*
* @see KoXmlStreamReader
*/
class KoXmlStreamAttributes
{
friend class KoXmlStreamReader;
public:
typedef const KoXmlStreamAttribute *const_iterator;
KoXmlStreamAttributes(const KoXmlStreamAttributes &other);
~KoXmlStreamAttributes();
KoXmlStreamAttributes &operator=(const KoXmlStreamAttributes &other);
// Relevant parts of the QVector API
const KoXmlStreamAttribute &at(int i) const;
int size() const;
KoXmlStreamAttribute value(int i) const;
const KoXmlStreamAttribute &operator[](int i) const;
const_iterator begin() const;
const_iterator end() const;
// Convenience functions taken from QXmlStreamAttributes API
void append(const QString &namespaceUri, const QString &name, const QString &value);
void append(const QXmlStreamAttribute &attribute);
void append(const QString &qualifiedName, const QString &value);
bool hasAttribute(const QString &qualifiedName) const;
bool hasAttribute(const QLatin1String &qualifiedName) const;
bool hasAttribute ( const QString & namespaceUri, const QString & name ) const;
QStringRef value ( const QString & namespaceUri, const QString & name ) const;
QStringRef value ( const QString & namespaceUri, const QLatin1String & name ) const;
QStringRef value ( const QLatin1String & namespaceUri, const QLatin1String & name ) const;
QStringRef value(const QString &qualifiedName) const;
QStringRef value(const QLatin1String &qualifiedName) const;
private:
// Only available from friend class KoXmlStreamReader.
KoXmlStreamAttributes(const KoXmlStreamReader *r, const QXmlStreamAttributes &qAttrs);
// This class is implicitly shared.
class Private;
QSharedDataPointer<Private> d;
};
void prepareForOdf(KoXmlStreamReader &reader);
#endif /* KOGENCHANGES_H */