2

我尝试在 StackOverflow 上搜索各种问题和答案,但找不到适合我情况的解决方案,所以这是我的问题。

我有 3 个要比较的 xml 文件。我遇到的问题是一次抓取“主要”XML 文件的部分并将信息保存在一起。例如,我想保留与 1 相关联的信息,并能够使用脚本中的每个部分。

这个 XML 文件在标签之间可以有任意数量的字段,但我只需要 5 个特定字段。我对 Python 相当陌生,并且对使用 Python 读取文本文件以外的内容非常陌生,任何帮助将不胜感激。

下面是 xml 的示例。

Main XML:
    <?xml version="1.0" encoding="ISO-8859-1" ?>
    <resultset table="foo_bar">
    <row>
        <field name="id">1</field>
        <field name="name">foo 1</field>
        <field name="item 1">bar 1</field>
        <field name="item 2">Accepted</field>
        <field name="item 3">Accepted</field>
    </row>
    <row>
        <field name="id">2</field>
        <field name="name">foo 2</field>
        <field name="item 1">bar 2</field>
        <field name="item 2">Declined</field>
        <field name="item 3">Accepted</field>
    </row>
    <row>
        <field name="id">3</field>
        <field name="name">foo 3</field>
        <field name="item 1">bar 3</field>
        <field name="item 2">Accepted</field>
        <field name="item 3">Declined</field>
    </row>
    .....Continues
    </resultset>

我曾尝试遵循类似问题的各种答案,但到目前为止还没有成功。

编辑我已经尝试了多种方法,我将不得不挖掘各种 .py 脚本以找到所有这些。这是基于此处发布的问题的最新信息

from lxml import etree as ET

def filter_by_itemid(doc, idlist):
    rowset = doc.xpath("//row")
    for elem in rowset.getchildren():
        if elem.get("*") not in idlist:
            rowset.remove(elem)
    return doc

doc = ET.parse("my.xml")
filter_by_itemid(doc, ['id', 'name', 'item 1', 'item 2', 'item 3'])

print(ET.tostring(doc))

我知道我在某处做错了什么,并且 xml 的格式(我无法从源头更改)没有帮助......

我收到的错误是“AttributeError: 'list' object has no attribute 'getchildren'”

4

1 回答 1

2

像这样的东西怎么样:

from lxml import etree

root = etree.parse('xml.xml')
rows = root.findall('row')

all_data = []

for row in rows:
    field_dict = {}
    fields = row.findall('field')

    for field in fields:
        field_dict[field.get('name')] = field.text

    print(field_dict)

    all_data.append(field_dict)

print(all_data)


--output:--
{'item 3': 'Accepted', 'item 2': 'Accepted', 'item 1': 'bar 1', 'id': '1', 'name': 'foo 1'}
{'item 3': 'Accepted', 'item 2': 'Declined', 'item 1': 'bar 2', 'id': '2', 'name': 'foo 2'}
{'item 3': 'Declined', 'item 2': 'Accepted', 'item 1': 'bar 3', 'id': '3', 'name': 'foo 3'}


[{'item 3': 'Accepted', 'item 2': 'Accepted', 'item 1': 'bar 1', 'id': '1', 'name': 'foo 1'}, {'item 3': 'Accepted', 'item 2': 'Declined', 'item 1': 'bar 2', 'id': '2', 'name': 'foo 2'}, {'item 3': 'Declined', 'item 2': 'Accepted', 'item 1': 'bar 3', 'id': '3', 'name': 'foo 3'}]

可能在一行中的额外字段将在 field_dict 中,但您可以忽略它们。或者,如果这对您不起作用,您可以过滤掉垃圾:

from lxml import etree

root = etree.parse('xml.xml')
rows = root.findall('row')

#Create a set:
allowed_names = {
    'id',
    'name',
    'item 1',
    'item 2',
    'item 3'
}

all_data = []


for row in rows:
    field_dict = {}
    fields = row.findall('field')

    for field in fields:
        name_val = field.get('name')

        if name_val in allowed_names:
            field_dict[name_val] = field.text

    print(field_dict)

    all_data.append(field_dict)

print(all_data)

如果更方便,您可以将 all_data 定义为字典,并使用 id 作为键,每个键的值可以是包含其余数据的字典。

于 2013-06-07T17:51:50.070 回答