Search code examples
c++xmlqtqt4

Reporting detailed XML errors when using QDomDocument


I'm currently modifying some old code that is using QDomDocument to parse XML file content. Example code below:

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);
    }
}

Unfortunately the error reporting is extremely limited. Removing a closing tag half way down the file simply reports the following error:

Invalid XML in file config.xml. Error = unexpected end of file, Line = 1, Column = 1

Which is fairly useless.

Any suggestions of how to get more descriptive errors out of Qt's XML parsers? An accurate line number would be a good start.

P.S. I'm using Qt version 4.7.4.


Solution

  • QDomDocument::setContent should give you the right information to know where the problem is.

    For example, with this snippet of code:

    #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;
    }
    

    And this xml file:

    <?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>
    

    We see the following error:

    Error: "tag mismatch" in line 4 column 19

    I've updated this answer after reading some comments from @kh25.

    • The problem could be due to the file encoding. In this case, we could try removing carriage returns and new lines. dos2unix can help if we're working on Linux.
    • Another option would be to use an online tool to check the XML.

    But in this particular case, it seems the problem is related to closing the file -- file.close() -- before calling in.readAll(). In this case, QDomDocument::setContent is reading an empty string and we see the error unexpected end of file.

    Another way of getting the error is calling QDomDocument::setContent when the file has reached the end of the stream.

    So, if we call for example QTextStream::readAll() twice, we get the same error. I.e:

    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 commented about using QXMLStreamReader. If you need an example, I have a little project in GitHub where I use that class.