Add QDom internalSubset implementation
QDom's internalSubset() always returned empty because nothing actually set the internal data member it returns. When parsing the DECLTYPE, extract the internal subset and save it to the doctype()'s member when present. Fixes: QTBUG-53661 Change-Id: I6e41ff8b914381168246073b3289d82205b1c255 Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io> (cherry picked from commit c3b959733a739e9b2fc00b2af469fa44f3048e29) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
0398679726
commit
acaed119e0
@ -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: '<!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)
|
||||
{
|
||||
@ -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;
|
||||
|
@ -45,6 +45,7 @@ public:
|
||||
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 @@ public:
|
||||
int errorColumn;
|
||||
|
||||
private:
|
||||
QString dtdInternalSubset(const QString &dtd);
|
||||
|
||||
QDomDocumentPrivate *doc;
|
||||
QDomNodePrivate *node;
|
||||
QXmlStreamReader *reader;
|
||||
|
@ -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<QString>("doc");
|
||||
QTest::addColumn<QString>("internalSubset");
|
||||
|
||||
QTest::newRow("data1") << "<?xml version='1.0'?>\n"
|
||||
"<!DOCTYPE note SYSTEM '/[abcd].dtd'>\n"
|
||||
"<note/>\n"
|
||||
<< "" ;
|
||||
|
||||
QTest::newRow("data2") << "<?xml version='1.0'?>\n"
|
||||
"<!DOCTYPE note PUBLIC '-/freedesktop' 'https://[abcd].dtd'>\n"
|
||||
"<note/>\n"
|
||||
<< "" ;
|
||||
|
||||
const QString internalSubset0(
|
||||
"<!-- open brackets comment [ -->\n"
|
||||
"<!-- colse brackets comment ] -->\n"
|
||||
);
|
||||
QTest::newRow("data3") << "<?xml version='1.0'?>\n"
|
||||
"<!DOCTYPE note ["
|
||||
+ internalSubset0 +
|
||||
"]>\n"
|
||||
"<note/>\n"
|
||||
<< internalSubset0;
|
||||
|
||||
const QString internalSubset1(
|
||||
"<!ENTITY obra '['>\n"
|
||||
"<!ENTITY cbra ']'>\n"
|
||||
);
|
||||
QTest::newRow("data4") << "<?xml version='1.0'?>\n"
|
||||
"<!DOCTYPE note ["
|
||||
+ internalSubset1 +
|
||||
"]>\n"
|
||||
"<note/>\n"
|
||||
<< internalSubset1;
|
||||
|
||||
QTest::newRow("data5") << "<?xml version='1.0'?>\n"
|
||||
"<!DOCTYPE note PUBLIC '-/freedesktop' 'https://[abcd].dtd' ["
|
||||
+ internalSubset0
|
||||
+ "]>\n"
|
||||
"<note/>\n"
|
||||
<< internalSubset0;
|
||||
|
||||
QTest::newRow("data6") << "<?xml version='1.0'?>\n"
|
||||
"<!DOCTYPE note PUBLIC '-/freedesktop' "
|
||||
"'2001:db8:130F:0000:0000:09C0:876A:130B://[abcd].dtd' ["
|
||||
+ internalSubset0
|
||||
+ "]>\n"
|
||||
"<note/>\n"
|
||||
<< internalSubset0;
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QDom)
|
||||
#include "tst_qdom.moc"
|
||||
|
Loading…
x
Reference in New Issue
Block a user