检索嵌套标记的值并将其存储在嵌套字典中

时间:2015-07-08 22:14:25

标签: python python-3.x xml-parsing

我正在尝试将XML标记之间的值存储到列表中,但它无法正常工作。我在缠绕这个问题时遇到了麻烦。以下代码给出 AttributeError: 'list' object has no attribute 'find'

以下是代码:

import xml.etree.ElementTree as ET
    tree = ET.parse(‘//storage1//harison/dev/gis/cocalig.xml’)
    root = tree.getroot()
input['merchandise_db'] = {'host': root.findall('cali_merchandise_db_ref').find('host').text, 'db_name': root.findall('cali_merchandise_db_ref').cali_merchandise_db_ref.find('db_name').text, 'schema': root.findall('cali_merchandise_db_ref').cali_merchandise_db_ref.find('schema').text, 'user': root.findall('cali_merchandise_db_ref').cali_merchandise_db_ref.find('user').text, 'pwd': root.findall('cali_merchandise_db_ref').cali_merchandise_db_ref.find('password').text}

input['incident_db'] = {'host': root.findall('incident_db_ref').incident_db_ref.find('host').text, 'db_name': root.findall('incident_db_ref').incident_db_ref.find('db_name').text, 'schema': root.findall('incident_db_ref').incident_db_ref.find('schema').text, 'user': root.findall('incident_db_ref').incident_db_ref.find('user').text, 'pwd': root.findall('incident_db_ref').incident_db_ref.find('password').text}

input['projection_db'] = {'host': root.findall('cali_projection_db_ref').incident_db_ref.find('host').text, 'db_name': root.findall('cali_projection_db_ref').incident_db_ref.find('db_name').text, 'schema': root.findall('cali_projection_db_ref').incident_db_ref.find('schema').text, 'user': root.findall('cali_projection_db_ref').incident_db_ref.find('user').text, 'pwd': root.findall('cali_projection_db_ref').incident_db_ref.find('password').text}

我理解为什么代码会给出错误但不确定如何解决它。在我刚刚将值输出到屏幕之前,我使用#for cali_merchandise_db_ref in root.findall('cali_merchandise_db_ref'): and cali_merchandise_db_ref.find('xyz')进行迭代.text`

TL; DR
给出xml文件

<animal>
 <lastmodified_date>4/6/2015</lastmodified_date>
 <data>some junk goes here</data>
 <dog>
   <sound>woof</sound>
   <hastail>yes</hastail>
 </dog>
 <cat>
   <sound>meow</sound>
   <hastail>yes</hastail>
 </cat>
</animal>

你怎么得到

input['dog']['sound'] = 'woof'
input['cat']['sound'] = 'meow'
input['dog']['hastail'] = 'yes'
input['cat']['hastail'] = 'yes'

尝试失败#2:

>>> import xml.etree.ElementTree as ET
>>> with open ("cocalig.xml", "r") as myfile:
...     data=myfile.read().replace('\n', '')
...
>>> root = ET.fromstring(data)
>>> mydic = {}
>>> for element in root:
...     host_tag = element.find("host")
...     mydic[element.tag] = {"host": host_tag.text}
...
Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
AttributeError: 'NoneType' object has no attribute 'text'
>>>

2 个答案:

答案 0 :(得分:1)

编辑以适合您的调整后的示例

你的例子可以这样解决:

root = ET.fromstring("<animal> <lastmodified_date>4/6/2015</lastmodified_date><data>some junk goes here</data><dog><sound>woof</sound><hastail>yes</hastail></dog><cat><sound>meow</sound><hastail>yes</hastail></cat></animal>")

mydic = {}
for element in root:
    if element.tag in ('lastmodified_date', 'data'):
        mydic[element.tag] = element.text
    else:  # here come the elements describing animals
        mydic[element.tag] = {}
        for animal_element in element:  # "sound" and "hastail" in undefined order
            mydic[element.tag][animal_element.tag] = animal_element.text

这会生成以下字典:

{'lastmodified_date': '4/6/2015', 'data': 'some junk goes here', 'dog': {'hastail': 'yes', 'sound': 'woof'}, 'cat': {'hastail': 'yes', 'sound': 'meow'}}

基本上,你不需要明确地说你要从动物中提取“声音”和“hastail”。你只想说:我想要动物的所有子元素。但是,如果您想将缺少的标记视为错误,则必须明确检查它们:

else:  # here come the elements describing animals
    mydic[element.tag] = {}
    try:
        sound = element.find("sound")
        mydic[element.tag][sound.tag] = sound.text
    except:
        # do some error handling

您也可以这种方式解决问题。链接findAllfind调用可能听起来很直观,但findAll只返回搜索工作不同的已找到元素的列表。因此,只需迭代所有元素。

答案 1 :(得分:0)

简而言之,你需要:

tree.findall('dog')[0].findall('sound')[0].text

这是一个纲要:

>>> import xml.etree.ElementTree as ET
>>> tree = ET.fromstring(s)
>>> tree.findall('dog')[0].findall('sound')[0].text
'woof'