将XML解析为列表Python / Django的字典

时间:2016-11-03 17:45:28

标签: python xml django dictionary

我在使用python解析xml时遇到了一些问题。我试图让我的字典看起来像下面的

listDict = [{'name':'Sales','id':'1','position':'1','order_by_type':'True','order_by_asc':'True;}, {'name':'Information','id':'2','position':'1','order_by_type':'True','order_by_asc':'True;}]

我认为从xml字符串中提取数据后我的循环是错误的。

        xml_data = ElementTree.fromstring(self.data)
    # Lets grab all the base cats info and add them to a dict containing a list
    base_cats = xml_data.findall('./BaseCategory/Name')
    base_cats_id = xml_data.findall('./BaseCategory/base_id')
    base_postion = xml_data.findall('./BaseCategory/position')
    base_order_by_type = xml_data.findall('./BaseCategory/order_by_type')
    base_order_by_asc = xml_data.findall('./BaseCategory/order_by_asc')

    # store all information into lists
    base_cat = [t.text for t in base_cats]
    base_id = [t.text for t in base_cats_id]
    base_p = [t.text for t in base_postion]
    base_obt = [t.text for t in base_order_by_type]
    base_asc = [t.text for t in base_order_by_asc]

    base_dict = defaultdict(list)
    # lets put everything in the list into a dictionary
    for base in range(len(base_cat)):  # for each base in base_cat loop
        base_dict[base].append(base_cat[base])
        base_dict[base].append(base_id[base])
        base_dict[base].append(base_p[base])
        base_dict[base].append(base_obt[base])
        base_dict[base].append(base_asc[base])

这会产生以下结果。

instance = {0: ['Sales 2', '1', '10', 'True', 'True'], 1: ['Information 2', '2', '20', 'True', 'True'], 2: ['Listing 2', '3', '30', 'True', 'True'], 3: ['Information', '4', '40', 'True', 'True'], 4: ['Land', '5', '50', 'True', 'True'], 5: ['&', '6', '60', 'True', 'True'], 6: ['Tax', '7', '70', 'True', 'True'], 7: ['Construction', '9', '90', 'True', 'True'], 8: ['Interior/Utilites', '10', '100', 'True', 'True'], 9: ['HOA/Community', '11', '110', 'True', 'True'], 10: ['Remarks', '12', '120', 'True', 'True'], 11: ['Exterior', '8', '80', 'True', 'True']}) 

我的最终目标是能够在我的django模板上执行以下操作

{%for item in instance%}
{{ item.name }}
{% endfor %}

任何有关我可能出错的帮助都会有很大帮助。在此先感谢您的帮助。

编辑: 这里问的是我的xml。

    <?xml version="1.0" ?>
<FormInstance>
    <BaseCategory>
        <Name>Sales</Name>
        <base_id>1</base_id>
        <position>10</position>
        <order_by_type>True</order_by_type>
        <order_by_asc>True</order_by_asc>
    </BaseCategory>
    <BaseCategory>
        <Name>Information</Name>
        <base_id>2</base_id>
        <position>20</position>
        <order_by_type>True</order_by_type>
        <order_by_asc>True</order_by_asc>
        <MainCategory>
            <main_id>1</main_id>
            <Name>Address 3</Name>
            <is_visible>True</is_visible>
            <position>10</position>
            <order_by_type>True</order_by_type>
            <order_by_asc>True</order_by_asc>
            <SubCategory>
                <sub_id>1</sub_id>
                <Name>Street Number 2</Name>
                <sub_library_id>StreetNumber</sub_library_id>
                <field_display_type>[u'input']</field_display_type>
                <field_type>[u'varchar']</field_type>
                <is_active>True</is_active>
                <is_required>True</is_required>
                <help_text>Street Number</help_text>
                <main_category>1</main_category>
                <is_visible>True</is_visible>
                <position>10</position>
                <order_by_type>True</order_by_type>
                <order_by_asc>True</order_by_asc>
                <show_seller>True</show_seller>
                <Enumerations>
                    <enum_id>4</enum_id>
                    <Name>Test Enum</Name>
                    <library_id>test enum</library_id>
                    <is_active>True</is_active>
                    <sub_category>1</sub_category>
                    <is_visible>True</is_visible>
                    <position>10</position>
                    <order_by_type>True</order_by_type>
                    <order_by_asc>True</order_by_asc>
                </Enumerations>
            </SubCategory>
        </MainCategory>
    </BaseCategory>
</FormInstance>

1 个答案:

答案 0 :(得分:2)

因此,对于我在预期结果中收集的内容,您似乎只想获取有关严格BaseCategory的节点的信息,对吧?在编辑中提供的XML中,您有两个。

您应该将XML视为节点树。在示例中,您有类似的内容:

                     FormInstance  # this is the root
                      /         \
                     /           \
             BaseCategory       BaseCategory
             (name:Sales)    (name:Information)
                                    \
                                     \
                                  MainCategory
                                (name:Address 3)
                                        \
                                         \
                                      Subcategory
                                  (name:Street Number 2)

但您只需要BaseCategory元素中的信息,对吗?

您可以将自己定位在root(其中......以及xml.fromstring无论如何)在其BaseCategory节点上进行迭代,从中获取所需的项目那些BaseCategory个节点并将它们放在您的词典列表中。

类似的东西:

import pprint
from xml.etree import ElementTree

with open("sample_xml.xml", 'r') as f:
    data = f.read()
    xml_data = ElementTree.fromstring(data)

base_categories = xml_data.findall("./BaseCategory")
print("Found %s base_categories." % len(base_categories))
list_dict = []
for base_category in base_categories:
    list_dict.append({
        "name": base_category.find("Name").text,
        "id": int(base_category.find("base_id").text),
        "position": int(base_category.find("position").text),
        "order_by_type": (True if base_category.find("order_by_type").text.lower() == "true"
                          else False),
        "order_by_asc": (True if base_category.find("order_by_asc").text.lower() == "true"
                         else False),
    })

print("list_dict=%s" % (pprint.pformat(list_dict)))

哪个输出:

Found 2 base_categories.
list_dict=[{'id': 1,
  'name': 'Sales',
  'order_by_asc': True,
  'order_by_type': True,
  'position': 10},
 {'id': 2,
  'name': 'Information',
  'order_by_asc': True,
  'order_by_type': True,
  'position': 20}]

这个想法是BaseCategory项可以被视为一个自包含的记录(如 dict ,如果它可以帮助你看到它)可以包含(在它)以下属性:

  • 名称为Name
  • 的字符串
  • base_id
  • 中的数字ID
  • 数字position
  • 布尔值order_by_type
  • 布尔值order_by_asc
  • 另一个对象MainCategory,有自己的字段......

因此,每当您将自己置于其中一个BaseCategory节点中时,您只需收集它所包含的有趣字段并将其放入字典中。

当你这样做时:

base_cats = xml_data.findall('./BaseCategory/Name')
base_cats_id = xml_data.findall('./BaseCategory/base_id')
base_postion = xml_data.findall('./BaseCategory/position')
base_order_by_type = xml_data.findall('./BaseCategory/order_by_type')
base_order_by_asc = xml_data.findall('./BaseCategory/order_by_asc')

您将这些元素(base_idposition ...)视为独立元素,这与您在XML中的不完全相同。

但是,如果您绝对确定,则所有这些列表(base_catsbase_cats_idbase_position ...)确实包含相同数量的项目,你仍然可以使用其中一个词的长度重新构建你的词典(在下面的示例len(base_cats)中,但它可能已经len(base_cats_id)len(base_position) ...因为所有这些列表具有相同的长度)以在同一步骤中遍历所有列表:

base_cats = xml_data.findall('./BaseCategory/Name')
base_cats_id = xml_data.findall('./BaseCategory/base_id')
base_postion = xml_data.findall('./BaseCategory/position')
base_order_by_type = xml_data.findall('./BaseCategory/order_by_type')
base_order_by_asc = xml_data.findall('./BaseCategory/order_by_asc')

list_dict = []
for i in range(len(base_cats)):
    list_dict.append({
        "name": base_cats[i].text,
        "id": int(base_cats_id[i].text),
        "position": int(base_postion[i].text),
        "order_by_type": True if base_order_by_type[i].text.lower() == "true" else False,
        "order_by_asc": True if base_order_by_asc[i].text.lower() == "true" else False,
    })
print("list_dict=%s" % (pprint.pformat(list_dict)))