XML阅读器似乎忽略了标签层次结构

时间:2018-04-22 22:24:34

标签: python xml beautifulsoup

在XML文件中,我试图获取在标记层次结构中不同级别多次出现的标记内容。我正在尝试获取标记最高级别内容,但我的XML阅读器(BeautifulSoup for Python)一直给我错误的内容。

这是具体问题。这是XML文件的一部分(浓缩到我认为相关的部分):

<object>
    <name>person</name>
    <part>
        <name>head</name>
        <bndbox>
            <xmin>337</xmin>
            <ymin>2</ymin>
            <xmax>382</xmax>
            <ymax>66</ymax>
        </bndbox>
    </part>
    <bndbox>
        <xmin>334</xmin>
        <ymin>1</ymin>
        <xmax>436</xmax>
        <ymax>373</ymax>
    </bndbox>
</object>

我有兴趣通过命令

获取此代码段末​​尾的<bndbox>标记内容
box = object.bndbox

但如果我打印出box,我会继续这样做:

<bndbox>
    <xmin>337</xmin>
    <ymin>2</ymin>
    <xmax>382</xmax>
    <ymax>66</ymax>
</bndbox>

这对我没有意义。我持续获得的上面的框是一个低于我要求的层次结构级别,在<part>标记下,所以我应该只能通过

访问此框
object.part.bndbox

,而

object.bndbox

应该为我提供唯一一个直接位于object标记下的框,这是上面代码段中的最后一个框。

2 个答案:

答案 0 :(得分:2)

正如@mjsquthe comments所述:

  

BeautifulSoup返回与该名称匹配的第一个标记,因此object.bbox指的是XML中的第一个bbox,无论层次结构中的位置如何。

因此,要获取第二个 <bndbox>标记,或<bndbox>标记的直接子标记<object>,您可以使用{{ 1}}作为参数。这将仅查找当前标记的直接子标记。

recursive=False

输出:

xml = '''
<object>
    <name>person</name>
    <part>
        <name>head</name>
        <bndbox>
            <xmin>337</xmin>
            <ymin>2</ymin>
            <xmax>382</xmax>
            <ymax>66</ymax>
        </bndbox>
    </part>
    <bndbox>
        <xmin>334</xmin>
        <ymin>1</ymin>
        <xmax>436</xmax>
        <ymax>373</ymax>
    </bndbox>
</object>'''

soup = BeautifulSoup(xml, 'xml')
print(soup.object.find('bndbox', recursive=False))

答案 1 :(得分:1)

走下树

建议,请快速查看官方BeautifulSoup文档HERE

from bs4 import BeautifulSoup

xml = '''<object>
    <name>person</name>
    <part>
        <name>head</name>
        <bndbox>
            <xmin>337</xmin>
            <ymin>2</ymin>
            <xmax>382</xmax>
            <ymax>66</ymax>
        </bndbox>
    </part>
    <bndbox>
        <xmin>334</xmin>
        <ymin>1</ymin>
        <xmax>436</xmax>
        <ymax>373</ymax>
    </bndbox>
</object>'''

soup = BeautifulSoup(xml, 'lxml')

print(soup.find('name'))  # or
# only string > print(soup.find('name').text)

print(soup.part.bndbox.xmin)  # we traverse through the tree >part>bndbox>xmin

print(soup.xmin)

将返回相同的内容,因为它会返回第一次出现的标记

print(soup.find('xmin')) # is the same as soup.xmin

要查找多个相同的标记,特别是第二个

bnxboxes = soup.find_all('bndbox') #
# we can either iterate through it or
print(bnxboxes[1]) # the Second occurence of tag (computer counting 0,1,2..)

我们也可以上树

  

继续“家谱”类比,每个标签和每个字符串都有一个父:包含它的标签。

the_xmin_tag = soup.xmin # we find the xmin tag
print(the_xmin_tag.parent)

我们也可以侧身

using `.next_sibling` and `.previous_sibling`