使用xxx.find()提取xml中的第一个元素会导致非类型错误吗?

2024-05-28 23:21:53 发布

您现在位置:Python中文网/ 问答频道 /正文

xml文件的结构基本上如下所示,它是MARC21 xml格式的书目数据(各地图书馆都使用):

<?xml version="1.0" encoding="UTF-8"?><collection xmlns="http://www.loc.gov/MARC21/slim">
<record type="Bibliographic">
    <leader> ... </leader>
    <controlfield> ... </controlfield>
    ...
    <controlfield> ... </controlfield>
    <datafield tag="123" ... >
        <subfield code="x"> ... </subfield>
        ...
        <subfield code="x"> ... </subfield>
    </datafield>
    <datafield tag="456" ...> 

这里有一个合适的示例文件:https://www.loc.gov/standards/marcxml/Sandburg/sandburg.xml-然而,这只表示一个项目(例如,一本特定的书),通常这些文件包含数百到数千条记录-所以记录标签及其所有内容都是可重复的

我处理的文件中有10000多个记录标记(都代表不同的项),所有这些标记都有一个带有标记“082”的数据字段,然后是几个子字段。 我现在正试图用code="a"来提取子字段中的文本,但是,由于这个字段也是可重复的,而且有些记录有两个,所以我总是只想要第一个。我当前的代码提取这些数据字段中所有子字段code="a"的文本,如下所示:

 for child in record.findall("{http://www.loc.gov/MARC21/slim}datafield[@tag='082']"):
        for subelement in child:
            if subelement.attrib['code'] == "a":
                ddc = subelement.text
                ddccoll.append(ddc)

这是可行的,但是,正如我所说,返回的元素太多了,如果我运行它,然后打印列表的长度,它返回10277条,但是,这个文件中只有10123条记录,所以有一些太多,可能是因为它的重复性

我尝试使用find而不是findall,但得到的错误消息是`TypeError:

TypeError                                 Traceback (most recent call last)
<ipython-input-23-fae786776bcf> in <module>
     18         idcoll.append("nicht vorhanden")
     19 
---> 20     for child in record.find("{http://www.loc.gov/MARC21/slim}datafield[@tag='082']"):
     21         for subelement in child:
     22             if subelement.attrib['code'] == "a":

TypeError: 'NoneType' object is not iterable

我不太清楚为什么,因为字段082应该出现在每一条记录中——但因为我实际上是在子字段之后,所以无论如何,这可能不是正确的方法。现在我试着深入一层,简单地查找代码为a的第一个子元素,代码如下:

for child in record.findall("{http://www.loc.gov/MARC21/slim}datafield[@tag='082']"):
    for subelement in child.find("{http://www.loc.gov/MARC21/slim}subfield[@code='a']"):
        if subelement: 
            ddc = subelement.text
            ddccoll.append(ddc)

但是,这不会返回resp。附加任何内容,如果我在之后打印列表的长度,它会显示“0”。我也为作者和身份证做了同样的工作,它正在为那些人工作。我正在努力做到这一点,以便以后我可以创建一个包含作者、ID、标题等的数据框架

我现在完全陷入这样的困境:这条路错了吗?还有其他更简单更好的方法吗


Tags: 文件inchildhttpfortagwww记录
1条回答
网友
1楼 · 发布于 2024-05-28 23:21:53

我假设您已使用以下代码读取XML:

import xml.etree.ElementTree as et

tree = et.parse('Input.xml')
root = tree.getroot()

要达到您想要的元素,您可以使用以下代码:

# Namespace dictionary
ns = {'slim': 'http://www.loc.gov/MARC21/slim'}
# Process "datafield" elements with the required "tag" attribute
for it in root.findall('.//slim:datafield[@tag="082"]', ns):
    print(f'{it.tag:10}, {it.attrib}')
    # Find the first child with "code" == "a"
    child = it.find('slim:*[@code="a"]', ns)
    if isinstance(child, et.Element):  # Something found
        print(f'  {child.tag:10}, {child.attrib}, {child.text}')
    else:
        print('  Nothing found')

在上面的示例中,我只包含元素的打印语句 找到了,但你可以用它们做任何你想做的事

使用以下源XML:

<?xml version="1.0" encoding="UTF-8"?>
<collection xmlns="http://www.loc.gov/MARC21/slim">
  <record type="Bibliographic">
    <leader>...</leader>
    <controlfield>...</controlfield>
    <datafield tag="082" id="1">
        <subfield code="a">a1</subfield>
        <subfield code="x">x1</subfield>
        <subfield code="a">a2</subfield>
    </datafield>
    <datafield tag="456" id="2">
        <subfield code="a">a3</subfield>
    </datafield>
    <datafield tag="082" id="3">
        <subfield code="a">a4</subfield>
        <subfield code="x">x2</subfield>
        <subfield code="a">a5</subfield>
    </datafield>
  </record>
  <record type="Bibliographic">
    <leader>...</leader>
    <controlfield>...</controlfield>
    <datafield tag="082" id="4">
        <subfield code="a">a6</subfield>
        <subfield code="x">x3</subfield>
        <subfield code="a">a7</subfield>
    </datafield>
    <datafield tag="456" id="5">
        <subfield code="a">a8</subfield>
    </datafield>
  </record>
</collection>

我得到了以下结果:

{http://www.loc.gov/MARC21/slim}datafield, {'tag': '082', 'id': '1'}
  {http://www.loc.gov/MARC21/slim}subfield, {'code': 'a'}, a1
{http://www.loc.gov/MARC21/slim}datafield, {'tag': '082', 'id': '3'}
  {http://www.loc.gov/MARC21/slim}subfield, {'code': 'a'}, a4
{http://www.loc.gov/MARC21/slim}datafield, {'tag': '082', 'id': '4'}
  {http://www.loc.gov/MARC21/slim}subfield, {'code': 'a'}, a6

相关问题 更多 >

    热门问题