如何抑制或自行处理QXmlSchemaValidator的错误输出信息
问题说明
你在使用QXmlSchemaValidator循环加载多个XSD校验XML内容时,校验失败时Qt默认会把XSD错误直接输出到控制台,占用输出窗口,需要抑制输出或自定义处理错误信息。
你当前的实现代码如下:
bool MyClass::verify(QByteArray message) { bool successfulValidated = false; for(QByteArray& xsd: _xsds) { QXmlSchema schema; schema.load(xsd); if(!schema.isValid()) throw Exception("schema not valid"); QXmlSchemaValidator msgValidator(schema); if(msgValidator.validate(message)) { successfulValidated = true; break; } } return successfulValidated; }
默认输出的错误格式类似:
Error XSDError in file:///MyApplication.exe, at line 1, column 47: No definition for element MyXMLElement available.
解决方案
Qt的XML Patterns模块所有错误、警告信息的输出都通过QAbstractMessageHandler派生类处理,默认的实现会直接把信息打印到控制台。你只需要替换默认的消息处理器,就可以完全拦截这些信息,选择抑制或自定义处理。
步骤1:实现自定义消息处理器
继承QAbstractMessageHandler重写handleMessage方法,所有XSD加载、XML校验阶段的信息都会传入这个方法:
#include <QAbstractMessageHandler> #include <QString> #include <QSourceLocation> #include <QUrl> class ValidationMessageHandler : public QAbstractMessageHandler { public: ValidationMessageHandler(QObject *parent = nullptr) : QAbstractMessageHandler(parent) {} // 对外提供最近一次的错误信息,供业务逻辑使用 QString getLastError() const { return m_lastError; } void reset() { m_lastError.clear(); } protected: void handleMessage(QtMsgType type, const QString &description, const QUrl &identifier, const QSourceLocation &sourceLocation) override { Q_UNUSED(type) Q_UNUSED(identifier) // 若要完全抑制输出,直接return即可,不需要拼接或打印任何内容 m_lastError = QString("位置:%0,行:%1,列:%2,错误:%3") .arg(sourceLocation.uri().toString()) .arg(sourceLocation.line()) .arg(sourceLocation.column()) .arg(description); } private: QString m_lastError; };
步骤2:替换Schema和Validator的默认消息处理器
在加载XSD、执行校验前,给QXmlSchema和QXmlSchemaValidator设置你自定义的消息处理器,即可接管所有错误信息。修改后的校验方法如下:
bool MyClass::verify(QByteArray message) { bool successfulValidated = false; ValidationMessageHandler msgHandler; for(QByteArray& xsd: _xsds) { QXmlSchema schema; // 拦截XSD加载阶段的错误 schema.setMessageHandler(&msgHandler); msgHandler.reset(); schema.load(xsd); if(!schema.isValid()) { throw Exception(QString("schema not valid: %0").arg(msgHandler.getLastError()).toStdString()); } QXmlSchemaValidator msgValidator(schema); // 拦截XML校验阶段的错误 msgValidator.setMessageHandler(&msgHandler); msgHandler.reset(); if(msgValidator.validate(message)) { successfulValidated = true; break; } // 此处可通过msgHandler.getLastError()获取当前校验失败的具体信息,自行做日志存储、提示等处理 } return successfulValidated; }
注意事项
- 消息处理器对象的生命周期必须覆盖
QXmlSchema和QXmlSchemaValidator的使用周期,避免出现野指针。 - 如果不需要获取错误详情,只需要屏蔽控制台输出,
handleMessage方法内直接写return;即可,不需要实现错误信息存储逻辑。 - 该方案可以同时拦截XSD本身无效、XML内容不符合Schema两类错误,不会有遗漏的默认输出。
内容的提问来源于stack exchange,提问作者Olloxan
相关产品推荐
相关产品推荐

