2015-01-05 17 views
5

Bozuk bir XML'yi ayrıştırmaya çalışırsam, istisna satır numarasını gösterir. XML içeriğini göstermenin bir yolu var mı?Daha iyi ayrıştırma hatası iletisini al ElementTree

Kırık bölümden önce ve sonra xml etiketlerini görmek istiyorum.

Örnek:

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

İstisna:

böyle
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 

şey güzel olurdu:

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

cevap

12

Bir yardımcı işlevi bunu yapabilir:

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

bu konuda bilmiyordum `err.position` kullanmak için

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

yukarı oyu verir. –

+0

@KobiK: Ben de bilmiyordum, ama IPython gibi iyi bir iç gözlem aracı, "err" gibi nesnelere uygun olanı bulmak için elverişli hale geliyor. – unutbu

+0

Çok teşekkür ederim. Güzel çalışıyor. – guettli

1

sadece can, En iyi seçenek değil ama kolay ve basit ParseError Ayrıştırma satırı ve sütunu ayıklayın ve sonra problem nerede olduğunu göster.

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

Not: \n sadece bunu doğru şekilde bölmek gerekir örneğin içindir.