我需要从xml文件中提取信息,将其与xml标签前后隔离,将信息存储在字典中,然后循环遍历字典以打印列表。我是一个绝对的初学者,所以我想尽量保持简单,如果我描述了我想做的事情没有多大意义,我道歉。
这是我到目前为止所拥有的。
for line in open("/people.xml"):
if "name" in line:
print (line)
if "age" in line:
print(line)
当前输出:
<name>John</name>
<age>14</age>
<name>Kevin</name>
<age>10</age>
<name>Billy</name>
<age>12</age>
期望输出
Name Age
John 14
Kevin 10
Billy 12
编辑 - 所以使用下面的代码我可以得到输出:
{'Billy': '12', 'John': '14', 'Kevin': '10'}
有没有人知道如何从这个到带有标题的图表,比如我想要的输出?
答案 0 :(得分:3)
尝试xmldict(将xml转换为python词典,反之亦然。):
>>> xmldict.xml_to_dict('''
... <root>
... <persons>
... <person>
... <name first="foo" last="bar" />
... </person>
... <person>
... <name first="baz" last="bar" />
... </person>
... </persons>
... </root>
... ''')
{'root': {'persons': {'person': [{'name': {'last': 'bar', 'first': 'foo'}}, {'name': {'last': 'bar', 'first': 'baz'}}]}}}
# Converting dictionary to xml
>>> xmldict.dict_to_xml({'root': {'persons': {'person': [{'name': {'last': 'bar', 'first': 'foo'}}, {'name': {'last': 'bar', 'first': 'baz'}}]}}})
'<root><persons><person><name><last>bar</last><first>foo</first></name></person><person><name><last>bar</last><first>baz</first></name></person></persons></root>'
或尝试xmlmapper(具有父子关系的python词典列表):
>>> myxml='''<?xml version='1.0' encoding='us-ascii'?>
<slideshow title="Sample Slide Show" date="2012-12-31" author="Yours Truly" >
<slide type="all">
<title>Overview</title>
<item>Why
<em>WonderWidgets</em>
are great
</item>
<item/>
<item>Who
<em>buys</em>
WonderWidgets1
</item>
</slide>
</slideshow>'''
>>> x=xml_to_dict(myxml)
>>> for s in x:
print s
>>>
{'text': '', 'tail': None, 'tag': 'slideshow', 'xmlinfo': {'ownid': 1, 'parentid': 0}, 'xmlattb': {'date': '2012-12-31', 'author': 'Yours Truly', 'title': 'Sample Slide Show'}}
{'text': '', 'tail': '', 'tag': 'slide', 'xmlinfo': {'ownid': 2, 'parentid': 1}, 'xmlattb': {'type': 'all'}}
{'text': 'Overview', 'tail': '', 'tag': 'title', 'xmlinfo': {'ownid': 3, 'parentid': 2}, 'xmlattb': {}}
{'text': 'Why', 'tail': '', 'tag': 'item', 'xmlinfo': {'ownid': 4, 'parentid': 2}, 'xmlattb': {}}
{'text': 'WonderWidgets', 'tail': 'are great', 'tag': 'em', 'xmlinfo': {'ownid': 5, 'parentid': 4}, 'xmlattb': {}}
{'text': None, 'tail': '', 'tag': 'item', 'xmlinfo': {'ownid': 6, 'parentid': 2}, 'xmlattb': {}}
{'text': 'Who', 'tail': '', 'tag': 'item', 'xmlinfo': {'ownid': 7, 'parentid': 2}, 'xmlattb': {}}
{'text': 'buys', 'tail': 'WonderWidgets1', 'tag': 'em', 'xmlinfo': {'ownid': 8, 'parentid': 7}, 'xmlattb': {}}
上面的代码将给出生成器。当你迭代它时;您将获得dict
键中的信息;例如tag
,text
,xmlattb
,tail
以及xmlinfo
中的附加信息。此处root
元素的parentid
信息为0
。
答案 1 :(得分:1)
为此使用XML parser。例如,
import xml.etree.ElementTree as ET
doc = ET.parse('people.xml')
names = [name.text for name in doc.findall('.//name')]
ages = [age.text for age in doc.findall('.//age')]
people = dict(zip(names,ages))
print(people)
# {'Billy': '12', 'John': '14', 'Kevin': '10'}
答案 2 :(得分:0)
在我看来,这是一个学习如何手动解析这个XML的练习,而不是简单地将一个库拉出包来为你做。如果我错了,我建议观看Steve Huffman的udacity视频,可以在这里找到:http://www.udacity.com/view#Course/cs253/CourseRev/apr2012/Unit/362001/Nugget/365002。他解释了如何使用minidom模块来解析轻量级的xml文件,例如这些文件。
现在,我想在答案中提出的第一点是,你不想创建一个python字典来打印所有这些值。 python字典只是一组与值对应的键。它们没有排序,因此按照它们出现在文件中的顺序进行遍历是一个痛苦的屁股。您试图打印出所有名称及其相应的年龄,因此像元组列表这样的数据结构可能更适合整理您的数据。
似乎xml文件的结构是这样的,每个名称标记都由与其对应的年龄标记继承。似乎每行只有一个名称标签。这使事情变得相当简单。我不打算为这个问题编写最有效或最通用的解决方案,但我会尝试使代码尽可能简单易懂。
因此,让我们首先创建一个列表来存储数据:
然后我们创建一个列表来存储数据: a_list = []
现在打开你的文件,并初始化几个变量来保存每个名字和年龄:
from __future__ import with_statement
with open("/people.xml") as f:
name, age = None, None #initialize a name and an age variable to be used during traversals.
for line in f:
name = extract_name(line,name) # This function will be defined later.
age = extract_age(line) # So will this one.
if age: #We know that if age is defined, we can add a person to our list and reset our variables
a_list.append( (name,age) ) # and now we can re-initialize our variables.
name,age = None , None # otherwise simply read the next line until age is defined.
现在,对于文件中的每一行,我们想确定它是否包含用户。如果是这样,我们想要提取名称。让我们创建一个用于执行此操作的函数:
def extract_name(a_line,name): #we pass in the line as well as the name value that that we defined before beginning our traversal.
if name: # if the name is predefined, we simply want to keep the name at its current value. (we can clear it upon encountering the corresponding age.)
return name
if not "<name>" in a_line: #if no "<name>" in a_line, return. otherwise, extract new name.
return
name_pos = a_line.find("<name>")+6
end_pos = a_line.find("</name>")
return a_line[name_pos:end_pos]
现在,我们必须创建一个函数来解析用户年龄的行。我们可以通过与前一个函数类似的方式完成此操作,但我们知道,一旦我们有了一个年龄,它将立即添加到列表中。因此,我们永远不需要关注年龄以前的价值。因此该函数可以如下所示:
def extract_age(a_line):
if not "<age>" in a_line: #if no "<age>" in a_line:
return
age_pos = a_line.find("<age>")+5 # else extract age from line and return it.
end_pos = a_line.find("</age>")
return a_line[age_pos:end_pos]
最后,您要打印列表。您可以按如下方式执行此操作:
for item in a_list:
print '\t'.join(item)
希望这有帮助。我还没有测试过我的代码,所以它可能仍然有点小问题。但是,这些概念存在。 :)
答案 3 :(得分:0)
以下是使用 lxml 库的另一种方式:
from lxml import objectify
def xml_to_dict(xml_str):
""" Convert xml to dict, using lxml v3.4.2 xml processing library, see http://lxml.de/ """
def xml_to_dict_recursion(xml_object):
dict_object = xml_object.__dict__
if not dict_object: # if empty dict returned
return xml_object
for key, value in dict_object.items():
dict_object[key] = xml_to_dict_recursion(value)
return dict_object
return xml_to_dict_recursion(objectify.fromstring(xml_str))
xml_string = """<?xml version="1.0" encoding="UTF-8"?><Response><NewOrderResp>
<IndustryType>Test</IndustryType><SomeData><SomeNestedData1>1234</SomeNestedData1>
<SomeNestedData2>3455</SomeNestedData2></SomeData></NewOrderResp></Response>"""
print xml_to_dict(xml_string)
要保留父节点,请改为使用:
def xml_to_dict(xml_str):
""" Convert xml to dict, using lxml v3.4.2 xml processing library, see http://lxml.de/ """
def xml_to_dict_recursion(xml_object):
dict_object = xml_object.__dict__
if not dict_object: # if empty dict returned
return xml_object
for key, value in dict_object.items():
dict_object[key] = xml_to_dict_recursion(value)
return dict_object
xml_obj = objectify.fromstring(xml_str)
return {xml_obj.tag: xml_to_dict_recursion(xml_obj)}
如果你只想返回一个子树并将其转换为dict,你可以使用 Element.find():
xml_obj.find('.//') # lxml.objectify.ObjectifiedElement instance