2015-01-05 13 views
5

壊れたXMLを解析しようとすると、例外に行番号が表示されます。 XMLコンテキストを表示する方法はありますか?ElementTreeからより良い解析エラーメッセージを取得

壊れた部分の前後にxmlタグが表示されます。

例:

import xml.etree.ElementTree as ET 
tree = ET.fromstring('<a><b></a>') 

例外:

Traceback (most recent call last): 
    File "tmp/foo.py", line 2, in <module> 
    tree = ET.fromstring('<a><b></a>') 
    File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 1300, in XML 
    parser.feed(text) 
    File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 1642, in feed 
    self._raiseerror(v) 
    File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 1506, in _raiseerror 
    raise err 
xml.etree.ElementTree.ParseError: mismatched tag: line 1, column 8 

このような何かがいいだろう:

ParseError: 
<a><b></a> 
=====^ 

答えて

12

あなたはヘルパー関数は、これを行うために作ることができる:

import sys 
import io 
import itertools as IT 
import xml.etree.ElementTree as ET 
PY2 = sys.version_info[0] == 2 
StringIO = io.BytesIO if PY2 else io.StringIO 

def myfromstring(content): 
    try: 
     tree = ET.fromstring(content) 
    except ET.ParseError as err: 
     lineno, column = err.position 
     line = next(IT.islice(StringIO(content), lineno)) 
     caret = '{:=>{}}'.format('^', column) 
     err.msg = '{}\n{}\n{}'.format(err, line, caret) 
     raise 
    return tree 

myfromstring('<a><b></a>') 

はそのことについて知らなかった `err.position`を使用するための

xml.etree.ElementTree.ParseError: mismatched tag: line 1, column 8 
<a><b></a> 
=======^ 
+0

アップ票を得られます。 –

+0

@ KobiK:私も知らなかったが、IPythonのような良いイントロスペクションツールは、 'err'のようなオブジェクトで利用できるものを発見するのに便利です。 – unutbu

+0

ありがとうございました。いいです。 – guettli

1

それが最良の選択肢ではないのですが、それは簡単で、簡単です、あなただけのことができます解析しますParseError 行と列を抽出し、それを使用してどこに問題があるかを示します。

import xml.etree.ElementTree as ET 
from xml.etree.ElementTree import ParseError 
my_string = '<a><b><c></b></a>' 
try: 
    tree = ET.fromstring(my_string) 
except ParseError as e: 
    formatted_e = str(e) 
    line = int(formatted_e[formatted_e.find("line ") + 5: formatted_e.find(",")]) 
    column = int(formatted_e[formatted_e.find("column ") + 7:]) 
    split_str = my_string.split("\n") 
    print "{}\n{}^".format(split_str[line - 1], len(split_str[line - 1][0:column])*"-") 

注:\nはちょうどあなたがそれを正しい方法を分割する必要があり、たとえばです。

関連する問題