我正在尝试阅读并验证具有外部实体的xml文档。但是我在阅读和验证方面都没有成功。 我使用this创建了一个测试示例。
测试xml:
<?xml version="1.0" standalone="no" ?>
<!DOCTYPE doc [
<!ENTITY otherFile SYSTEM "otherFile.xml">
]>
<doc>&otherFile;</doc>
其他xml:
<baz>this is my content</baz>
测试xsd:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="doc">
<xs:complexType>
<xs:sequence>
<xs:element ref="baz"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="baz" type="xs:string"/>
</xs:schema>
首先,我尝试使用QDomDocument
读取test.xml的内容:
QDomDocument doc;
doc.setContent(&testFile);
qDebug() << doc.toString();
但是在调试输出中,我从test.xml获取原始文本。外部实体未被替换。
然后我尝试针对test.xsd验证test.xml:
QXmlSchema schema;
bool res = schema.load(&xsdFile, QUrl::fromLocalFile(xsdPath));
if (res == true)
{
QXmlSchemaValidator validator(schema);
if (validator.validate(&xmlFile, QUrl::fromLocalFile(xmlPath)))
{
qDebug() << "xml" << xmlName << "is valid";
}
else
{
qDebug() << "xml" << xmlName << "is invalid";
}
}
但验证失败,我收到以下错误:
Error XSDError in file:///..., at line 5, column 5: Element doc is missing child element.
我做错了什么或者Qt Xml模块不支持外部实体?
答案 0 :(得分:4)
我已经为您了解了这一点,简短的回答是,如果您想要DTD SYSTEM实体支持,我认为您可能需要更改为使用不同的解析器和验证器。
Qt 4有三种不同的XML解析器:
QXmlStreamReader
- 拉解析器,QtCore的一部分,现在是推荐的解析器QXmlSimpleReader
- 推送(事件)解析器,QtXML的一部分QDomDocument
- DOM解析器,QtXML的一部分有3种不同类型的解析器被认为过于复杂,所以移动到Qt 5时,XML模块已被弃用,推荐的解析器现在是 QXmlStreamReader 。这是一个非常容易使用的解析器(与 QXmlSimpleReader 不同),但内存使用率远低于 QDomDocument 。
因此,如果您在Qt中编写用于XML解析的新代码,即使您当前没有使用Qt 5,我强烈建议您使用 QXmlStreamReader 。
不幸的是,手册页注释:
QXmlStreamReader是一个格式良好的XML 1.0解析器,不包含外部解析实体。
这意味着,它无法解析您的SYSTEM实体。此外,在检查源代码之后,看起来不存在可用于拦截实体解析的任何“隐藏”钩子或方法。
如果要将外部XML文档包含到其他文档中,可能需要查看使用XInclude。使用 QXmlStreamReader 和QXmlStreamWriter编写XInclude处理器相当简单。
这是我写的basic Qt XInclude processor,它只包含一个级别,但我相信你可以扩展它以合理地轻松支持递归包含。
获得完全解析的XML文档后,您应该能够使用 QXmlSchemaValidator 对其进行验证。