我正在尝试解析如下所示的 xml。我想提取有关类别的信息,即 ID、家长 ID 等:
<?xml version="1.0" encoding="UTF-8"?>
<test timestamp="20210113">
<kategorien>
<kategorie id="1" parent_id="0">
Sprache
</kategorie>
</kategorien>
</test>
我正在尝试这个
fields = ['id', 'parent_id']
with open('output.csv', 'wb') as fp:
writer = csv.writer(fp)
writer.writerow(fields)
tree = ET.parse('./file.xml')
# from your example Locations is the root and Location is the first level
for elem in tree.getroot():
writer.writerow([(elem.get(name) or '').encode('utf-8')
for name in fields])
但我收到此错误:
in <module>
writer.writerow(fields)
TypeError: a bytes-like object is required, not 'str'
即使我已经在代码中使用了
encode('utf-8')
。我怎样才能摆脱这个错误?
编辑2 如果想查找嵌套属性或子类,有两种方法:
for elem in root:
for child in elem:
print([(child.attrib.get(name) or 'c') for name in fields])
输出:
['1','0']
在这里,它还可以返回具有
id
和 parent_id
但不包含名称 kategorie
的类。
for elem in root.iter('kategorie'):
print([(elem.attrib.get(name) or 'c') for name in fields])
输出:
['1','0']
对于此方法,它将返回名为
kategorie
的每个类和子类。
编辑1:对于评论中的问题:
<?xml version="1.0"?>
<kategorien>
<kategorie id="1" parent_id="0">
Sprache
</kategorie>
</kategorien>
对于上面的
xml
文件,代码似乎运行得很好:
fields = ['id', 'parent_id']
for elem in tree.getroot():
print([(elem.attrib.get(name) or 'c') for name in fields])
输出:
['1','0']
原答案: 看起来您正在寻找错误的位置。错误实际上发生在
writer.writerow(fields)
fields
是一个包含 str
而不是 byte
的列表,这就是它给你错误的原因。我建议您将写入类型从 wb
更改为 w
,但看看其余的代码,看起来您想用 byte
写入。
writer.writerow([x.encode('utf-8') for x in fields])
encode()
只是将您的数据转换为 byte
形式。
我看到两个问题。首先,您不需要自己进行编码。打开不带“b”二进制标志的文件并跳过 .encode。文件对象将为您进行编码。您看到的错误来自包含未编码字符串的
['id', 'parent_id']
列表。但如果你一开始就不以二进制方式打开,那就不是问题。
其次,您迭代了错误的元素。在循环中添加
print(elem)
,您就会看到。相反,您可以使用 findall
和伪 xpath 来获取所需的元素。
import csv
import xml.etree.ElementTree as ET
fields = ['id', 'parent_id']
with open('output.csv', 'w') as fp:
writer = csv.writer(fp)
writer.writerow(fields)
tree = ET.parse('./file.xml')
# from your example Locations is the root and Location is the first level
for elem in tree.getroot().findall('kategorien/kategorie'):
writer.writerow([(elem.get(name) or '')
for name in fields])