python - 提取 xml 中的第一个元素 - 使用 xxx.find() 会导致非类型错误?
问题描述
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 - 然而,这仅代表一个项目(例如一本特定的书),通常这些文件包含数百到数千记录 - 所以记录标签及其所有内容都是可重复的。
我使用的文件中有超过 10,000 个记录标签(都代表不同的项目),所有这些标签都有一个带有标签“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)
但是,这不会返回相应的。附加任何内容,如果我之后打印列表的长度,它会显示“0”。我也为作者和 ID 做了同样的事情,它对那些人有效。我正在努力做到这一点,以便之后我可以创建一个包含作者、ID、标题等的数据框。
我目前完全被困在这个:路径错了吗?还有另一种更简单、更好的方法吗?
解决方案
我假设您已经使用以下代码阅读了您的 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
推荐阅读
- ios - 无法在使用 iOS 9 的设备上安装 Firebase 分发版本
- java - 二维数组列表会自动更新列表中的所有二维数组,并使用 java 中最后提供的二维数组
- python - 无法通过 pywin32 使用 Excel 选择活动打印机
- javascript - 如何通过 Chrome 扩展程序捕获 cookie
- javascript - 如何制定规则,使每个用户js反应只能运行一次函数?
- google-apps-script - 有没有办法将工作表复制到另一个包含脚本功能的电子表格?
- python - 有没有办法在熊猫数据框中取消嵌套列表列?
- firebase - 暴露 Google Analytics Tag 对敏感数据造成的危害
- linux - 在我的 Amazon Linux 2 上释放一些内存空间
- c# - 如何在 C# WPF 中访问我的解决方案中的图像文件