diff --git a/src/xml/dom/qdomhelpers.cpp b/src/xml/dom/qdomhelpers.cpp index 39c7dcd360d..b58d2f7ae94 100644 --- a/src/xml/dom/qdomhelpers.cpp +++ b/src/xml/dom/qdomhelpers.cpp @@ -52,6 +52,35 @@ 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: '' + 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) { @@ -272,6 +301,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 f2a0a79c3a0..81de6e2e801 100644 --- a/src/xml/dom/qdomhelpers_p.h +++ b/src/xml/dom/qdomhelpers_p.h @@ -45,6 +45,7 @@ class QDomBuilder 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); @@ -61,6 +62,8 @@ class QDomBuilder int errorColumn; private: + QString dtdInternalSubset(const QString &dtd); + QDomDocumentPrivate *doc; QDomNodePrivate *node; QXmlStreamReader *reader; diff --git a/tests/auto/xml/dom/qdom/tst_qdom.cpp b/tests/auto/xml/dom/qdom/tst_qdom.cpp index f05020f61ca..0736e158fcc 100644 --- a/tests/auto/xml/dom/qdom/tst_qdom.cpp +++ b/tests/auto/xml/dom/qdom/tst_qdom.cpp @@ -97,6 +97,8 @@ private slots: void cloneDTD_QTBUG8398() const; void DTDNotationDecl(); void DTDEntityDecl(); + void DTDInternalSubset() const; + void DTDInternalSubset_data() const; void QTBUG49113_dontCrashWithNegativeIndex() const; void cleanupTestCase() const; @@ -2044,5 +2046,69 @@ void tst_QDom::QTBUG49113_dontCrashWithNegativeIndex() const QVERIFY(node.isNull()); } +void tst_QDom::DTDInternalSubset() const +{ + QFETCH( QString, doc ); + QFETCH( QString, internalSubset ); + QXmlStreamReader reader(doc); + QDomDocument document; + QVERIFY(document.setContent(&reader, true)); + + QCOMPARE(document.doctype().internalSubset(), internalSubset); +} + +void tst_QDom::DTDInternalSubset_data() const +{ + QTest::addColumn("doc"); + QTest::addColumn("internalSubset"); + + QTest::newRow("data1") << "\n" + "\n" + "\n" + << "" ; + + QTest::newRow("data2") << "\n" + "\n" + "\n" + << "" ; + + const QString internalSubset0( + "\n" + "\n" + ); + QTest::newRow("data3") << "\n" + "\n" + "\n" + << internalSubset0; + + const QString internalSubset1( + "\n" + "\n" + ); + QTest::newRow("data4") << "\n" + "\n" + "\n" + << internalSubset1; + + QTest::newRow("data5") << "\n" + "\n" + "\n" + << internalSubset0; + + QTest::newRow("data6") << "\n" + "\n" + "\n" + << internalSubset0; +} + QTEST_MAIN(tst_QDom) #include "tst_qdom.moc"