2015-01-05 7 views
5

Jeśli spróbuję przeanalizować uszkodzony XML, wyjątek pokazuje numer wiersza. Czy istnieje sposób na pokazanie kontekstu XML?Uzyskaj lepszy komunikat o błędzie analizy składni z ElementTree

Chcę zobaczyć tagi xml przed i po zepsutej części.

Przykład:

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

Wyjątek:

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 

Coś takiego byłoby miło:

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

Odpowiedz

12

Można zrobić funkcja pomocnika, aby to zrobić:

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>') 

daje

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

up-głosowania za pomocą 'err.position' nie wiedział o tym. –

+0

@KobiK: Nie wiedziałem też, ale dobre narzędzie introspekcji, takie jak IPython, przydaje się, aby odkryć, co jest dostępne w obiektach takich jak 'err'. – unutbu

+0

Dziękuję bardzo. Działa miło. – guettli

1

To nie jest najlepszym rozwiązaniem, ale jest to łatwe i proste, można po prostu Przetwórz ParseError Wyodrębnij linię i kolumnę, a następnie użyj jej do pokaż, gdzie jest problem.

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])*"-") 

Uwaga: \n jest tylko dla przykładu trzeba podzielić go na właściwą drogę.

Powiązane problemy