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' オブジェクトに属性 '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 に答える