我有一个XML文件的文件夹,我想解析。我需要从这些文件的元素中获取文本。它们将被收集并打印到CSV文件中,其中元素列在列中。
也就是说,对于我的许多XML文件,这个过程很顺利,我得到了我想要的输出。执行此操作的代码是:
import os, re, csv, string, operator
import xml.etree.cElementTree as ET
import codecs
def parseEO(doc):
#getting the basic structure
tree = ET.ElementTree(file=doc)
root = tree.getroot()
agencycodes = []
rins = []
titles =[]
elements = [agencycodes, rins, titles]
#pulling in the text from the fields
for elem in tree.iter():
if elem.tag == "AGENCY_CODE":
agencycodes.append(int(elem.text))
elif elem.tag == "RIN":
rins.append(elem.text)
elif elem.tag == "TITLE":
titles.append(elem.text)
with open('parsetest.csv', 'w') as f:
writer = csv.writer(f)
writer.writerows(zip(*elements))
parseEO('EO_file.xml')
但是,在某些版本的输入文件中,我收到了臭名昭着的错误:
'ascii' codec can't encode character u'\x97' in position 32: ordinal not in range(128)
完整的追溯是:
---------------------------------------------------------------------------
UnicodeEncodeError Traceback (most recent call last)
<ipython-input-15-28d095d44f02> in <module>()
----> 1 execfile(r'/parsingtest.py') # PYTHON-MODE
/Users/ian/Desktop/parsingtest.py in <module>()
91 writer.writerows(zip(*elements))
92
---> 93 parseEO('/EO_file.xml')
94
95
/parsingtest.py in parseEO(doc)
89 with open('parsetest.csv', 'w') as f:
90 writer = csv.writer(f)
---> 91 writer.writerows(zip(*elements))
92
93 parseEO('/EO_file.xml')
UnicodeEncodeError: 'ascii' codec can't encode character u'\x97' in position 32: ordinal not in range(128)
我非常有信心阅读其他线程,问题出在所使用的编解码器中(而且,你知道,错误也非常清楚)。但是,我读过的解决方案并没有帮助 me (强调因为我知道我是问题的根源,而不是人们过去回答的方式)。
几个回复(例如:this one和this one和this one)不直接与ElementTree打交道,我不确定如何将解决方案转换为我的解决方案我在做。
其他处理ElementTree的解决方案(例如:this one和this one)要么使用短字符串(此处为第一个链接),要么使用ElementTree中的.tostring / .fromstring方法我没有。 (当然,也许我应该是。)
我尝试过的东西不起作用:
我试图通过UTF-8编码引入文件:
infile = codecs.open('/EO_file.xml', encoding="utf-8")
parseEO(infile)
但是我认为ElementTree进程已经将它理解为UTF-8(我在所有XML文件的第一行中都注明了这一点),所以这不仅不正确,而且实际上是多余的错误再次。
我试图在循环中声明一个编码过程,取而代之的是:
tree = ET.ElementTree(file=doc)
带
parser = ET.XMLParser(encoding="utf-8")
tree = ET.parse(doc, parser=parser)
在上面的循环中确实有效。这对我也不起作用。之前工作的相同文件仍然有效,创建错误的相同文件仍然会产生错误。
还有很多其他的随机尝试,但我不会强调这一点。
所以,虽然我认为我所拥有的代码既低效又缺乏良好的编程风格,但它确实能满足我对多个文件的需求。我试图理解是否只有一个我不知道的参数,我不知道,如果我应该以某种方式预处理文件(我还没有确定哪个有问题的字符,但确实知道你的'' x97转换为某种控制字符,或其他一些选项。
答案 0 :(得分:10)
您正在解析XML; XML API为您提供unicode
个值。然后,您尝试将unicode数据写入CSV文件,而不先对其进行编码。 Python然后尝试为您编码但失败。您可以在回溯中看到这一点,.writerows()
调用失败,错误告诉您 encoding 失败,而不是解码(解析XML)。
您需要选择编码,然后在编写之前对数据进行编码:
for elem in tree.iter():
if elem.tag == "AGENCY_CODE":
agencycodes.append(int(elem.text))
elif elem.tag == "RIN":
rins.append(elem.text.encode('utf8'))
elif elem.tag == "TITLE":
titles.append(elem.text.encode('utf8'))
我使用UTF8编码,因为它可以处理任何Unicode代码点,但您需要自己做出明确的选择。
答案 1 :(得分:3)
听起来你的xml文件中有一个unicode字符。 Unicode与编码为utf8的字符串不同。
python2.7 csv库不支持unicode字符,因此在将它们转储到csv文件之前,必须通过编码它们的函数运行数据。
def normalize(s):
if type(s) == unicode:
return s.encode('utf8', 'ignore')
else:
return str(s)
所以你的代码看起来像这样:
for elem in tree.iter():
if elem.tag == "AGENCY_CODE":
agencycodes.append(int(elem.text))
elif elem.tag == "RIN":
rins.append(normalize(elem.text))
elif elem.tag == "TITLE":
titles.append(normalize(elem.text))