考虑以下只包含两个名为XML
的节点的Mydoc
:
<?xml version="1.0" encoding="UTF-8" ?>
<Mydoc Time="2017-01-02"
Period="2017-01-03">
<mycontent ClassID="kinder">
<bibliography>
<Id>
<Num>123456</Num>
</Id>
<Body>
this is some crazy text my friend
</Body>
<myreaders>
<names>
<Id>john</Id>
<value>95</value>
</names>
</myreaders>
<school>
<myclass>
<Id>12</Id>
<name>Laura</name>
</myclass>
<myclass>
<Id>14</Id>
<name>Frank</name>
</myclass>
<myclass>
<Id>144</Id>
<name>Jonny</name>
</myclass>
<myclass>
<Id>222</Id>
<name>Alex</name>
</myclass>
<myclass>
<Id>5443</Id>
<name>Johnny Doe</name>
</myclass>
</school>
</bibliography>
</mycontent>
<mycontent ClassID="preK">
<bibliography>
<Id>
<Num>123456</Num>
</Id>
<Body>
this is another crazy text my friend
</Body>
<myreaders>
<names>
<Id>fritz</Id>
<value>133</value>
</names>
</myreaders>
</bibliography>
</mycontent>
</Mydoc>
我正在尝试使用xml.etree
对其进行解析,并将每个节点mydoc
放入Pandas
数据框中的单行中。
但是,正如您所看到的,我想将多个名为myclass
的元素合并到我的数据帧的一个单元格中。
例如,预期输出(Pandas
数据框两行两列)将类似于:
myreaders school
"(john-95)" "(12-Laura),(14-Frank),(144-Johnny),(222-Alex),(5443-Johnny Doe)"
"(fritz-133)" ""
我尝试使用xpath
,但我无法将xpath
次查询合并到"(12-Laura),(14-Frank),(144-Johnny),(222-Alex),(5443-Johnny Doe)"
有什么建议吗?
谢谢!
答案 0 :(得分:1)
您可以尝试XmlToDict,并将您的XML解析为词典/列表,它可以使您尝试做的更容易。 然后你可以循环/通过什么是myclass字典列表。 希望有所帮助。
答案 1 :(得分:1)
它变成了列表理解装置,但我认为这就是你所需要的。
import xml.etree.ElementTree as ET
import pandas as pd
tree = ET.parse('test.xml')
root = tree.getroot()
dicty = {}
dicty['myreaders'] = [','.join(['(' + x.findall('Id')[0].text + '-' + x.findall('value')[0].text + ')' for x in (root.findall('.//mycontent/bibliography/myreaders/names'))])]
dicty['school'] = [','.join(['(' + x.findall('Id')[0].text + '-' + x.findall('name')[0].text + ')' for x in (root.findall('.//mycontent/bibliography/school/myclass'))])]
print(dicty)
print(pd.DataFrame(dicty))
输出:
myreaders school
0 (john-95) (12-Laura),(14-Frank),(144-Jonny),(222-Alex),(...
没有真正简单的方法来解析xml,你需要对数据结构有很多了解。
答案 2 :(得分:1)
你考虑过使用lxml模块吗?它有一些非常方便的方法来解析和遍历xml文件。 例如,我尝试了以下findall-lists并将它们组合在一起,然后您可以将它们添加到记录的“其余”中:
from lxml import etree
root = etree.parse(path_to_xml_file)
ids = [i.text for i in root.findall(".//myclass/Id")]
names = [n.text for n in root.findall(".//myclass/Name")]
comb = list(zip(ids,names))
这会给你:
[('12', 'Laura'), ('14', 'Frank'), ('144', 'Jonny'), ('222', 'Alex')]
答案 3 :(得分:1)
与其他答案类似,位更短,适用于新添加的节点:
parsedXML = ET.parse( "sample.xml")
root = parsedXML.getroot()
pairs0 = []
pairs1 = []
for mycontent in root.iter('mycontent'):
pairs0.append(','.join(['(' + name[0].text + '-' + name[1].text + ')' for name in mycontent.iter('names')]))
pairs1.append(','.join(['(' + myclass[0].text + '-' + myclass[1].text + ')' for myclass in mycontent.iter('myclass')]))
df = pd.DataFrame(data = {"myreaders": pairs0, "school": pairs1}, columns=['myreaders', 'school'])
编辑:重写以解决多个案例。