diff options
-rw-r--r-- | src/xml/doc/src/qt6-changes.qdoc | 9 | ||||
-rw-r--r-- | src/xml/dom/qdom.cpp | 6 | ||||
-rw-r--r-- | src/xml/dom/qdom.h | 1 | ||||
-rw-r--r-- | src/xml/dom/qdomhelpers.cpp | 15 | ||||
-rw-r--r-- | src/xml/dom/qdomhelpers_p.h | 3 | ||||
-rw-r--r-- | tests/auto/xml/dom/qdom/tst_qdom.cpp | 61 |
6 files changed, 87 insertions, 8 deletions
diff --git a/src/xml/doc/src/qt6-changes.qdoc b/src/xml/doc/src/qt6-changes.qdoc index 3ee4d103c6..cca6aa9317 100644 --- a/src/xml/doc/src/qt6-changes.qdoc +++ b/src/xml/doc/src/qt6-changes.qdoc @@ -73,6 +73,15 @@ If you use QDomDocument and rely on any of these, you must update your code and XML documents accordingly. + \section3 Spacing-only text nodes + + By default, text nodes containing only spacing characters are stripped + and won't appear in the QDomDocument. The Qt 5 way of changing this behavior + was using the QDomDocument::setContent() overload that allowed a \c QXmlReader + to be supplied. That overload was removed in Qt 6.0, but since Qt 6.5, + you can pass QDomDocument::ParseOption::PreserveSpacingOnlyNodes as a parse + option, to specify that spacing-only text nodes must be preserved. + \section2 Qt Core5 compatibility library If your application or library cannot be ported right now, the \l diff --git a/src/xml/dom/qdom.cpp b/src/xml/dom/qdom.cpp index 74ea7d1e4e..b2fcac7f1b 100644 --- a/src/xml/dom/qdom.cpp +++ b/src/xml/dom/qdom.cpp @@ -6221,6 +6221,8 @@ bool QDomDocument::setContent(QXmlStreamReader *reader, bool namespaceProcessing \value Default No parse options are set. \value UseNamespaceProcessing Namespace processing is enabled. + \value PreserveSpacingOnlyNodes Text nodes containing only spacing + characters are preserved. \sa setContent() */ @@ -6307,7 +6309,9 @@ bool QDomDocument::setContent(QXmlStreamReader *reader, bool namespaceProcessing string if the element or attribute has no prefix. Text nodes consisting only of whitespace are stripped and won't - appear in the QDomDocument. + appear in the QDomDocument. Since Qt 6.5, one can pass + QDomDocument::ParseOption::PreserveSpacingOnlyNodes as a parse + option, to specify that spacing-only text nodes must be preserved. \include qdom.cpp entity-refs diff --git a/src/xml/dom/qdom.h b/src/xml/dom/qdom.h index f4c0da1b16..390a319553 100644 --- a/src/xml/dom/qdom.h +++ b/src/xml/dom/qdom.h @@ -268,6 +268,7 @@ public: enum class ParseOption { Default = 0x00, UseNamespaceProcessing = 0x01, + PreserveSpacingOnlyNodes = 0x02, }; Q_DECLARE_FLAGS(ParseOptions, ParseOption) diff --git a/src/xml/dom/qdomhelpers.cpp b/src/xml/dom/qdomhelpers.cpp index 2a4d4c5b3a..62258fbdfd 100644 --- a/src/xml/dom/qdomhelpers.cpp +++ b/src/xml/dom/qdomhelpers.cpp @@ -349,13 +349,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; diff --git a/src/xml/dom/qdomhelpers_p.h b/src/xml/dom/qdomhelpers_p.h index 73177981b5..5a4b2207f9 100644 --- a/src/xml/dom/qdomhelpers_p.h +++ b/src/xml/dom/qdomhelpers_p.h @@ -56,6 +56,9 @@ public: void fatalError(const QString &message); QDomDocument::ParseResult result() const { return parseResult; } + bool preserveSpacingOnlyNodes() const + { return parseOptions & QDomDocument::ParseOption::PreserveSpacingOnlyNodes; } + private: QString dtdInternalSubset(const QString &dtd); diff --git a/tests/auto/xml/dom/qdom/tst_qdom.cpp b/tests/auto/xml/dom/qdom/tst_qdom.cpp index c537b8ec70..71c65ea78d 100644 --- a/tests/auto/xml/dom/qdom/tst_qdom.cpp +++ b/tests/auto/xml/dom/qdom/tst_qdom.cpp @@ -32,6 +32,8 @@ private slots: void setContent(); void setContentOverloads(); void parseOptions(); + void spacingOnlyNodes_data() const; + void spacingOnlyNodes() const; void parseResult(); void toString_01_data(); void toString_01(); @@ -292,6 +294,65 @@ void tst_QDom::parseOptions() } } +void tst_QDom::spacingOnlyNodes_data() const +{ + QTest::addColumn<QString>("input"); + QTest::addColumn<QString>("expected"); + QTest::addColumn<QDomDocument::ParseOption>("options"); + + QTest::newRow("spacing-only-remove") + << u"<a> \t \n \r</a>"_s + << u"<a/>"_s + << QDomDocument::ParseOption::Default; + // \r is translated to \n, see https://www.w3.org/TR/xml11/#sec-line-ends + QTest::newRow("spacing-only-preserve") + << u"<a> \t \n \r</a>"_s + << u"<a> \t \n \n</a>"_s + << QDomDocument::ParseOption::PreserveSpacingOnlyNodes; + QTest::newRow("mixed-text-remove") + << u"<a> abc \t \n \r</a>"_s + << u"<a> abc \t \n \n</a>"_s + << QDomDocument::ParseOption::Default; + QTest::newRow("mixed-text-preserve") + << u"<a> abc \t \n \r</a>"_s + << u"<a> abc \t \n \n</a>"_s + << QDomDocument::ParseOption::PreserveSpacingOnlyNodes; + + // QDomDocument treats all chacarcters below as spaces (see QTBUG-105348) + static constexpr char16_t spaces[] = { + QChar::Space, QChar::Tabulation, QChar::LineFeed, + QChar::CarriageReturn, QChar::Nbsp, + 0x2002, // EN SPACE + 0x2003, // EM SPACE + 0x2009 // THIN SPACE + }; + + for (char16_t space : spaces) { + QTest::addRow("spacing-remove-u%04x", space) + << u"<a>"_s + space + u"</a>"_s + << u"<a/>"_s + << QDomDocument::ParseOption::Default; + + // \r is translated to \n, see https://www.w3.org/TR/xml11/#sec-line-ends + char16_t expected = (space == QChar::CarriageReturn) ? char16_t(QChar::LineFeed) : space; + QTest::addRow("spacing-preserve-u%04x", space) + << u"<a>"_s + space + u"</a>"_s + << u"<a>"_s + expected + u"</a>"_s + << QDomDocument::ParseOption::PreserveSpacingOnlyNodes; + } +} + +void tst_QDom::spacingOnlyNodes() const +{ + QFETCH(QString, input); + QFETCH(QString, expected); + QFETCH(QDomDocument::ParseOption, options); + + QDomDocument doc; + QVERIFY(doc.setContent(input, options)); + QCOMPARE(doc.toString(-1), expected); +} + void tst_QDom::parseResult() { QString input = u"<doc xmlns:b='http://example.com/'>" |