如何使用 BeautifulSoup 访问命名空间的 XML 元素?
Posted
技术标签:
【中文标题】如何使用 BeautifulSoup 访问命名空间的 XML 元素?【英文标题】:How can I access namespaced XML elements using BeautifulSoup? 【发布时间】:2011-03-04 18:54:19 【问题描述】:我有一个这样的 XML 文档:
<xml>
<web:Web>
<web:Total>4000</web:Total>
<web:Offset>0</web:Offset>
</web:Web>
</xml>
我的问题是如何使用 Python 中的 BeautifulSoup 之类的库来访问它们?
xmlDom.web["Web"].Total ?不工作?
【问题讨论】:
BeautifulSoup = 4.6.1 (20180728) 后已过时 【参考方案1】:BeautifulSoup 本身并不是一个 DOM 库(它没有实现 DOM API)。更复杂的是,您在该 xml 片段中使用命名空间。要解析特定的 XML 片段,您可以使用 BeautifulSoup,如下所示:
from BeautifulSoup import BeautifulSoup
xml = """<xml>
<web:Web>
<web:Total>4000</web:Total>
<web:Offset>0</web:Offset>
</web:Web>
</xml>"""
doc = BeautifulSoup( xml )
print doc.find( 'web:total' ).string
print doc.find( 'web:offset' ).string
如果您不使用命名空间,代码可能如下所示:
from BeautifulSoup import BeautifulSoup
xml = """<xml>
<Web>
<Total>4000</Total>
<Offset>0</Offset>
</Web>
</xml>"""
doc = BeautifulSoup( xml )
print doc.xml.web.total.string
print doc.xml.web.offset.string
这里的关键是 BeautifulSoup 对命名空间一无所知(或关心)。因此web:Web
被视为web:web
标记,而不是属于eweb
命名空间的Web
标记。虽然 BeautifulSoup 将 web:web
添加到 xml 元素字典中,但 python 语法不会将 web:web
识别为单个标识符。
您可以通过阅读documentation了解更多信息。
【讨论】:
谢谢!现在完美运行。我总是对给 find() 提供什么感到困惑。这些命名空间定义和它们的编写方式让我很困惑...任何清除所有这些的链接都将不胜感激! 只是我已经给你的文档链接......以及大量的实验。AttributeError: 'NoneType' object has no attribute 'string'
【参考方案2】:
这是一个老问题,但如果您将'xml'
作为第二个参数传递给构造函数,那么至少有人可能不知道BeautifulSoup 4 确实 可以很好地处理命名空间:
soup = BeautifulSoup("""<xml>
<web:Web>
<web:Total>4000</web:Total>
<web:Offset>0</web:Offset>
</web:Web>
</xml>""", 'xml')
print soup.prettify()
<?xml version="1.0" encoding="utf-8"?>
<xml>
<Web>
<Total>
4000
</Total>
<Offset>
0
</Offset>
</Web>
</xml>
【讨论】:
这对于 4.4.1-1 版本(在 ubuntu 64 16.04 中)并不完全正确。由于 cmets 是有限的。见link【参考方案3】:您应该使用xmlns:prefix="URI"
syntax (see examples here) 在根元素上明确定义您的命名空间,然后通过 BeautifulSoup 中的prefix:tag
访问您的属性。请记住,您还应该明确定义什么,BeautifulSoup 应该如何处理您的文档,在这种情况下:
xml = BeautifulSoup(xml_content, 'xml')
【讨论】:
【参考方案4】:环境
import bs4
bs4.__version__
---
4.10.0'
import sys
print(sys.version)
---
3.8.10 (default, Nov 26 2021, 20:14:08)
[GCC 9.3.0]
带有命名空间定义的 XML 上的 BS4/XML 解析器
from bs4 import BeautifulSoup
xbrl_with_namespace = """
<?xml version="1.0" encoding="UTF-8"?>
<xbrl
xmlns:dei="http://xbrl.sec.gov/dei/2020-01-31"
>
<dei:EntityRegistrantName>
Hoge, Inc.
</dei:EntityRegistrantName>
</xbrl>
"""
soup = BeautifulSoup(xbrl_with_namespace, 'xml')
registrant = soup.find("dei:EntityRegistrantName")
print(registrant.prettify())
---
<dei:EntityRegistrantName>
Hoge, Inc.
</dei:EntityRegistrantName>
没有命名空间定义的 XML 上的 BS4/XML 解析器
xbrl_without_namespace = """
<?xml version="1.0" encoding="UTF-8"?>
<dei:EntityRegistrantName>
Hoge, Inc.
</dei:EntityRegistrantName>
</xbrl>
"""
soup = BeautifulSoup(xbrl_without_namespace, 'xml')
registrant = soup.find("dei:EntityRegistrantName")
print(registrant)
---
None
没有命名空间定义的 XML 上的 BS4/html 解析器
BS4/HTML 解析器将<namespace>:<tag>
视为单个标签,除此之外它还降低了字母。
soup = BeautifulSoup(xbrl_without_namespace, 'html.parser')
registrant = soup.find("dei:EntityRegistrantName".lower())
print(registrant)
---
<dei:entityregistrantname>
Hoge, Inc.
</dei:entityregistrantname>
与大写字母不匹配,因为它们已被转换为小写字母。
registrant = soup.find("dei:EntityRegistrantName")
print(registrant)
---
None
结论
-
提供命名空间定义以将命名空间与 XML 解析器一起使用,或者
使用 HTML 解析器并处理所有小写字母。
【讨论】:
以上是关于如何使用 BeautifulSoup 访问命名空间的 XML 元素?的主要内容,如果未能解决你的问题,请参考以下文章
BeautifulSoup.find_all() 方法不适用于命名空间标签