的Python读取XML与相关的子元素
我有这种结构的XML文件:的Python读取XML与相关的子元素
<?DOMParser ?>
<logbook:LogBook xmlns:logbook="http://www/logbook/1.0" version="1.2">
<product>
<serialNumber value="764000606"/>
</product>
<visits>
<visit>
<general>
<startDateTime>2014-01-10T12:22:39.166Z</startDateTime>
<endDateTime>2014-03-11T13:51:31.480Z</endDateTime>
</general>
<parts>
<part number="03081" name="WSSA" index="0016"/>
</parts>
</visit>
<visit>
<general>
<startDateTime>2013-01-10T12:22:39.166Z</startDateTime>
<endDateTime>2013-03-11T13:51:31.480Z</endDateTime>
</general>
<parts>
<part number="02081" name="PSSF" index="0017"/>
</parts>
</visit>
</visits>
</logbook:LogBook>
我想要从这个XML两个输出:
1-参观,包括序列号,所以我写道:
import pandas as pd
import xml.etree.ElementTree as ET
tree = ET.parse(filename)
root=tree.getroot()
visits=pd.DataFrame()
for general in root.iter('general'):
for child in root.iter('serialNumber'):
visits=visits.append({'startDateTime':general.find('startDateTime').text ,
'endDateTime': general.find('endDateTime').text, 'serialNumber':child.attrib['value'] }, ignore_index=True)
这段代码的输出如下数据框:
serialNumber | startDateTime | endDateTime
-------------|------------------------|------------------------|
764000606 |2014-01-10T12:22:39.166Z|2014-03-11T13:51:31.480Z|
764000606 |2013-03-11T13:51:31.480Z|2013-01-10T12:22:39.166Z|
个
2-部分
为parts
,我想有以下输出,在我的startDateTime
相互区分访问的方式,我想显示关联于每次访问的部分:
serialNumber | startDateTime|number|name|index|
-------------|--------------|------|----|-----|
零件我写道:
parts=pd.DataFrame()
for part in root.iter('part'):
for child in root.iter('serialNumber'):
parts=parts.append({'index':part.attrib['index'],
'znumber':part.attrib['number'],
'name': part.attrib['name'], 'serialNumber':child.attrib['value'], 'startDateTime':general.find('startDateTime').text}, ignore_index=True)
这是我从这个代码获得:
index |name|serialNumber| startDateTime |znumber|
------|----|------------|------------------------|-------|
0016 |WSSA| 764000606 |2013-01-10T12:22:39.166Z| 03081 |
0017 |PSSF| 764000606 |2013-01-10T12:22:39.166Z| 02081 |
虽然我想这一点:看startDateTime
:
index |name|serialNumber| startDateTime |znumber|
------|----|------------|------------------------|-------|
0016 |WSSA| 764000606 |2014-01-10T12:22:39.166Z| 03081 |
0017 |PSSF| 764000606 |2013-01-10T12:22:39.166Z| 02081 |
任何想法? 我使用XML ElementTree的
下面是一段代码,从XML获取数据:
import xml.etree.ElementTree as ET
from pprint import pprint as pp
file_name = "a.xml"
def get_product_sn(product_node):
for product_node_child in list(product_node):
if product_node_child.tag == "serialNumber":
return product_node_child.attrib.get("value", None)
return None
def get_parts_data(parts_node):
ret = list()
for parts_node_child in list(parts_node):
attrs = parts_node_child.attrib
ret.append({"number": attrs.get("number", None), "name": attrs.get("name", None), "index": attrs.get("index", None)})
return ret
def get_visit_node_data(visit_node):
ret = dict()
for visit_node_child in list(visit_node):
if visit_node_child.tag == "general":
for general_node_child in list(visit_node_child):
if general_node_child.tag == "startDateTime":
ret["startDateTime"] = general_node_child.text
elif general_node_child.tag == "endDateTime":
ret["endDateTime"] = general_node_child.text
elif visit_node_child.tag == "parts":
ret["parts"] = get_parts_data(visit_node_child)
return ret
def get_node_data(node):
ret = {"visits": list()}
for node_child in list(node):
if node_child.tag == "product":
ret["serialNumber"] = get_product_sn(node_child)
elif node_child.tag == "visits":
for visits_node_child in list(node_child):
ret["visits"].append(get_visit_node_data(visits_node_child))
return ret
def main():
tree = ET.parse(file_name)
root_node = tree.getroot()
data = get_node_data(root_node)
pp(data)
if __name__ == "__main__":
main()
注意:
- 它对待XML在树状方式,所以它地图(如果您愿意)xml(如果xml结构发生变化,代码应该是ad艾普特以及)
- 它的设计是一般:<产品>和<访问>:
get_node_data
可能有2个孩子的节点上调用。在我们的例子中,它是根节点本身,但在现实世界中可能有一系列这样的节点,每个节点都有我上面列出的两个孩子 - 它的设计是对错误友好的,所以如果xml不完整,它将获得尽可能多的数据;我选择了在一个本(贪婪)的方式,当它遇到它只是抛出一个异常的错误
- ,因为我没有与
pandas
工作,而不是填充物我简单地返回一个的Python字典(json);我认为它转换为DataFrame
应该不难 - 我已经与Python2.7和Python3.5
输出(含2个键的字典)运行 - 为缩进可读性:
- SERIALNUMBER - 序列号(显然)
- 访问(因为它是一本字典,我只好把这个数据一键“下”) - 字典列表从<访问>节点
{'serialNumber': '764000606', 'visits': [{'endDateTime': '2014-03-11T13:51:31.480Z', 'parts': [{'index': '0016', 'name': 'WSSA', 'number': '03081'}], 'startDateTime': '2014-01-10T12:22:39.166Z'}, {'endDateTime': '2013-03-11T13:51:31.480Z', 'parts': [{'index': '0017', 'name': 'PSSF', 'number': '02081'}], 'startDateTime': '2013-01-10T12:22:39.166Z'}]}
EDIT0每个包含数据:增加了多个部分节点处理请求的其中一个评论。该功能已移至get_parts_data
。现在,在访问列表中的每个条目将具有份键,其值将是由来自各部分节点(不是用于提供XML的情况下)提取的字典的列表。
在这段代码中,当每个访问有多个部分时,只返回最后一部分。它不会为每次访问返回所有部件。 – Safariba
的确如此。我认为每个_visit_只能有一个_part_节点(如例子_xml_)。你想要它处理多个_part_节点吗? (改变是微不足道的) – CristiFati
是的,我想处理多个部分,我在处理字典方面经验不足,你能帮助我吗?谢谢。 – Safariba
尝试以下方法,
import xml.dom.minidom as minidom
doc = minidom.parse('filename')
memoryElem = doc.getElementsByTagName('part')[0]
print memoryElem.getAttribute('number')
print memoryElem.getAttribute('name')
print memoryElem.getAttribute('index')
希望这将有助于ü。
不应该''终止标记在文件的末尾?因为_XML_文件应该只包含__one__ _root_节点。 – CristiFati
访问'熊猫数据框? – mzjn
@mzjn yes visit = pandas.DataFrame() – Safariba