更新: 解決に向けて
このコード:
tree = ET.parse(assetsfilename)
root = tree.getroot()
assets = {}
def find_rows(rowset, container):
for row in rowset.findall("row"):
singleton = int((row.get('singleton')))
flag = int((row.get('flag')))
quantity = int((row.get('quantity')))
typeID = int((row.get('typeID')))
locationID = int((row.get('locationID', '0')))
itemID = int((row.get('itemID')))
dkey = (singleton, flag, quantity, typeID, locationID, itemID)
container[dkey] = {}
child_rowset = row.find("rowset")
if child_rowset is not None:
find_rows(child_rowset, container[dkey])
first_rowset = root.find('.//rowset[@name="assets"]')
find_rows(first_rowset, assets)
#print singleton, flag, quantity, typeID, locationID, itemID
pp = pprint.PrettyPrinter(indent=4)
pp.pprint(assets)
次の出力が得られます。
{ (0, 4, 1, 3317, 61000419, 1000913922710L): { },
(0, 4, 1, 6159, 60003463, 1007025519384L): { },
(0, 4, 1, 7669, 60000361, 1007215573625L): { },
(0, 4, 1, 23566, 61000419, 1000992661686L): { },
(1, 4, 1, 51, 60001345, 1004073218074L): { },
(1, 4, 1, 51, 60001345, 1004073218075L): { },
(1, 4, 1, 596, 60003337, 1007908184113L): { (0, 5, 1, 34, 0, 1007908184132
L): { },
(1, 27, 1, 3634, 0, 1007908184
129L): { },
(1, 28, 1, 3651, 0, 1007908184
130L): { }},
(1, 4, 1, 3766, 61000419, 1000973178550L): { (0, 5, 25, 16273, 0, 10009731
88870L): { },
(1, 27, 1, 21096, 0, 10006872
93796L): { }}}
これは基本的に、ネストされた dict を既に持っている dict の最後に追加し、存在する場合は子からのデータで埋めます。ただし、理想的には、親データと子データの両方がメイン dict にあり、dict の最後の追加フィールドに親の itemID が含まれる (その行が子行の場合) か、空である (その項目の場合)親行または子を持たない行です。)
質問
ネストされた .xml ファイルから何らかの辞書にデータを読み込んで、他の形式で出力できるようにしようとしています (現在の目標は sqlite3 と sqlite .db ファイルですが、これは私の目的ではありません質問。) データのプライマリ レベルはすべて読み取ることができますが、ネストされたデータ (存在する場合) も読み取る方法がわかりません。
データ
サンプルの .xml ファイルを次に示します。
<?xml version='1.0' encoding='UTF-8'?>
<eveapi version="2">
<currentTime>2012-11-14 03:26:35</currentTime>
<result>
<rowset name="assets" key="itemID" columns="itemID,locationID,typeID,quantity,flag,singleton">
<row itemID="1007215573625" locationID="60000361" typeID="7669" quantity="1" flag="4" singleton="0" />
<row itemID="1004073218074" locationID="60001345" typeID="51" quantity="1" flag="4" singleton="1" rawQuantity="-1" />
<row itemID="1004073218075" locationID="60001345" typeID="51" quantity="1" flag="4" singleton="1" rawQuantity="-1" />
<row itemID="1007908184113" locationID="60003337" typeID="596" quantity="1" flag="4" singleton="1" rawQuantity="-1">
<rowset name="contents" key="itemID" columns="itemID,typeID,quantity,flag,singleton">
<row itemID="1007908184129" typeID="3634" quantity="1" flag="27" singleton="1" rawQuantity="-1" />
<row itemID="1007908184130" typeID="3651" quantity="1" flag="28" singleton="1" rawQuantity="-1" />
<row itemID="1007908184132" typeID="34" quantity="1" flag="5" singleton="0" />
</rowset>
</row>
<row itemID="1007025519384" locationID="60003463" typeID="6159" quantity="1" flag="4" singleton="0" />
<row itemID="1000913922710" locationID="61000419" typeID="3317" quantity="1" flag="4" singleton="0" />
<row itemID="1000973178550" locationID="61000419" typeID="3766" quantity="1" flag="4" singleton="1" rawQuantity="-1">
<rowset name="contents" key="itemID" columns="itemID,typeID,quantity,flag,singleton">
<row itemID="1000687293796" typeID="21096" quantity="1" flag="27" singleton="1" rawQuantity="-1" />
<row itemID="1000973188870" typeID="16273" quantity="25" flag="5" singleton="0" />
</rowset>
</row>
<row itemID="1000992661686" locationID="61000419" typeID="23566" quantity="1" flag="4" singleton="0" />
</rowset>
</result>
<cachedUntil>2012-11-14 07:05:29</cachedUntil>
</eveapi>
一部の項目には子項目がネストされているが、そうでないものもあり、子の数 (存在する場合) は固定されていないことに注意してください (したがって、1 つの項目には 3 つの子があり、別の項目には 2 つの子がありますが、他の多くの項目には子がまったくありません)。
(興味のある方のために説明すると、このデータは、EVE Online と呼ばれるオンライン ゲームからの完全な ID キー アセット リスト API プルから取得されます。)
私が得ることができるもの
このコードを取得できます:
import xml.etree.ElementTree as ET
tree = ET.parse(assetsfilename)
root = tree.getroot()
singleton = []
flag = []
quantity = []
typeID = []
locationID = []
itemID = []
assets = {}
for row in root.findall(".//*[@name='assets']/row"):
singleton.append (int((row.get('singleton'))))
flag.append (int((row.get('flag'))))
quantity.append (int((row.get('quantity'))))
typeID.append (int((row.get('typeID'))))
locationID.append (int((row.get('locationID'))))
itemID.append (int((row.get('itemID'))))
assets = zip(singleton, flag, quantity, typeID, locationID, itemID)
print singleton, flag, quantity, typeID, locationID, itemID
print assets
これを画面に出力するには:
[0, 1, 1, 1, 0, 0, 1, 0] [4, 4, 4, 4, 4, 4, 4, 4] [1, 1, 1, 1, 1, 1, 1, 1] [7669
, 51, 51, 596, 6159, 3317, 3766, 23566] [60000361, 60001345, 60001345, 60003337,
60003463, 61000419, 61000419, 61000419] [1007215573625L, 1004073218074L, 100407
3218075L, 1007908184113L, 1007025519384L, 1000913922710L, 1000973178550L, 100099
2661686L]
[(0, 4, 1, 7669, 60000361, 1007215573625L), (1, 4, 1, 51, 60001345, 100407321807
4L), (1, 4, 1, 51, 60001345, 1004073218075L), (1, 4, 1, 596, 60003337, 100790818
4113L), (0, 4, 1, 6159, 60003463, 1007025519384L), (0, 4, 1, 3317, 61000419, 100
0913922710L), (1, 4, 1, 3766, 61000419, 1000973178550L), (0, 4, 1, 23566, 610004
19, 1000992661686L)]
これが、開始するすべてのメインレベル行をどのように読み取っているのかに注意してください。ただし<row itemID=
、ネストされた行を取得していません (これは、その上の親 itemID に関連付けられているものとして何らかの方法で表示したいと考えています)。
望ましい出力
ここでの提案にはいくらかオープンですが、これは 1 つのオプションです。メイン レベルの行を dict に解析して (既に持っているように)、サブレベルの行からのデータを含む別の dict を作成し、それがどの itemID の子であるかを示す追加の部分を追加することができます。別のオプションは、サブレベルの行からのデータをメインの辞書に追加することですNull
.None
親を持つアイテム。