【问题标题】:Reporting detailed XML errors when using QDomDocument使用 QDomDocument 时报告详细的 XML 错误
【发布时间】:2016-04-12 14:43:39
【问题描述】:

我目前正在修改一些使用 QDomDocument 解析 XML 文件内容的旧代码。示例代码如下:

QFile file(file_.filePath());   

if (file.open(QIODevice::ReadOnly)) 
{
    QTextStream in(&file);
    file.close();

    QString errorMsg;
    int errorLine;
    int errorColumn;

    if (!doc.setContent(in.readAll(), &errorMsg, &errorLine, &errorColumn))
    {
        qWarning("Invalid XML in file %s. Error = %s, Line = %d, Column = %d", qPrintable(file_name), qPrintable(errorMsg), errorLine, errorColumn);
    }
}

不幸的是,错误报告非常有限。删除文件中途的结束标签只会报告以下错误:

文件 config.xml 中的 XML 无效。错误 = 文件意外结束,行 = 1,列 = 1

这是相当无用的。

关于如何从 Qt 的 XML 解析器中获取更多描述性错误的任何建议?准确的行号将是一个好的开始。

附:我使用的是 Qt 4.7.4 版。

【问题讨论】:

  • QDomDocument 是旧的、不受支持的 QtXML 模块的一部分。最好的办法是改用QXMLStreamReader 重写它。

标签: c++ xml qt qt4


【解决方案1】:

QDomDocument::setContent 应该为您提供正确的信息以了解问题所在。

例如,用这个 sn-p 的代码:

#include <QtXml>
#include <QtCore>

int main()
{
    QFile file(":/myxml_error.xml");

    qDebug() << "File path:" << QFileInfo(file).absoluteFilePath();
    qDebug() << "File exists:" << file.exists();

    file.open(QFile::ReadOnly|QFile::Text);

    qDebug() << "File open:" << file.isOpen();

    QDomDocument dom;
    QString error;

    int line, column;

    if(dom.setContent(&file, &error, &line, &column)){
        qDebug() << dom.toString(4);
    } else {
        qDebug() << "Error:" << error << "in line " << line << "column" << column;
    }
    return 0;
}

还有这个 xml 文件:

<?xml version="1.0" encoding="UTF-8"?>
<note>
    <to>Tove</to>
    <from>Jani</Ffrom>
    <heading>Reminder</heading>
    <body>Don't forget me this weekend!</body>
</note>

我们看到以下错误:

Error: "tag mismatch" in line 4 column 19

在阅读了@kh25 的一些 cmets 后,我更新了这个答案。

  • 问题可能是由文件编码引起的。在这种情况下,我们可以尝试删除回车和新行。如果我们在 Linux 上工作,dos2unix 可以提供帮助。
  • 另一种选择是使用online tool 来检查 XML。

但在这种特殊情况下,问题似乎与在调用in.readAll() 之前关闭文件有关——file.close()。在这种情况下,QDomDocument::setContent 正在读取一个空字符串,我们会看到错误 unexpected end of file

获取错误的另一种方法是在文件到达流末尾时调用QDomDocument::setContent

所以,如果我们调用 QTextStream::readAll() 两次,我们会得到同样的错误。即:

QTextStream in(&file);
in.readAll();

if(dom.setContent(in.readAll(), &error, &line, &column)) {
    qDebug() << "Content: " << dom.toString(4);
} else {        
    qDebug() << "Error:" << error << "in line " << line << "column" << column;
}

@MrEricSir 评论了使用QXMLStreamReader。如果你需要一个例子,我在GitHub 有一个小项目,我使用了那个类。

【讨论】:

  • 我认为这不是 kh25 的情况,这里可以在不匹配的结束标记处检测到不一致,而在 kh25 中,文档一直有效,但不完整。
  • 谢谢塔罗德。你是100%正确的先生。对于这种情况,如果您直接使用该文件,您将获得更准确的错误报告。使用 QTextStream 并将 QString 传递给同一个函数会导致一组不太清晰的错误。我不确定为什么最初编写这段代码是为了使用 QTextStream(可能早期版本的 Qt 不支持 setContent() 的 QFile 参数),但我已经更新,现在好多了。有一个标记。也许有人可以解释为什么表示 XML 块的 QString 的错误处理能力如此差。
  • @kh25 哦,太好了! :) 所以问题不在于编码,而是QTextStream。我应该更新我的答案,但是如果我们使用QTextStream,我想做一些测试来验证为什么会出现这个问题。 setContent 似乎只获取文件的最后一行。
  • @kh25 我已经更新了我的答案。您能否尝试不关闭文件并检查原始问题是否发生?
  • Tarod 我可以确认,正如您所建议的,问题是由于在 in.readAll() 之前调用了 file.close()。这实际上不是 QDomDocument.setContent() 的问题。在 file.close() 之后调用时检查 in.readAll() 的返回值只会产生一个空白字符串,而不是 XML 内容,这就是我得到这些一般错误的原因。这就是为什么切换到只传递 QFile 起作用的原因。再次感谢。
【解决方案2】:

报告文件中准确的 XML 错误的正确代码发布在下面:

QFile file(file_.filePath());

if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
    QString errorMsg;
    int errorLine;
    int errorColumn;

    if (!doc.setContent(in.readAll(), &errorMsg, &errorLine, &errorColumn)) {
        QString line;
        file.seek(0);

        for (int i = 0; i < errorLine; ++i) {
            line = file.readLine();
        }

        qFatal("Invalid XML encountered.\nFile %s.\nError = %s\nLine= %d\n%s", qPrintable(file_.absoluteFilePath()), qPrintable(errorMsg), errorLine, qPrintable(line.insert(errorColumn -1, "^").trimmed()));
    }
}

【讨论】:

    猜你喜欢
    • 2018-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-30
    • 1970-01-01
    • 2011-08-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多