1 /* This file is part of the KDE project 2 3 Copyright (C) 2013 Inge Wallin <inge@lysator.liu.se> 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Library General Public 7 License as published by the Free Software Foundation; either 8 version 2 of the License, or (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Library General Public License for more details. 14 15 You should have received a copy of the GNU Library General Public License 16 along with this library; see the file COPYING.LIB. If not, write to 17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 * Boston, MA 02110-1301, USA. 19 */ 20 21 #ifndef KOXMLSTREAMREADER_H 22 #define KOXMLSTREAMREADER_H 23 24 25 #include "KoXmlStreamReader.h" 26 27 #include <QXmlStreamReader> 28 #include <QStringRef> 29 #include <QVector> 30 #include <QSharedData> 31 32 #include "koodf2_export.h" 33 34 35 class QByteArray; 36 class QString; 37 class QIODevice; 38 39 class KoXmlStreamAttributes; 40 41 42 /** 43 * @brief An XML stream reader based on QXmlStreamReader and with namespace handling better suited to use for ODF in Calligra. 44 * 45 * Opendocument uses an XML encoding which makes heavy use of 46 * namespaces. So normally you would want to compare the qualified 47 * name when accessing tagnames and attributes. 48 * 49 * However, in QXmlStreamReader you have to either make an explicit 50 * comparison with the namespace URI for every element and attribute 51 * or risk that documents that use the correct namespaces but not the 52 * normal namespace prefixes are wrongly interpreted. This is because 53 * the prefix (e.g. "fo" in "fo:border-width") is declared at the 54 * beginning of the document using a namespace declaration attribute 55 * such as: xmlns:fo="http://www.w3.org/1999/XSL/Format". In this case 56 * xmlns:fo could just as well be xmlns:xxx which makes the expected 57 * fo:border-width become xxx:border-width in the rest of this 58 * document. 59 * 60 * However, it is extremely rare to find document that uses such 61 * non-standard namespace prefixes. This gives us the opportunity to 62 * optimize for the common case, which is exactly what 63 * KoXmlStreamReader does. 64 * 65 * The way to use this class is to tell it which namespaces and 66 * prefixes that you expect before you open the XML stream. Then it 67 * checks if the namespaces and prefixes in the document are the same 68 * as the expected ones. If they are in fact the same, the document 69 * is pronounced "sound", and for the rest of the processing you can 70 * use the qualified name with the expected prefix ("fo:border-width") 71 * with the maximum performance. 72 * 73 * If the namespace(s) in the document are the expected ones but the 74 * prefix(es) are not, you can still compare the qualified name to 75 * your expected ones. But in this case the document is deemed 76 * "unsound" and for every access to attributes or calls to 77 * qualifiedName(), KoXmlStreamReader will rewrite the actual name in 78 * the document to become what you expect. The functions 79 * namespaceUri() and name() are not affected, only the prefixes. 80 */ 81 class KOODF2_EXPORT KoXmlStreamReader : public QXmlStreamReader 82 { 83 friend class KoXmlStreamAttribute; 84 friend class KoXmlStreamAttributes; 85 86 public: 87 KoXmlStreamReader(); 88 explicit KoXmlStreamReader(QIODevice *device); 89 explicit KoXmlStreamReader(const QByteArray &data); 90 explicit KoXmlStreamReader(const QString &data); 91 explicit KoXmlStreamReader(const char *data); 92 93 ~KoXmlStreamReader(); 94 95 void clear(); 96 97 void addExpectedNamespace(const QString &prefix, const QString &namespaceUri); 98 void addExtraNamespace(const QString &prefix, const QString &namespaceUri); 99 100 // -------------------------------- 101 // Reimplemented from QXmlStreamReader 102 103 QStringRef prefix() const; 104 QStringRef qualifiedName() const; 105 void setDevice(QIODevice *device); 106 KoXmlStreamAttributes attributes() const; 107 108 private: 109 // No copying 110 KoXmlStreamReader(const KoXmlStreamReader &other); 111 KoXmlStreamReader &operator=(const KoXmlStreamReader &other); 112 113 // Only for friend classes KoXmlStreamAttributes and KoXmlStreamAttribute. 114 bool isSound() const; 115 116 class Private; 117 Private * const d; 118 }; 119 120 121 /** 122 * @brief KoXmlStreamAttribute is a source-compatible replacement for QXmlStreamAttribute. 123 * 124 * In addition to the API from QXmlStreamAttribute, it offers the same 125 * advantages that KoXmlStreamReader does over QXmlStreamReader: when 126 * asked for the qualified name of an attribute it will return the 127 * expected one even if the prefix declared in the namespace 128 * declaration of the document is different. 129 * 130 * @see KoXmlStreamReader 131 */ 132 class KOODF2_EXPORT KoXmlStreamAttribute 133 { 134 friend class QVector<KoXmlStreamAttribute>; // For the default constructor 135 friend class KoXmlStreamAttributes; // For the normal constructor 136 friend class KoXmlStreamReader; 137 public: 138 ~KoXmlStreamAttribute(); 139 140 // API taken from QXmlStreamAttribute 141 bool isDefault() const; 142 QStringRef name() const; 143 QStringRef namespaceUri() const; 144 QStringRef prefix() const; 145 QStringRef qualifiedName() const; 146 QStringRef value() const; 147 148 bool operator==(const KoXmlStreamAttribute &other) const; 149 bool operator!=(const KoXmlStreamAttribute &other) const; 150 KoXmlStreamAttribute &operator=(const KoXmlStreamAttribute &other); 151 152 private: 153 // Only for friend classes. 154 KoXmlStreamAttribute(); 155 KoXmlStreamAttribute(const KoXmlStreamAttribute &other); 156 KoXmlStreamAttribute(const QXmlStreamAttribute *attr, const KoXmlStreamReader *reader); 157 158 class Private; 159 Private * const d; 160 }; 161 162 163 /** 164 * @brief KoXmlStreamAttributes is a mostly source-compatible replacement for QXmlStreamAttributes. 165 * 166 * All the convenience functions of KoXmlStreamAttributes work exactly 167 * like the counterparts of QXmlStreamAttributes but they give the 168 * expected prefix for the registered expected namespaces. 169 * 170 * Not all functions from QVector are implemented but the ones that 171 * make sense for this read-only class are. This class can only be 172 * used in connection with KoXmlStreamReader. 173 * 174 * @see KoXmlStreamReader 175 */ 176 class KOODF2_EXPORT KoXmlStreamAttributes 177 { 178 friend class KoXmlStreamReader; 179 180 public: 181 typedef const KoXmlStreamAttribute *const_iterator; 182 183 KoXmlStreamAttributes(const KoXmlStreamAttributes &other); 184 ~KoXmlStreamAttributes(); 185 186 KoXmlStreamAttributes &operator=(const KoXmlStreamAttributes &other); 187 188 // Relevant parts of the QVector API 189 const KoXmlStreamAttribute &at(int i) const; 190 int size() const; 191 KoXmlStreamAttribute value(int i) const; 192 const KoXmlStreamAttribute &operator[](int i) const; 193 const_iterator begin() const; 194 const_iterator end() const; 195 196 // Convenience functions taken from QXmlStreamAttributes API 197 void append(const QString &namespaceUri, const QString &name, const QString &value); 198 void append(const QXmlStreamAttribute &attribute); 199 void append(const QString &qualifiedName, const QString &value); 200 bool hasAttribute(const QString &qualifiedName) const; 201 bool hasAttribute(const QLatin1String &qualifiedName) const; 202 bool hasAttribute ( const QString & namespaceUri, const QString & name ) const; 203 QStringRef value ( const QString & namespaceUri, const QString & name ) const; 204 QStringRef value ( const QString & namespaceUri, const QLatin1String & name ) const; 205 QStringRef value ( const QLatin1String & namespaceUri, const QLatin1String & name ) const; 206 QStringRef value(const QString &qualifiedName) const; 207 QStringRef value(const QLatin1String &qualifiedName) const; 208 209 private: 210 // Only available from friend class KoXmlStreamReader. 211 KoXmlStreamAttributes(const KoXmlStreamReader *r, const QXmlStreamAttributes &qAttrs); 212 213 // This class is implicitly shared. 214 class Private; 215 QSharedDataPointer<Private> d; 216 }; 217 218 219 void KOODF2_EXPORT prepareForOdf(KoXmlStreamReader &reader); 220 221 222 #endif /* KOXMLSTREAMREADER_H */ 223