diff options
Diffstat (limited to 'src/xml/dom/qdomhelpers.cpp')
-rw-r--r-- | src/xml/dom/qdomhelpers.cpp | 86 |
1 files changed, 54 insertions, 32 deletions
diff --git a/src/xml/dom/qdomhelpers.cpp b/src/xml/dom/qdomhelpers.cpp index 39c7dcd360..0649e0c75d 100644 --- a/src/xml/dom/qdomhelpers.cpp +++ b/src/xml/dom/qdomhelpers.cpp @@ -8,6 +8,7 @@ #include "qdomhelpers_p.h" #include "qdom_p.h" #include "qxmlstream.h" +#include "private/qxmlstream_p.h" #include <memory> #include <stack> @@ -22,13 +23,9 @@ using namespace Qt::StringLiterals; * **************************************************************/ -QDomBuilder::QDomBuilder(QDomDocumentPrivate *d, QXmlStreamReader *r, bool namespaceProcessing) - : errorLine(0), - errorColumn(0), - doc(d), - node(d), - reader(r), - nsProcessing(namespaceProcessing) +QDomBuilder::QDomBuilder(QDomDocumentPrivate *d, QXmlStreamReader *r, + QDomDocument::ParseOptions options) + : doc(d), node(d), reader(r), parseOptions(options) { Q_ASSERT(doc); Q_ASSERT(reader); @@ -52,9 +49,40 @@ bool QDomBuilder::startDTD(const QString &name, const QString &publicId, const Q return true; } +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).sliced(dtd.indexOf(name) + name.size()); + + const QString &publicId = doc->doctype()->publicId; + if (!publicId.isEmpty()) + tmp = tmp.sliced(tmp.indexOf(publicId) + publicId.size()); + + const QString &systemId = doc->doctype()->systemId; + if (!systemId.isEmpty()) + tmp = tmp.sliced(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).sliced(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) { + const bool nsProcessing = + parseOptions.testFlag(QDomDocument::ParseOption::UseNamespaceProcessing); QDomNodePrivate *n = nsProcessing ? doc->createElementNS(nsURI, qName) : doc->createElement(qName); if (!n) @@ -139,14 +167,9 @@ bool QDomBuilder::skippedEntity(const QString &name) void QDomBuilder::fatalError(const QString &message) { - errorMsg = message; - errorLine = static_cast<int>(reader->lineNumber()); - errorColumn = static_cast<int>(reader->columnNumber()); -} - -QDomBuilder::ErrorInfo QDomBuilder::error() const -{ - return ErrorInfo(errorMsg, errorLine, errorColumn); + parseResult.errorMessage = message; + parseResult.errorLine = reader->lineNumber(); + parseResult.errorColumn = reader->columnNumber(); } bool QDomBuilder::startEntity(const QString &name) @@ -203,8 +226,9 @@ bool QDomBuilder::notationDecl(const QString &name, const QString &publicId, * **************************************************************/ -QDomParser::QDomParser(QDomDocumentPrivate *d, QXmlStreamReader *r, bool namespaceProcessing) - : reader(r), domBuilder(d, r, namespaceProcessing) +QDomParser::QDomParser(QDomDocumentPrivate *d, QXmlStreamReader *r, + QDomDocument::ParseOptions options) + : reader(r), domBuilder(d, r, options) { } @@ -213,11 +237,6 @@ bool QDomParser::parse() return parseProlog() && parseBody(); } -QDomBuilder::ErrorInfo QDomParser::errorInfo() const -{ - return domBuilder.error(); -} - bool QDomParser::parseProlog() { Q_ASSERT(reader); @@ -246,9 +265,9 @@ bool QDomParser::parseProlog() if (reader->isStandaloneDocument()) { value += u" standalone='yes'"_s; } else { - // TODO: Add standalone='no', if 'standalone' is specified. With the current - // QXmlStreamReader there is no way to figure out if it was specified or not. - // QXmlStreamReader needs to be modified for handling that case correctly. + // Add the standalone attribute only if it was specified + if (reader->hasStandaloneDeclaration()) + value += u" standalone='no'"_s; } if (!domBuilder.processingInstruction(u"xml"_s, value)) { @@ -272,6 +291,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; @@ -329,13 +350,14 @@ bool QDomParser::parseBody() } break; case QXmlStreamReader::Characters: - if (!reader->isWhitespace()) { // Skip the content consisting of only whitespaces - if (reader->isCDATA() || !reader->text().trimmed().isEmpty()) { - if (!domBuilder.characters(reader->text().toString(), reader->isCDATA())) { - domBuilder.fatalError(QDomParser::tr( - "Error occurred while processing the element content")); - return false; - } + // Skip the content if it contains only spacing characters, + // unless it's CDATA or PreserveSpacingOnlyNodes was specified. + if (reader->isCDATA() || domBuilder.preserveSpacingOnlyNodes() + || !(reader->isWhitespace() || reader->text().trimmed().isEmpty())) { + if (!domBuilder.characters(reader->text().toString(), reader->isCDATA())) { + domBuilder.fatalError( + QDomParser::tr("Error occurred while processing the element content")); + return false; } } break; |