File indexing completed on 2024-12-01 13:11:45
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 0022 // Own 0023 #include "KoXmlStreamReader.h" 0024 0025 // Qt 0026 #include <QString> 0027 #include <QStringList> 0028 #include <QSet> 0029 0030 #include "Odf2Debug.h" 0031 0032 0033 // ================================================================ 0034 // class KoXmlStreamReader and Private class 0035 0036 0037 class Q_DECL_HIDDEN KoXmlStreamReader::Private 0038 { 0039 public: 0040 Private(KoXmlStreamReader *qq); 0041 ~Private(); 0042 0043 void clear(); 0044 0045 // Checks the soundness of the whole document. Must be called 0046 // after the namespace declarations are read. 0047 void checkSoundness(); 0048 0049 // Builds a prefix for the current element. Only called if the 0050 // document is unsound. 0051 QStringRef buildNewPrefix(); 0052 // Builds a qualified name for the current element. Only called if 0053 // the document is unsound. 0054 QStringRef buildQName(); 0055 0056 KoXmlStreamReader *q; // The owner object; 0057 0058 bool isSound; // True if the document is sound (see the class doc for details) 0059 bool isChecked; // True if the soundness is checked 0060 0061 // These are filled using the addEx{pected,tra}Namespace() functions. 0062 QHash<QString, QString> expectedNamespaces; // nsUri, prefix 0063 QHash<QString, QString> extraNamespaces; // nsUri, prefix 0064 0065 // This is only used when a document is unsound, but is always created. 0066 QHash<QString, QString> prefixes; // nsUri, prefix 0067 0068 // If the document is unsound, we need to build the prefix and 0069 // qualified names from a prefix that we get from "prefixes" and 0070 // the actual name. But we return a QStringRef and not QString so 0071 // we need to make sure that the stringref is valid until this 0072 // KoXmlStreamReader is destructed. So we use this QSet as a 0073 // cache of all constructed qualified names that we ever generate. 0074 QSet<QString> prefixCache; 0075 QSet<QString> qualifiedNamesCache; 0076 }; 0077 0078 0079 KoXmlStreamReader::Private::Private(KoXmlStreamReader *qq) 0080 : q(qq) 0081 { 0082 clear(); 0083 } 0084 0085 KoXmlStreamReader::Private::~Private() 0086 { 0087 } 0088 0089 0090 void KoXmlStreamReader::Private::clear() 0091 { 0092 // The initial state is Unsound and Unchecked. The check may 0093 // switch it to Sound. See the class documentation for an 0094 // explanation of those terms. 0095 isSound = false; 0096 isChecked = false; 0097 0098 expectedNamespaces.clear(); 0099 extraNamespaces.clear(); 0100 0101 prefixes.clear(); 0102 prefixCache.clear(); 0103 qualifiedNamesCache.clear(); 0104 } 0105 0106 0107 void KoXmlStreamReader::Private::checkSoundness() 0108 { 0109 isSound = true; 0110 0111 // Temp values 0112 QStringList namespacesToFix; // List of namespaces we need to create a unique prefix for 0113 QSet<QString> usedPrefixes; 0114 0115 // Initialize by setting all expected prefixes and all extra ones. 0116 prefixes.clear(); 0117 foreach(const QString &nsUri, expectedNamespaces.keys()) { 0118 QString prefix = expectedNamespaces.value(nsUri); 0119 0120 prefixes.insert(nsUri, prefix); 0121 usedPrefixes.insert(prefix); 0122 } 0123 foreach(const QString &nsUri, extraNamespaces.keys()) { 0124 QString prefix = extraNamespaces.value(nsUri); 0125 0126 prefixes.insert(nsUri, prefix); 0127 usedPrefixes.insert(prefix); 0128 } 0129 0130 // The document is "Sound" if for all the declared namespaces in 0131 // the document, the prefix is the same as the one in the expected 0132 // namespaces for the same namespace URI. 0133 // 0134 // If it is not Sound, then we need to rewrite the prefixes for 0135 // the qualified names when the caller wants to access them. 0136 // Hopefully this only happens once in a million documents (and it 0137 // would be interesting to know which application created such a 0138 // strange beast). 0139 // 0140 QXmlStreamNamespaceDeclarations nsDeclarations = q->QXmlStreamReader::namespaceDeclarations(); 0141 foreach(const QXmlStreamNamespaceDeclaration &decl, nsDeclarations) { 0142 0143 QString nsUri(decl.namespaceUri().toString()); 0144 QString prefix(decl.prefix().toString()); 0145 0146 if (prefixes.contains(nsUri)) { 0147 if (prefix == prefixes.value(nsUri)) { 0148 0149 // 1. nsUri = expected nsUri AND prefix = expected prefix: 0150 // 0151 // Soundness is not disturbed. Let's continue with the next declaration. 0152 continue; 0153 } 0154 else { 0155 // 2. nsUri = expected nsUri AND prefix != expected prefix: 0156 // 0157 // Document is not sound but we don't need to do 0158 // anything else; the expected prefix is already in 0159 // prefixes[] and the prefix will be rewritten to the 0160 // expected one when used later in the document. 0161 isSound = false; 0162 continue; 0163 } 0164 } 0165 else { 0166 // 3. nsUri is not among the expected nsUri's 0167 // 0168 // Let's check if the prefix is unique or if it already 0169 // exists among the expected ones. If it is unique the 0170 // soundness is not affected, otherwise it is unsound. 0171 if (usedPrefixes.contains(prefix)) { 0172 0173 // Yes, the prefix is used for another namespace among 0174 // the expected ones. Let's store this namespace for 0175 // now and create a unique, non-"expected" prefix 0176 // later when all namespaces and prefixes are known. 0177 isSound = false; 0178 namespacesToFix.append(nsUri); 0179 } 0180 else { 0181 prefixes.insert(nsUri, prefix); 0182 usedPrefixes.insert(prefix); 0183 } 0184 } 0185 } 0186 0187 //debugOdf2 << "namespaces to fix:" << namespacesToFix; 0188 0189 // Finally, if necessary, create unique prefixes for namespaces 0190 // that are found to use one of the expected prefixes. It doesn't 0191 // much matter what we come up with here since these will have to 0192 // be accessed through namespaceUri() anyway. 0193 int number = 1; 0194 foreach (const QString &ns, namespacesToFix) { 0195 bool ok = false; 0196 QString pfx; 0197 while (!ok) { 0198 pfx = QString("pfx%1").arg(number++); 0199 if (!usedPrefixes.contains(pfx)) { 0200 ok = true; 0201 } 0202 } 0203 prefixes.insert(ns, pfx); 0204 } 0205 0206 //debugOdf2 << "Document soundness:" << isSound; 0207 //debugOdf2 << "prefixes:" << prefixes; 0208 0209 isChecked = true; 0210 } 0211 0212 QStringRef KoXmlStreamReader::Private::buildNewPrefix() 0213 { 0214 if (!isChecked) { 0215 checkSoundness(); // Sets isChecked and isSound; 0216 } 0217 0218 if (isSound) { 0219 return q->prefix(); 0220 } 0221 0222 // FIXME: Handle undeclared prefixes. (Is that even legal?) 0223 //QString nsUri = q->QXmlStreamReader::namespaceUri().toString(); 0224 QString newPrefix = prefixes.value(q->QXmlStreamReader::namespaceUri().toString()); 0225 0226 // The following code is because prefix() returns a QStringRef, 0227 // not a QString. So we need to make sure that the QString that 0228 // it references stays valid until the end of the document is 0229 // parsed. We do this by storing all prefix names that are 0230 // accessed in a QSet<QString> and return a QStringRef that 0231 // references the copy in the set. Ugly but effective. 0232 #if 1 0233 if (!prefixCache.contains(newPrefix)) { 0234 // FIXME: Is there a way to do this at the same time as the 0235 // check without creating a double copy if it was already inserted? 0236 prefixCache.insert(newPrefix); 0237 } 0238 0239 QSet<QString>::ConstIterator it = prefixCache.find(newPrefix); 0240 #else 0241 // This should work too but it's unclear from the documentation 0242 // what is returned if it was already in the set. It only 0243 // mentions "the inserted item" 0244 QSet<QString>::ConstIterator it = prefixCace.insert(newPrefix); 0245 #endif 0246 0247 // Will always succeed since we entered it if it didn't exist already. 0248 return (*it).leftRef(-1); 0249 } 0250 0251 QStringRef KoXmlStreamReader::Private::buildQName() 0252 { 0253 if (!isChecked) { 0254 checkSoundness(); // Sets isChecked and isSound; 0255 } 0256 0257 if (isSound) { 0258 return q->qualifiedName(); 0259 } 0260 0261 // FIXME: Handle undeclared prefixes. (Is that even legal?) 0262 //QString nsUri = q->QXmlStreamReader::namespaceUri().toString(); 0263 QString qualifiedName = prefixes.value(q->QXmlStreamReader::namespaceUri().toString()) 0264 + ':' + q->QXmlStreamReader::name().toString(); 0265 0266 // The following code is because qualifiedName() returns a 0267 // QStringRef, not a QString. So we need to make sure that the 0268 // QString that it references stays valid until the end of the 0269 // document is parsed. We do this by storing all qualified names 0270 // that are accessed in a QSet<QString> and return a QStringRef 0271 // that references the copy in the set. Ugly but effective. 0272 #if 1 0273 if (!qualifiedNamesCache.contains(qualifiedName)) { 0274 // FIXME: Is there a way to do this at the same time as the 0275 // check without creating a double copy if it was already inserted? 0276 qualifiedNamesCache.insert(qualifiedName); 0277 } 0278 0279 QSet<QString>::ConstIterator it = qualifiedNamesCache.find(qualifiedName); 0280 #else 0281 // This should work too but it's unclear from the documentation 0282 // what is returned if it was already in the set. It only 0283 // mentions "the inserted item" 0284 QSet<QString>::ConstIterator it = qualifiedNamesCache.insert(qualifiedName); 0285 #endif 0286 0287 // Will always succeed since we entered it if it didn't exist already. 0288 return (*it).leftRef(-1); 0289 } 0290 0291 0292 // ---------------------------------------------------------------- 0293 // class KoXmlStreamReader 0294 0295 0296 KoXmlStreamReader::KoXmlStreamReader() 0297 : QXmlStreamReader() 0298 , d(new KoXmlStreamReader::Private(this)) 0299 { 0300 } 0301 0302 KoXmlStreamReader::KoXmlStreamReader(QIODevice *device) 0303 : QXmlStreamReader(device) 0304 , d(new KoXmlStreamReader::Private(this)) 0305 { 0306 } 0307 0308 KoXmlStreamReader::KoXmlStreamReader(const QByteArray &data) 0309 : QXmlStreamReader(data) 0310 , d(new KoXmlStreamReader::Private(this)) 0311 { 0312 } 0313 0314 KoXmlStreamReader::KoXmlStreamReader(const QString &data) 0315 : QXmlStreamReader(data) 0316 , d(new KoXmlStreamReader::Private(this)) 0317 { 0318 } 0319 0320 KoXmlStreamReader::KoXmlStreamReader(const char *data) 0321 : QXmlStreamReader(data) 0322 , d(new KoXmlStreamReader::Private(this)) 0323 { 0324 } 0325 0326 KoXmlStreamReader::~KoXmlStreamReader() 0327 { 0328 delete d; 0329 } 0330 0331 0332 void KoXmlStreamReader::clear() 0333 { 0334 d->clear(); 0335 0336 QXmlStreamReader::clear(); 0337 } 0338 0339 0340 void KoXmlStreamReader::addExpectedNamespace(const QString &prefix, const QString &namespaceUri) 0341 { 0342 d->expectedNamespaces.insert(namespaceUri, prefix); 0343 0344 d->isChecked = false; 0345 d->isSound = false; 0346 } 0347 0348 void KoXmlStreamReader::addExtraNamespace(const QString &prefix, const QString &namespaceUri) 0349 { 0350 d->extraNamespaces.insert(namespaceUri, prefix); 0351 0352 d->isChecked = false; 0353 d->isSound = false; 0354 } 0355 0356 0357 // ---------------------------------------------------------------- 0358 // Reimplemented from QXmlStreamReader 0359 0360 0361 // Should these be made inline? that would make it very fast at the 0362 // cost of a possibly unstable API. 0363 0364 QStringRef KoXmlStreamReader::prefix() const 0365 { 0366 return d->isSound ? QXmlStreamReader::prefix() : d->buildNewPrefix(); 0367 } 0368 0369 QStringRef KoXmlStreamReader::qualifiedName() const 0370 { 0371 return d->isSound ? QXmlStreamReader::qualifiedName() : d->buildQName(); 0372 } 0373 0374 0375 void KoXmlStreamReader::setDevice(QIODevice *device) 0376 { 0377 // Setting the device clears the checked status since we don't know 0378 // which namespace declarations that will be in the new document. 0379 d->isChecked = false; 0380 d->isSound = false; 0381 0382 QXmlStreamReader::setDevice(device); 0383 } 0384 0385 KoXmlStreamAttributes KoXmlStreamReader::attributes() const 0386 { 0387 QXmlStreamAttributes qAttrs = QXmlStreamReader::attributes(); 0388 KoXmlStreamAttributes retval = KoXmlStreamAttributes(this, qAttrs); 0389 0390 return retval; 0391 } 0392 0393 0394 // ---------------------------------------------------------------- 0395 // private functions 0396 0397 0398 bool KoXmlStreamReader::isSound() const 0399 { 0400 return d->isSound; 0401 } 0402 0403 0404 // ================================================================ 0405 // class KoXmlStreamAttribute and Private class 0406 0407 0408 class Q_DECL_HIDDEN KoXmlStreamAttribute::Private 0409 { 0410 public: 0411 Private(const QXmlStreamAttribute *attr, const KoXmlStreamReader *r); 0412 Private(const KoXmlStreamAttribute::Private &other); 0413 ~Private(); 0414 0415 void generateQName(); 0416 0417 const QXmlStreamAttribute *qAttr; 0418 const KoXmlStreamReader *reader; 0419 0420 // These two are only used when the document is unsound 0421 QString qName; // qualifiedName if it was ever asked for. 0422 int prefixLen; // the length of the prefix alone. -1 means uninitialized. 0423 }; 0424 0425 KoXmlStreamAttribute::Private::Private(const QXmlStreamAttribute *attr, const KoXmlStreamReader *r) 0426 : qAttr(attr) 0427 , reader(r) 0428 , qName() 0429 , prefixLen(-1) 0430 { 0431 } 0432 0433 KoXmlStreamAttribute::Private::Private(const KoXmlStreamAttribute::Private &other) 0434 : qAttr(other.qAttr) 0435 , reader(other.reader) 0436 , qName(other.qName) 0437 , prefixLen(other.prefixLen) 0438 { 0439 } 0440 0441 KoXmlStreamAttribute::Private::~Private() 0442 { 0443 } 0444 0445 0446 void KoXmlStreamAttribute::Private::generateQName() 0447 { 0448 qName = reader->d->prefixes.value(qAttr->namespaceUri().toString()); 0449 prefixLen = qName.size(); 0450 0451 qName += QLatin1Char(':') + qAttr->name(); 0452 } 0453 0454 0455 // ---------------------------------------------------------------- 0456 0457 0458 0459 KoXmlStreamAttribute::KoXmlStreamAttribute() 0460 : d(new KoXmlStreamAttribute::Private(0, 0)) 0461 { 0462 //debugOdf2 << "default constructor called"; 0463 } 0464 0465 KoXmlStreamAttribute::KoXmlStreamAttribute(const QXmlStreamAttribute *attr, 0466 const KoXmlStreamReader *reader) 0467 : d(new KoXmlStreamAttribute::Private(attr, reader)) 0468 { 0469 //debugOdf2 << "normal constructor called"; 0470 } 0471 0472 KoXmlStreamAttribute::KoXmlStreamAttribute(const KoXmlStreamAttribute &other) 0473 : d(new KoXmlStreamAttribute::Private(*other.d)) 0474 { 0475 //debugOdf2 << "copy constructor called"; 0476 } 0477 0478 KoXmlStreamAttribute::~KoXmlStreamAttribute() 0479 { 0480 delete d; 0481 } 0482 0483 0484 bool KoXmlStreamAttribute::isDefault() const 0485 { 0486 return d->qAttr->isDefault(); 0487 } 0488 0489 QStringRef KoXmlStreamAttribute::name() const 0490 { 0491 return d->qAttr->name(); 0492 } 0493 0494 QStringRef KoXmlStreamAttribute::namespaceUri() const 0495 { 0496 return d->qAttr->namespaceUri(); 0497 } 0498 0499 0500 QStringRef KoXmlStreamAttribute::prefix() const 0501 { 0502 if (d->reader->isSound()) { 0503 return d->qAttr->prefix(); 0504 } 0505 0506 if (d->prefixLen == -1) { 0507 d->generateQName(); 0508 } 0509 0510 return d->qName.leftRef(d->prefixLen); 0511 } 0512 0513 0514 QStringRef KoXmlStreamAttribute::qualifiedName() const 0515 { 0516 if (d->reader->isSound()) { 0517 return d->qAttr->qualifiedName(); 0518 } 0519 0520 if (d->prefixLen == -1) { 0521 d->generateQName(); 0522 } 0523 0524 return d->qName.leftRef(-1); 0525 } 0526 0527 0528 QStringRef KoXmlStreamAttribute::value() const 0529 { 0530 return d->qAttr->value(); 0531 } 0532 0533 0534 bool KoXmlStreamAttribute::operator==(const KoXmlStreamAttribute &other) const 0535 { 0536 return d->qAttr == other.d->qAttr; 0537 } 0538 0539 bool KoXmlStreamAttribute::operator!=(const KoXmlStreamAttribute &other) const 0540 { 0541 return d->qAttr != other.d->qAttr; 0542 } 0543 0544 0545 KoXmlStreamAttribute &KoXmlStreamAttribute::operator=(const KoXmlStreamAttribute &other) 0546 { 0547 d->qAttr = other.d->qAttr; 0548 d->reader = other.d->reader; 0549 d->qName = other.d->qName; 0550 d->prefixLen = other.d->prefixLen; 0551 0552 return *this; 0553 } 0554 0555 0556 // ================================================================ 0557 // class KoXmlStreamAttributes and Private class 0558 0559 0560 class Q_DECL_HIDDEN KoXmlStreamAttributes::Private : public QSharedData 0561 { 0562 public: 0563 Private(const KoXmlStreamReader *r, const QXmlStreamAttributes &qa); 0564 ~Private(); 0565 0566 const KoXmlStreamReader *reader; 0567 QVector<KoXmlStreamAttribute> koAttrs; 0568 const QXmlStreamAttributes qAttrs; // We need the Q attributes to live while this class lives. 0569 }; 0570 0571 KoXmlStreamAttributes::Private::Private(const KoXmlStreamReader *r, const QXmlStreamAttributes &qa) 0572 : reader(r) 0573 , koAttrs(qa.size()) 0574 , qAttrs(qa) 0575 { 0576 } 0577 0578 KoXmlStreamAttributes::Private::~Private() 0579 { 0580 } 0581 0582 0583 // ---------------------------------------------------------------- 0584 0585 0586 KoXmlStreamAttributes::KoXmlStreamAttributes(const KoXmlStreamReader *r, 0587 const QXmlStreamAttributes &qAttrs) 0588 : d(new KoXmlStreamAttributes::Private(r, qAttrs)) 0589 { 0590 for (int i = 0; i < qAttrs.size(); ++i) { 0591 d->koAttrs[i] = KoXmlStreamAttribute(&qAttrs[i], d->reader); 0592 } 0593 } 0594 0595 KoXmlStreamAttributes::KoXmlStreamAttributes(const KoXmlStreamAttributes &other) 0596 : d(other.d) 0597 { 0598 } 0599 0600 KoXmlStreamAttributes::~KoXmlStreamAttributes() 0601 { 0602 // No delete because d is a QSharedDataPointer; 0603 } 0604 0605 KoXmlStreamAttributes &KoXmlStreamAttributes::operator=(const KoXmlStreamAttributes &other) 0606 { 0607 d = other.d; 0608 return *this; 0609 } 0610 0611 0612 // Relevant parts of the QVector API 0613 const KoXmlStreamAttribute& KoXmlStreamAttributes::at(int i) const 0614 { 0615 return d->koAttrs[i]; 0616 } 0617 0618 int KoXmlStreamAttributes::size() const 0619 { 0620 return d->koAttrs.size(); 0621 } 0622 0623 KoXmlStreamAttribute KoXmlStreamAttributes::value(int i) const 0624 { 0625 return d->koAttrs.value(i); 0626 } 0627 0628 const KoXmlStreamAttribute& KoXmlStreamAttributes::operator[](int i) const 0629 { 0630 return d->koAttrs[i];//.operator[](i); 0631 } 0632 0633 KoXmlStreamAttributes::const_iterator KoXmlStreamAttributes::begin() const 0634 { 0635 return const_iterator(d->koAttrs.begin()); 0636 } 0637 0638 KoXmlStreamAttributes::const_iterator KoXmlStreamAttributes::end() const 0639 { 0640 return const_iterator(d->koAttrs.end()); 0641 } 0642 0643 0644 // reimplemented from QXmlStreamAttributes 0645 bool KoXmlStreamAttributes::hasAttribute(const QString &qualifiedName) const 0646 { 0647 for (int i = 0; i < size(); ++i) { 0648 // This compares with the expected name always. 0649 if (qualifiedName == this->at(i).qualifiedName()) { 0650 return true; 0651 } 0652 } 0653 0654 return false; 0655 } 0656 0657 0658 bool KoXmlStreamAttributes::hasAttribute(const QLatin1String &qualifiedName) const 0659 { 0660 #if 1 0661 const QString qName(qualifiedName); 0662 return hasAttribute(qName); 0663 #else 0664 for (int i = 0; i < size(); ++i) { 0665 if (qualifiedName == this->at(i).qualifiedName()) { 0666 return true; 0667 } 0668 } 0669 0670 return false; 0671 #endif 0672 } 0673 0674 0675 QStringRef KoXmlStreamAttributes::value(const QString &qualifiedName) const 0676 { 0677 for (int i = 0; i < size(); ++i) { 0678 if (qualifiedName == this->at(i).qualifiedName()) { 0679 return this->at(i).value(); 0680 } 0681 } 0682 0683 return QStringRef(); 0684 } 0685 0686 0687 QStringRef KoXmlStreamAttributes::value(const QLatin1String &qualifiedName) const 0688 { 0689 // FIXME: Find faster way. 0690 const QString qName(qualifiedName); 0691 return value(qName); 0692 } 0693 0694 0695 // ================================================================ 0696 // non-class functions 0697 0698 0699 void prepareForOdf(KoXmlStreamReader &reader) 0700 { 0701 // This list of namespaces is taken from KoXmlNs.cpp 0702 // Maybe not all of them are expected in an ODF document? 0703 reader.addExpectedNamespace("office", "urn:oasis:names:tc:opendocument:xmlns:office:1.0"); 0704 reader.addExpectedNamespace("meta", "urn:oasis:names:tc:opendocument:xmlns:meta:1.0"); 0705 reader.addExpectedNamespace("config", "urn:oasis:names:tc:opendocument:xmlns:config:1.0"); 0706 reader.addExpectedNamespace("text", "urn:oasis:names:tc:opendocument:xmlns:text:1.0"); 0707 reader.addExpectedNamespace("table", "urn:oasis:names:tc:opendocument:xmlns:table:1.0"); 0708 reader.addExpectedNamespace("draw", "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"); 0709 reader.addExpectedNamespace("presentation", "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0"); 0710 reader.addExpectedNamespace("dr3d", "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0"); 0711 reader.addExpectedNamespace("chart", "urn:oasis:names:tc:opendocument:xmlns:chart:1.0"); 0712 reader.addExpectedNamespace("form", "urn:oasis:names:tc:opendocument:xmlns:form:1.0"); 0713 reader.addExpectedNamespace("script", "urn:oasis:names:tc:opendocument:xmlns:script:1.0"); 0714 reader.addExpectedNamespace("style", "urn:oasis:names:tc:opendocument:xmlns:style:1.0"); 0715 reader.addExpectedNamespace("number", "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"); 0716 reader.addExpectedNamespace("manifest", "urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"); 0717 reader.addExpectedNamespace("anim", "urn:oasis:names:tc:opendocument:xmlns:animation:1.0"); 0718 0719 reader.addExpectedNamespace("math", "http://www.w3.org/1998/Math/MathML"); 0720 reader.addExpectedNamespace("svg", "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"); 0721 reader.addExpectedNamespace("fo", "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"); 0722 reader.addExpectedNamespace("dc", "http://purl.org/dc/elements/1.1/"); 0723 reader.addExpectedNamespace("xlink", "http://www.w3.org/1999/xlink"); 0724 reader.addExpectedNamespace("VL", "http://openoffice.org/2001/versions-list"); 0725 reader.addExpectedNamespace("smil", "urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0"); 0726 reader.addExpectedNamespace("xhtml", "http://www.w3.org/1999/xhtml"); 0727 reader.addExpectedNamespace("xml", "http://www.w3.org/XML/1998/namespace"); 0728 0729 reader.addExpectedNamespace("calligra", "http://www.calligra.org/2005/"); 0730 reader.addExpectedNamespace("officeooo", "http://openoffice.org/2009/office"); 0731 reader.addExpectedNamespace("ooo", "http://openoffice.org/2004/office"); 0732 0733 reader.addExpectedNamespace("delta", "http://www.deltaxml.com/ns/track-changes/delta-namespace"); 0734 reader.addExpectedNamespace("split", "http://www.deltaxml.com/ns/track-changes/split-namespace"); 0735 reader.addExpectedNamespace("ac", "http://www.deltaxml.com/ns/track-changes/attribute-change-namespace"); 0736 0737 // This list of namespaces is taken from KoXmlReader::fixNamespace() 0738 // They were generated by old versions of OpenOffice.org. 0739 reader.addExtraNamespace("office", "http://openoffice.org/2000/office"); 0740 reader.addExtraNamespace("text", "http://openoffice.org/2000/text"); 0741 reader.addExtraNamespace("style", "http://openoffice.org/2000/style"); 0742 reader.addExtraNamespace("fo", "http://www.w3.org/1999/XSL/Format"); 0743 reader.addExtraNamespace("table", "http://openoffice.org/2000/table"); 0744 reader.addExtraNamespace("drawing", "http://openoffice.org/2000/drawing"); 0745 reader.addExtraNamespace("datastyle", "http://openoffice.org/2000/datastyle"); 0746 reader.addExtraNamespace("svg", "http://www.w3.org/2000/svg"); 0747 reader.addExtraNamespace("chart", "http://openoffice.org/2000/chart"); 0748 reader.addExtraNamespace("dr3d", "http://openoffice.org/2000/dr3d"); 0749 reader.addExtraNamespace("form", "http://openoffice.org/2000/form"); 0750 reader.addExtraNamespace("script", "http://openoffice.org/2000/script"); 0751 reader.addExtraNamespace("meta", "http://openoffice.org/2000/meta"); 0752 reader.addExtraNamespace("config", "http://openoffice.org/2001/config"); 0753 reader.addExtraNamespace("pres", "http://openoffice.org/2000/presentation"); 0754 reader.addExtraNamespace("manifest", "http://openoffice.org/2001/manifest"); 0755 }