diff options
Diffstat (limited to 'src/xml')
-rw-r--r-- | src/xml/dom/qdom.cpp | 23 | ||||
-rw-r--r-- | src/xml/dom/qdomhelpers.cpp | 31 | ||||
-rw-r--r-- | src/xml/dom/qdomhelpers_p.h | 3 |
3 files changed, 53 insertions, 4 deletions
diff --git a/src/xml/dom/qdom.cpp b/src/xml/dom/qdom.cpp index 104ed1b48e..45da7f961d 100644 --- a/src/xml/dom/qdom.cpp +++ b/src/xml/dom/qdom.cpp @@ -62,7 +62,7 @@ #include <qdebug.h> #include <qxmlstream.h> #include <private/qduplicatetracker_p.h> - +#include <private/qstringiterator_p.h> #include <stdio.h> #include <limits> @@ -192,11 +192,26 @@ static QString fixedCharData(const QString &data, bool *ok) return data; } + // Copied from QChar::fromUcs4() implementation in Qt 6 + auto fromUcs4 = [](char32_t c) noexcept { + struct R { + char16_t chars[2]; + operator QStringView() const noexcept { return {begin(), end()}; } + qsizetype size() const noexcept { return chars[1] ? 2 : 1; } + const char16_t *begin() const noexcept { return chars; } + const char16_t *end() const noexcept { return begin() + size(); } + }; + if (QChar::requiresSurrogates(c)) + return R{{QChar::highSurrogate(c), QChar::lowSurrogate(c)}}; + return R{{char16_t(c), u'\0'}}; + }; + QString result; - for (int i = 0; i < data.size(); ++i) { - QChar c = data.at(i); + QStringIterator it(data); + while (it.hasNext()) { + const char32_t c = it.next(QChar::Null); if (QXmlUtils::isChar(c)) { - result.append(c); + result.append(fromUcs4(c)); } else if (QDomImplementationPrivate::invalidDataPolicy == QDomImplementation::ReturnNullNode) { *ok = false; return QString(); diff --git a/src/xml/dom/qdomhelpers.cpp b/src/xml/dom/qdomhelpers.cpp index 7a9ae1a46c..0f72e314c8 100644 --- a/src/xml/dom/qdomhelpers.cpp +++ b/src/xml/dom/qdomhelpers.cpp @@ -300,6 +300,35 @@ inline QString stringRefToString(const QStringRef &stringRef) return stringRef.isNull() ? QString() : stringRef.toString(); } +QString QDomBuilder::dtdInternalSubset(const QString &dtd) +{ + // https://www.w3.org/TR/xml/#NT-intSubset + // doctypedecl: '<!DOCTYPE' S Name (S ExternalID)? S? ('[' intSubset ']' S?)? '>' + const QString &name = doc->doctype()->name; + QStringView tmp = QStringView(dtd).mid(dtd.indexOf(name) + name.size()); + + const QString &publicId = doc->doctype()->publicId; + if (!publicId.isEmpty()) + tmp = tmp.mid(tmp.indexOf(publicId) + publicId.size()); + + const QString &systemId = doc->doctype()->systemId; + if (!systemId.isEmpty()) + tmp = tmp.mid(tmp.indexOf(systemId) + systemId.size()); + + const qsizetype obra = tmp.indexOf(u'['); + const qsizetype cbra = tmp.lastIndexOf(u']'); + if (obra >= 0 && cbra >= 0) + return tmp.left(cbra).mid(obra + 1).toString(); + + return QString(); +} + +bool QDomBuilder::parseDTD(const QString &dtd) +{ + doc->doctype()->internalSubset = dtdInternalSubset(dtd); + return true; +} + bool QDomBuilder::startElement(const QString &nsURI, const QString &qName, const QXmlStreamAttributes &atts) { @@ -520,6 +549,8 @@ bool QDomParser::parseProlog() QDomParser::tr("Error occurred while processing document type declaration")); return false; } + if (!domBuilder.parseDTD(reader->text().toString())) + return false; if (!parseMarkupDecl()) return false; break; diff --git a/src/xml/dom/qdomhelpers_p.h b/src/xml/dom/qdomhelpers_p.h index 4de18f7d4d..1649a4097d 100644 --- a/src/xml/dom/qdomhelpers_p.h +++ b/src/xml/dom/qdomhelpers_p.h @@ -143,6 +143,7 @@ QT_WARNING_POP bool startEntity(const QString &name); bool endEntity(); bool startDTD(const QString &name, const QString &publicId, const QString &systemId); + bool parseDTD(const QString &dtd); bool comment(const QString &characters); bool externalEntityDecl(const QString &name, const QString &publicId, const QString &systemId); bool notationDecl(const QString &name, const QString &publicId, const QString &systemId); @@ -159,6 +160,8 @@ QT_WARNING_POP int errorColumn; private: + QString dtdInternalSubset(const QString &dtd); + QDomDocumentPrivate *doc; QDomNodePrivate *node; QXmlDocumentLocator *locator; |