2015-01-05 13 views
5

Se si tenta di analizzare un XML interrotto, l'eccezione mostra il numero di riga. C'è un modo per mostrare il contesto XML?Ottenere un migliore messaggio di errore di analisi da ElementTree

Voglio vedere i tag xml prima e dopo la parte rotta.

Esempio:

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

Eccezione:

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 

Qualcosa di simile sarebbe bello:

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

risposta

12

si potrebbe fare una funzione di supporto per fare questo:

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

cede

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

up-voto per l'utilizzo di 'err.position' non saperlo. –

+0

@KobiK: Non lo sapevo neanch'io, ma un buon strumento di introspezione, come IPython, è utile per scoprire cosa è disponibile in oggetti come 'err'. – unutbu

+0

Grazie mille. Funziona bene. – guettli

1

Non è l'opzione migliore, ma è facile e semplice, si può solo analizzare lo ParseError Estrarre la linea e la colonna e quindi utilizzarlo per mostra dove è il problema.

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

Nota: il \n è solo per l'esempio è necessario dividere nel modo giusto.

Problemi correlati