0

私はここSOでzipと魔法についての他の質問を見てきました*。これは、それがどのように機能するかを理解するのに大いに役立ちました。例えば:

実際に何が起こっているのかについてはまだ少し考えなければなりませんが、今では理解が深まっています。私が達成しようとしているのは、xmlドキュメントをcsvに変換することです。上記の最後のリンクは、私がやりたいことに非常に近いものですが、私のソース xml は最も一貫した構造を持っておらず、それが私が壁にぶつかっているところです。ソース xml の例を次に示します (この例のために簡略化しています)。

<?xml version="1.0" encoding="utf-8"?>
<root>
    <child>
        <Name>John</Name>
        <Surname>Doe</Surname>
        <Phone>123456</Phone>
        <Phone>654321</Phone>
        <Fax>111111</Fax>
    </child>
    <child>
        <Name>Tom</Name>
        <Surname>Cat</Surname>
        <Phone>98765</Phone>
        <Phone>56789</Phone>
        <Phone>00000</Phone>
    </child>
</root>

ご覧のとおり、 の下に 2 つ以上の同じ要素を含めることができます<child>。また、特定の要素に値がない場合、それは存在しません (2 番目<child>に no がない場合のように<Fax>)。

これは私が現在持っているコードです:

data = etree.parse(open('test.xml')).findall(".//child")
tags = ('Name', 'Surname', 'Phone', 'Fax')

for child in data:
    for a in zip(*[child.findall(x) for x in tags]):
        print([x.text for x in a])

>> Result:

['John', 'Doe', '123456', '111111']

これにより、csv の書き込みに使用できる形式が得られますが、次の 2 つの問題があります。

  1. 要素がないため、2番目の子をスキップし<Fax>ます(私はそう思います)。設定して両方の子に存在する要素のみを検索すると、tags = ('Name', 'Surname')2 つのリストが返されます (すばらしい!)

  2. その最初の子には実際には 2 つの電話番号がありますが、返されるのは 1 つだけです

私がテストできることから、zip * が機能すると、ものが消え始めます...空の値を保持できるように、デフォルト値を設定するにはどうすればよいですか?

更新:私が何をしようとしているのかをより明確にするために、予想される出力形式を次に示します(各フィールドの複数の値がカンマで区切られたセミコロン区切りのCSV):

John;Joe;123456,654321;111111;
Tom;Cat;98765,56789;00000;;

ありがとう!

4

2 に答える 2

0

最初の問題に関して、「[i]両方の子に存在する要素のみを検索すると... 2つのリストが返ってきます」と言い、2番目の子の出力の欠如に何か関係があることを暗示しています2 つのchildノード間の相互作用。そうではありません。zipあなたが見落としているように見える動作の側面はzip、最短のものを使い果たした後に引数の処理を停止することです。

コードを次のように簡略化した出力を検討してください。

for child in data:
    print [child.findall(x) for x in tags]

出力は次のようになります (メモリ アドレスは省略します)。

[[<Element 'Name'>], [<Element 'Surname'>], [<Element 'Phone'>, <Element 'Phone'>], [<Element 'Fax'>]]
[[<Element 'Name'>], [<Element 'Surname'>], [<Element 'Phone'>, <Element 'Phone'>, <Element 'Phone'>], []]

2 番目のリストには空のサブリストがあることに注意してください(2 番目の子にはFaxノードがないため)。これは、これらのサブリストを一緒に圧縮すると、プロセスがすぐに停止し、空のリストが返されることを意味します。最初のパスでは、すでにサブリストの 1 つを使い果たしています。 そのため、出力で 2 番目の子が省略されます。子の間で共有される要素とは関係ありません。

の動作の同じ原則がzip、2 番目の問題を説明しています。上記の最初の出力リストは 4 つの要素で構成されていることに注意してください。3 つのタグに対する長さ 1 のリストと、2 つの phone 要素を含む長さ 2 のリストです。それらを一緒に圧縮すると、サブリストのいずれかを使い果たした後、プロセスは再び停止します。この場合、最短のサブリストの長さは 1 であるため、結果は phone サブリストから 1 つの要素のみを引き出します。

出力をどのように表示したいか正確にはわかりませんが、子ノードごとに、そのノードの各要素のテキストを含むリストを単純に作成しようとしている場合は、次のようにすることができます。

for child in data:
    print [x.text for x in child]

それは以下を生成します:

['John', 'Doe', '123456', '654321', '111111']
['Tom', 'Cat', '98765', '56789', '00000']
于 2013-07-08T23:00:14.617 に答える