我想用Python把一个XML文件变成一个JSON文件。我目前正试图从XML文件中提取信息,使其成为一个dict或dataframe。
这里是XML文件。
<?xml version="1.0" encoding="UTF-8"?>
<Terms>
<Term>
<Title>.177 (4.5mm) Airgun</Title>
<Description>The standard airgun calibre for international target shooting.</Description>
<RelatedTerms>
<Term>
<Title>Shooting sport equipment</Title>
<Relationship>Narrower Term</Relationship>
</Term>
</RelatedTerms>
</Term>
<Term>
<Title>.22</Title>
<Description>A rimfire calibre, much used in target shooting and often synonymous with the term smallbore.</Description>
<RelatedTerms>
<Term>
<Title>Shooting sport equipment</Title>
<Relationship>Narrower Term</Relationship>
</Term>
</RelatedTerms>
</Term>
<Term>
<Title>.22 Long Rifle</Title>
<Description>The standard .22 rimfire cartridge for target rifle and pistol use.</Description>
<RelatedTerms>
<Term>
<Title>Shooting sport equipment</Title>
<Relationship>Narrower Term</Relationship>
</Term>
</RelatedTerms>
</Term>
<Term>
<Title>.22 Short</Title>
<Description>Used as a target shooting round for timed fire pistol competitions.</Description>
<RelatedTerms>
<Term>
<Title>Shooting sport equipment</Title>
<Relationship>Narrower Term</Relationship>
</Term>
</RelatedTerms>
</Term>
</Terms>
当我去调用 标题 标签,它给了我所有的标题标签。然而,我想把主 标题 标签和嵌入在 相关术语 标签。
xml_file = open('xml.xml', encoding='UTF-8')
soup = BeautifulSoup(xml_file, 'lxml-xml', from_encoding='UTF-8')
Terms = soup.select('Terms > Term')
jsonObj = {"thesaurus": []}
for term in Terms:
termDetail = {
"Description": term.find('Description').text,
"Title": term.find('Title').text
}
RelatedTerms = term.select('RelatedTerms > Term')
if RelatedTerms:
termDetail["RelatedTerms"] = []
for rterm in RelatedTerms:
termDetail["RelatedTerms"].append({
"Title": rterm.find('Title').text,
"Relationship": rterm.find('Relationship').text
})
jsonObj["thesaurus"].append(termDetail)
print(json.dumps(jsonObj))
好吧,我已经更新了上面的代码,它基本上是工作的。但是 "Title": rterm.find('Title').text
代码给出的错误
属性错误:'NoneType'对象没有属性'text'。
我也不知道为什么,因为里面有一段文字
我将使用 旁听生 将你的数据拉出来--你的数据是嵌入在条款和关系中的,所以相应地调整你的代码。
from parsel import Selector
data = """[ur code above here]"""
selector = Selector(data)
#extract titles in Terms :
title_in_terms = selector.xpath(".//terms/term/title/text()").getall()
title_in_terms
['.177 (4.5mm) Airgun', '.22', '.22 Long Rifle', '.22 Short']
#extract title in relationship terms:
title_in_relationship_terms = selector.xpath(".//relatedterms/term/title/text()").getall()
title_in_relationship_terms
['Shooting sport equipment',
'Shooting sport equipment',
'Shooting sport equipment',
'Shooting sport equipment']
我创建了一个工作解决方案,只使用你在代码中指定的包。它看起来像这样。
from bs4 import BeautifulSoup as bs
import lxml
xml_file = open('xml.xml', encoding='UTF-8')
soup = bs(xml_file, 'lxml-xml', from_encoding='UTF-8')
term = soup.find_all('Term')[0]
main_title = term.find_all('Title')[0]
related_terms = term.find_all('RelatedTerms')[0]
embedded_title = related_terms.find_all('Title')[0]
print(main_title.string)
print(embedded_title.string)
输出:
.177 (4.5mm) Airgun
Shooting sport equipment
代码强烈保证所有标签至少有一个指定的子标签。因此,如果你有一个没有这种保证的XML文件,你必须检查结果标签列表不是空的。
只使用 BeautifulSoup
当 xml_text
是你在问题中的xml文本,然后这个脚本。
from bs4 import BeautifulSoup
soup = BeautifulSoup(xml_text, 'xml')
data = []
for title, description in zip(soup.select('Terms > Term > Title'), soup.select('Terms > Term > Description')):
data.append({'Title': title.get_text(strip=True),
'Description': description.get_text(strip=True),
'Related Terms': [(rel_title.get_text(strip=True), rel.get_text(strip=True)) for rel_title, rel in zip(
title.find_parent('Term').select('RelatedTerms > Term > Title'),
title.find_parent('Term').select('RelatedTerms > Term > Relationship') )]})
df = pd.DataFrame(data)
print(df)
创建Pandas数据框架。
Title Description Related Terms
0 .177 (4.5mm) Airgun The standard airgun calibre for international ... [(Shooting sport equipment, Narrower Term)]
1 .22 A rimfire calibre, much used in target shootin... [(Shooting sport equipment, Narrower Term)]
2 .22 Long Rifle The standard .22 rimfire cartridge for target ... [(Shooting sport equipment, Narrower Term)]
3 .22 Short Used as a target shooting round for timed fire... [(Shooting sport equipment, Narrower Term)]