python 分析XML文件时需要类似字节的对象,而不是“str”

omvjsjqw  于 2023-01-24  发布在  Python
关注(0)|答案(2)|浏览(122)

我正在尝试解析一个XML,看起来像这样。我想提取有关katagorie的信息,即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'),我怎样才能消除这个错误呢?

ffdz8vbo

ffdz8vbo1#

    • EDIT 2**如果要查找关于嵌套属性或子类,有两种方法:

1.可以使用嵌套循环:

for elem in root:
    for child in elem:
        print([(child.attrib.get(name) or 'c') for name in fields])

输出:
["1"、"0"]
在这里,它也可以返回具有idparent_id但没有名称kategorie的类。
1.如果您希望以更高的性能和更少的内存执行任务:

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

t3irkdon

t3irkdon2#

我发现了两个问题。首先,你不需要自己编码。打开没有“b”二进制标志的文件并跳过. encode。file对象将为你编码。你看到的错误来自['id', 'parent_id']列表,该列表包含未编码的字符串。但是如果你一开始没有用二进制打开,这不是问题。
第二,你迭代了错误的元素,在循环中添加一个print(elem),你会看到,相反,你可以使用带有伪xpath的findall来得到你想要的元素。

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

相关问题