两个名称相同但位置不同的标签xml。

问题描述 投票:0回答:1

我想用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'。

我也不知道为什么,因为里面有一段文字

python json xml beautifulsoup xml-parsing
1个回答
0
投票

我将使用 旁听生 将你的数据拉出来--你的数据是嵌入在条款和关系中的,所以相应地调整你的代码。

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']

0
投票

我创建了一个工作解决方案,只使用你在代码中指定的包。它看起来像这样。

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文件,你必须检查结果标签列表不是空的。


0
投票

只使用 BeautifulSoupxml_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)]
© www.soinside.com 2019 - 2024. All rights reserved.