File indexing completed on 2024-12-08 12:56:12

0001 /* This file is part of the KDE project
0002 
0003    Copyright (C) 2013 Inge Wallin <inge@lysator.liu.se>
0004 
0005    This library is free software; you can redistribute it and/or
0006    modify it under the terms of the GNU Library General Public
0007    License as published by the Free Software Foundation; either
0008    version 2 of the License, or (at your option) any later version.
0009 
0010    This library is distributed in the hope that it will be useful,
0011    but WITHOUT ANY WARRANTY; without even the implied warranty of
0012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013    Library General Public License for more details.
0014 
0015    You should have received a copy of the GNU Library General Public License
0016    along with this library; see the file COPYING.LIB.  If not, write to
0017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018  * Boston, MA 02110-1301, USA.
0019  */
0020 
0021 #ifndef KOXMLSTREAMREADER_H
0022 #define KOXMLSTREAMREADER_H
0023 
0024 
0025 #include "KoXmlStreamReader.h"
0026 
0027 #include <QXmlStreamReader>
0028 #include <QStringRef>
0029 #include <QVector>
0030 #include <QSharedData>
0031 
0032 #include "koodf2_export.h"
0033 
0034 
0035 class QByteArray;
0036 class QString;
0037 class QIODevice;
0038 
0039 class KoXmlStreamAttributes;
0040 
0041 
0042 /**
0043  * @brief An XML stream reader based on QXmlStreamReader and with namespace handling better suited to use for ODF in Calligra.
0044  *
0045  * Opendocument uses an XML encoding which makes heavy use of
0046  * namespaces. So normally you would want to compare the qualified
0047  * name when accessing tagnames and attributes.
0048  * 
0049  * However, in QXmlStreamReader you have to either make an explicit
0050  * comparison with the namespace URI for every element and attribute
0051  * or risk that documents that use the correct namespaces but not the
0052  * normal namespace prefixes are wrongly interpreted.  This is because
0053  * the prefix (e.g. "fo" in "fo:border-width") is declared at the
0054  * beginning of the document using a namespace declaration attribute
0055  * such as: xmlns:fo="http://www.w3.org/1999/XSL/Format". In this case
0056  * xmlns:fo could just as well be xmlns:xxx which makes the expected
0057  * fo:border-width become xxx:border-width in the rest of this
0058  * document.
0059  *
0060  * However, it is extremely rare to find document that uses such
0061  * non-standard namespace prefixes. This gives us the opportunity to
0062  * optimize for the common case, which is exactly what
0063  * KoXmlStreamReader does.
0064  *
0065  * The way to use this class is to tell it which namespaces and
0066  * prefixes that you expect before you open the XML stream. Then it
0067  * checks if the namespaces and prefixes in the document are the same
0068  * as the expected ones.  If they are in fact the same, the document
0069  * is pronounced "sound", and for the rest of the processing you can
0070  * use the qualified name with the expected prefix ("fo:border-width")
0071  * with the maximum performance.
0072  *
0073  * If the namespace(s) in the document are the expected ones but the
0074  * prefix(es) are not, you can still compare the qualified name to
0075  * your expected ones.  But in this case the document is deemed
0076  * "unsound" and for every access to attributes or calls to
0077  * qualifiedName(), KoXmlStreamReader will rewrite the actual name in
0078  * the document to become what you expect.  The functions
0079  * namespaceUri() and name() are not affected, only the prefixes.
0080  */
0081 class KOODF2_EXPORT KoXmlStreamReader : public QXmlStreamReader
0082 {
0083     friend class KoXmlStreamAttribute;
0084     friend class KoXmlStreamAttributes;
0085 
0086 public:
0087     KoXmlStreamReader();
0088     explicit KoXmlStreamReader(QIODevice *device);
0089     explicit KoXmlStreamReader(const QByteArray &data);
0090     explicit KoXmlStreamReader(const QString &data);
0091     explicit KoXmlStreamReader(const char *data);
0092 
0093     ~KoXmlStreamReader();
0094 
0095     void clear();
0096 
0097     void addExpectedNamespace(const QString &prefix, const QString &namespaceUri);
0098     void addExtraNamespace(const QString &prefix, const QString &namespaceUri);
0099 
0100     // --------------------------------
0101     // Reimplemented from QXmlStreamReader
0102 
0103     QStringRef prefix() const;
0104     QStringRef qualifiedName() const;
0105     void setDevice(QIODevice *device);
0106     KoXmlStreamAttributes attributes() const;
0107 
0108 private:
0109     // No copying
0110     KoXmlStreamReader(const KoXmlStreamReader &other);
0111     KoXmlStreamReader &operator=(const KoXmlStreamReader &other);
0112 
0113     // Only for friend classes KoXmlStreamAttributes and KoXmlStreamAttribute.
0114     bool isSound() const;
0115 
0116     class Private;
0117     Private * const d;
0118 };
0119 
0120 
0121 /**
0122  * @brief KoXmlStreamAttribute is a source-compatible replacement for QXmlStreamAttribute.
0123  *
0124  * In addition to the API from QXmlStreamAttribute, it offers the same
0125  * advantages that KoXmlStreamReader does over QXmlStreamReader: when
0126  * asked for the qualified name of an attribute it will return the
0127  * expected one even if the prefix declared in the namespace
0128  * declaration of the document is different.
0129  *
0130  * @see KoXmlStreamReader
0131  */
0132 class KOODF2_EXPORT KoXmlStreamAttribute
0133 {
0134     friend class QVector<KoXmlStreamAttribute>;       // For the default constructor
0135     friend class KoXmlStreamAttributes;               // For the normal constructor
0136     friend class KoXmlStreamReader;
0137  public:
0138     ~KoXmlStreamAttribute();
0139 
0140     // API taken from QXmlStreamAttribute
0141     bool       isDefault() const;
0142     QStringRef name() const;
0143     QStringRef namespaceUri() const;
0144     QStringRef prefix() const;
0145     QStringRef qualifiedName() const;
0146     QStringRef value() const;
0147 
0148     bool operator==(const KoXmlStreamAttribute &other) const;
0149     bool operator!=(const KoXmlStreamAttribute &other) const;
0150     KoXmlStreamAttribute &operator=(const KoXmlStreamAttribute &other);
0151 
0152  private:
0153     // Only for friend classes.
0154     KoXmlStreamAttribute();
0155     KoXmlStreamAttribute(const KoXmlStreamAttribute &other);
0156     KoXmlStreamAttribute(const QXmlStreamAttribute *attr, const KoXmlStreamReader *reader);
0157 
0158     class Private;
0159     Private * const d;
0160 };
0161 
0162 
0163 /**
0164  * @brief KoXmlStreamAttributes is a mostly source-compatible replacement for QXmlStreamAttributes.
0165  *
0166  * All the convenience functions of KoXmlStreamAttributes work exactly
0167  * like the counterparts of QXmlStreamAttributes but they give the
0168  * expected prefix for the registered expected namespaces.
0169  *
0170  * Not all functions from QVector are implemented but the ones that
0171  * make sense for this read-only class are. This class can only be
0172  * used in connection with KoXmlStreamReader.
0173  *
0174  * @see KoXmlStreamReader
0175  */
0176 class KOODF2_EXPORT KoXmlStreamAttributes
0177 {
0178     friend class KoXmlStreamReader;
0179 
0180  public:
0181     typedef const KoXmlStreamAttribute *const_iterator;
0182 
0183     KoXmlStreamAttributes(const KoXmlStreamAttributes &other);
0184     ~KoXmlStreamAttributes();
0185 
0186     KoXmlStreamAttributes &operator=(const KoXmlStreamAttributes &other);
0187 
0188     // Relevant parts of the QVector API
0189     const KoXmlStreamAttribute &at(int i) const;
0190     int size() const;
0191     KoXmlStreamAttribute value(int i) const;
0192     const KoXmlStreamAttribute &operator[](int i) const;
0193     const_iterator begin() const;
0194     const_iterator end() const;
0195 
0196     // Convenience functions taken from QXmlStreamAttributes API
0197     void        append(const QString &namespaceUri, const QString &name, const QString &value);
0198     void        append(const QXmlStreamAttribute &attribute);
0199     void        append(const QString &qualifiedName, const QString &value);
0200     bool        hasAttribute(const QString &qualifiedName) const;
0201     bool        hasAttribute(const QLatin1String &qualifiedName) const;
0202     bool        hasAttribute ( const QString & namespaceUri, const QString & name ) const;
0203     QStringRef  value ( const QString & namespaceUri, const QString & name ) const;
0204     QStringRef  value ( const QString & namespaceUri, const QLatin1String & name ) const;
0205     QStringRef  value ( const QLatin1String & namespaceUri, const QLatin1String & name ) const;
0206     QStringRef  value(const QString &qualifiedName) const;
0207     QStringRef  value(const QLatin1String &qualifiedName) const;
0208 
0209  private:
0210     // Only available from friend class KoXmlStreamReader.
0211     KoXmlStreamAttributes(const KoXmlStreamReader *r, const QXmlStreamAttributes &qAttrs);
0212 
0213     // This class is implicitly shared.
0214     class Private;
0215     QSharedDataPointer<Private> d;
0216 };
0217 
0218 
0219 void KOODF2_EXPORT prepareForOdf(KoXmlStreamReader &reader);
0220 
0221 
0222 #endif /* KOXMLSTREAMREADER_H */