2016-04-12 22 views
3

現在、QDomDocumentを使用してXMLファイルの内容を解析する古いコードを変更しています。以下のコード例: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パーサーから説明的なエラーを取り除く方法の提案はありますか?正確な行番号は良いスタートになります。

P.S. Qtバージョン4.7.4を使用しています。

+1

'QDomDocument'が古いの一部であり、サポートされていない[QtXML](http://doc.qt.io/qt- 5/qtxml-module.html)モジュール。あなたの最善の策は、[QXMLStreamReader](http://doc.qt。io/qt-5/qxmlstreamreader.html)を使用してください。 – MrEricSir

答えて

1

QDomDocument::setContentは、どこに問題があるかを知るための適切な情報を提供する必要があります。

#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ファイル:私はしました

Error: "tag mismatch" in line 4 column 19

:私たちは、次のエラーが表示

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

のコードスニペットと例

、 @ kh25からのコメントを読んだ後、この回答を更新しました。

  • 問題は、ファイルのエンコードが原因である可能性があります。この場合、キャリッジリターンと改行を削除することができます。 dos2unixは、Linuxで作業している場合に役立ちます。
  • もう1つの方法は、online toolを使用してXMLをチェックすることです。 in.readAll()を呼び出す前に - file.close() -

しかし、この特定のケースではは、問題がファイルを閉じるに関係しているようです。この場合、QDomDocument::setContentは空の文字列を読み取り、エラーunexpected end of fileが表示されます。

エラーを取得する別の方法は、ファイルがストリームの最後に到達したときにQDomDocument::setContentを呼び出すことです。

したがって、たとえばQTextStream::readAll()を2回呼び出すと、同じエラーが発生します。すなわち:

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に小さなプロジェクトがあり、そのクラスを使っています。

+0

これはkh25のケースではないと思います。ここでは、一致しない終了タグでは矛盾が検出されますが、kh25では最後まですべて有効ですが、不完全です。 –

+0

ありがとうTarod。あなたは100%正解です。この場合、ファイルを直接使用すると、より正確なエラー報告が得られます。 QTextStreamを使用してQStringを同じ関数に渡すと、はるかに明確でないエラーが発生しました。私はこのコードがもともとQTextStreamを使用するように書かれていたのかどうかは不明です(以前のQtのバージョンはsetContent()へのQFile引数をサポートしていなかったかもしれません)。マークアップがあります。 XMLブロックを表すQStringがなぜこのようなエラー処理が貧弱であるのか、誰かが説明するかもしれません。 – kh25

+0

@ kh25ああ、素晴らしい! :)問題はエンコーディングではなく、 'QTextStream'でした。私は私の答えを更新する必要がありますが、私は 'QTextStream'を使うとなぜ問題が発生するのかを検証するためにいくつかのテストをしたいと思います。 'setContent'はファイルの最後の行だけを取得しているようです。 – Tarod

1

ファイル内の正確な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())); 
    } 
} 
関連する問題