来自资源与 noNamespaceSchemaLocation 的 Qt Schema 验证
Qt Schema validation from resource vs noNamespaceSchemaLocation
抱歉提前阅读了很长时间,我尽量保持简洁。请随时要求我详细说明某些方面,或编辑和删除某些部分以增强此问题。
背景:
我们有一个可以与许多模块(守护进程)交互的应用程序。
每个模块都是从数据库中的 XML 配置的。
当有人手动编辑 XML 配置(在总部和现场)时,我们有时不得不调试问题,所以我自己在运行时验证 XML,所以我们可以更早地发现这些配置问题:
/*---------------------------------------------------------------------------
**
*/
bool BaseApplication::validateXML(const QDomDocument& doc, const QString& schema)
{
QFile xsdfile(schema);
if (xsdfile.open(QFile::ReadOnly)) {
QXmlSchema xsd;
xsd.load(&xsdfile);
if (xsd.isValid()) {
QXmlSchemaValidator validator(xsd);
const QString xml = doc.toString();
return validator.validate(xml.toLatin1());
}
else {
qWarning("BaseApplication::validateXML() - schema \"%s\" is not well-formed", qPrintable(schema));
}
}
else {
qWarning("BaseApplication::validateXML() - unable to open schema \"%s\"", qPrintable(schema));
}
return false;
}
所有模块都有一个派生自此 BaseApplication
的应用程序 class。它是更大框架的一部分。
所以 bootstrap 的应用程序可以做类似的事情:
void Application::preBegin()
{
...
const QDomDocument config = // load XML from database
if (!validateXML(config, ":schema.xsd")) {
qFatal("Application::preBegin() - configuration is not valid");
}
...
}
但是这样做仍然完全是可选的(每个模块)。
这在我们的工程环境中一切正常。
问题:
由于{原因过于复杂和分散注意力},设置和维护大型客户系统的部门编写了生成各种模块 XML 配置的脚本,以包括(除其他外)noNamespaceSchemaLocation
.
所以典型的模块配置不是这样的:
<configuration>
<!--XML struct here-->
</configuration>
它们是这样写的:
<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" schema_version="1" xsi:noNamespaceSchemaLocation="{url to XSD file on intranet server}">
<!--XML struct here-->
</configuration>
(模块将这些额外属性视为元数据)
这会导致具有内置 XSD 验证的模块出现问题。在加载和验证模块的 XML 配置的运行时,我们看到了奇怪的行为(UB?)。即使这是单线程中的同步进程,调试日志也会显示在 Application::preBegin()
之前发生的事件应该在之后发生。
我们还看到在 XML 验证中丢失了整整一分钟(精确到秒)。
从根对象中手动删除 noNamespaceSchemaLocation 属性可以解决此问题。
然后验证立即发生,事件根据日志以正确的顺序发生。
问题:
是否有任何我可以添加到 BaseApplication::validateXML()
中的 /call 的内容,这可能会导致例程忽略它试图验证的 XML 中提及的任何 noNamespaceSchemaLocation
?
验证例程尝试解析 xml 架构位置时,1 分钟超时可能是 tcpip 超时。
您可以做的是在验证之前从配置文件中删除所有命名空间。将原始配置解析为 xml 文档,并让这个问题 How to remove all namespaces from XML with C#? 的解决方案从中删除名称空间。然后可以根据架构验证清理后的字符串结果。
抱歉提前阅读了很长时间,我尽量保持简洁。请随时要求我详细说明某些方面,或编辑和删除某些部分以增强此问题。
背景:
我们有一个可以与许多模块(守护进程)交互的应用程序。
每个模块都是从数据库中的 XML 配置的。
当有人手动编辑 XML 配置(在总部和现场)时,我们有时不得不调试问题,所以我自己在运行时验证 XML,所以我们可以更早地发现这些配置问题:
/*---------------------------------------------------------------------------
**
*/
bool BaseApplication::validateXML(const QDomDocument& doc, const QString& schema)
{
QFile xsdfile(schema);
if (xsdfile.open(QFile::ReadOnly)) {
QXmlSchema xsd;
xsd.load(&xsdfile);
if (xsd.isValid()) {
QXmlSchemaValidator validator(xsd);
const QString xml = doc.toString();
return validator.validate(xml.toLatin1());
}
else {
qWarning("BaseApplication::validateXML() - schema \"%s\" is not well-formed", qPrintable(schema));
}
}
else {
qWarning("BaseApplication::validateXML() - unable to open schema \"%s\"", qPrintable(schema));
}
return false;
}
所有模块都有一个派生自此 BaseApplication
的应用程序 class。它是更大框架的一部分。
所以 bootstrap 的应用程序可以做类似的事情:
void Application::preBegin()
{
...
const QDomDocument config = // load XML from database
if (!validateXML(config, ":schema.xsd")) {
qFatal("Application::preBegin() - configuration is not valid");
}
...
}
但是这样做仍然完全是可选的(每个模块)。 这在我们的工程环境中一切正常。
问题:
由于{原因过于复杂和分散注意力},设置和维护大型客户系统的部门编写了生成各种模块 XML 配置的脚本,以包括(除其他外)noNamespaceSchemaLocation
.
所以典型的模块配置不是这样的:
<configuration>
<!--XML struct here-->
</configuration>
它们是这样写的:
<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" schema_version="1" xsi:noNamespaceSchemaLocation="{url to XSD file on intranet server}">
<!--XML struct here-->
</configuration>
(模块将这些额外属性视为元数据)
这会导致具有内置 XSD 验证的模块出现问题。在加载和验证模块的 XML 配置的运行时,我们看到了奇怪的行为(UB?)。即使这是单线程中的同步进程,调试日志也会显示在 Application::preBegin()
之前发生的事件应该在之后发生。
我们还看到在 XML 验证中丢失了整整一分钟(精确到秒)。
从根对象中手动删除 noNamespaceSchemaLocation 属性可以解决此问题。 然后验证立即发生,事件根据日志以正确的顺序发生。
问题:
是否有任何我可以添加到 BaseApplication::validateXML()
中的 /call 的内容,这可能会导致例程忽略它试图验证的 XML 中提及的任何 noNamespaceSchemaLocation
?
验证例程尝试解析 xml 架构位置时,1 分钟超时可能是 tcpip 超时。
您可以做的是在验证之前从配置文件中删除所有命名空间。将原始配置解析为 xml 文档,并让这个问题 How to remove all namespaces from XML with C#? 的解决方案从中删除名称空间。然后可以根据架构验证清理后的字符串结果。