1

更新:寻求解决方案

这段代码:

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): {   }}}

这基本上在我已经拥有的字典的末尾添加了一个嵌套字典,并用来自孩子的数据(如果存在)填充它。但是,理想情况下,父数据和子数据都在主字典中,并且字典末尾的额外字段将包含父项的 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>

请注意,有些项目如何在其下嵌套子项目,但有些则没有,并且子项目(如果存在)的数量不固定(因此一个项目可以有 3 个孩子,另一个项目可以有 2 个孩子,而许多其他项目根本没有孩子。)

(对于那些好奇的人,这些数据来自名为 EVE Online 的在线游戏中提取的完整 id 密钥 Asset List 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 相关联。)

期望的输出

我对这里的建议持开放态度,但这是一种选择。我可以将主要级别的行解析为一个字典(就像我已经拥有的那样),然后创建另一个字典,其中包含来自子级别行的数据,并添加一个额外的片段,说明它是哪个 itemID 的子级。另一种选择是将子级别行中的数据添加到我已经可以制作的主字典中,然后添加一个额外的字段,例如NullNone对于没有父项并提供父项的 itemID 的项目确实有父项的项目。

4

1 回答 1

1

这个片段(有点大)递归地将 xml 结构解析为嵌套字典,就像您描述的可能的解决方案一样。它适用于您提供的示例,但我认为它无论如何都适用于实时数据。如果没有别的,你可以使用这个想法。

更新:好的,这个更新的版本将 itemID 存储为键,并将 parent_id 添加为附加的 dict 属性,检查它是否是所需的行为:

import xml.etree.ElementTree as ET

from StringIO import StringIO
tree = ET.parse(StringIO(xml_data))
root = tree.getroot()

assets = {}

def find_rows(rowset, parent_id):
    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')))

        assets[itemID] = {'singleton': singleton,
                          'flag': flag,
                          'quantity': quantity,
                          'typeID': typeID,
                          'locationID': locationID,
                          'parentID': parent_id}
        child_rowset = row.find("rowset")
        if child_rowset is not None:
            find_rows(child_rowset, itemID)

first_rowset = root.find('.//rowset[@name="assets"]')
find_rows(first_rowset, None)
于 2012-11-14T07:14:02.793 回答