为什么 Element.attrib 不包含命名空间定义?



我想创建一个XML命名空间映射(例如,在ElementTree的Python文档中使用findall调用)。鉴于这些定义似乎作为xbrl根元素的属性而存在,我本以为我可以在ElementTree中检查root元素的attrib属性。但是,下面的代码

from io import StringIO
import xml.etree.ElementTree as ET

TEST = '''<?xml version="1.0" encoding="utf-8"?>
<xbrl
  xml:lang="en-US"
  xmlns="http://www.xbrl.org/2003/instance"
  xmlns:country="http://xbrl.sec.gov/country/2021"
  xmlns:dei="http://xbrl.sec.gov/dei/2021q4"
  xmlns:iso4217="http://www.xbrl.org/2003/iso4217"
  xmlns:link="http://www.xbrl.org/2003/linkbase"
  xmlns:nvda="http://www.nvidia.com/20220130"
  xmlns:srt="http://fasb.org/srt/2021-01-31"
  xmlns:stpr="http://xbrl.sec.gov/stpr/2021"
  xmlns:us-gaap="http://fasb.org/us-gaap/2021-01-31"
  xmlns:xbrldi="http://xbrl.org/2006/xbrldi"
  xmlns:xlink="http://www.w3.org/1999/xlink"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  </xbrl>'''

xbrl = ET.parse(StringIO(TEST))
print(xbrl.getroot().attrib)

产生以下输出:

{'{http://www.w3.org/XML/1998/namespace}lang': 'en-US'}

为什么没有任何名称空间属性显示在root.attrib ?我至少希望xlmns在字典中,因为它没有前缀。

我尝试了什么?

下面的代码似乎可以生成名称空间映射:

print({prefix: uri for key, (prefix, uri) in ET.iterparse(StringIO(TEST), events=['start-ns'])})

输出:

{'': 'http://www.xbrl.org/2003/instance',
'country': 'http://xbrl.sec.gov/country/2021',
'dei': 'http://xbrl.sec.gov/dei/2021q4',
'iso4217': 'http://www.xbrl.org/2003/iso4217',
'link': 'http://www.xbrl.org/2003/linkbase',
'nvda': 'http://www.nvidia.com/20220130',
'srt': 'http://fasb.org/srt/2021-01-31',
'stpr': 'http://xbrl.sec.gov/stpr/2021',
'us-gaap': 'http://fasb.org/us-gaap/2021-01-31',
'xbrldi': 'http://xbrl.org/2006/xbrldi',
'xlink': 'http://www.w3.org/1999/xlink',
'xsi': 'http://www.w3.org/2001/XMLSchema-instance'}

但是要解析文件两次是不是很恶心。

关于你的具体问题的答案,为什么attrib列表不包含命名空间前缀decls,很抱歉没有熄灭的答案:因为它们不是属性。

http://www.w3.org/XML/1998/namespace是一个特殊的模式,它的行为与用户空间中的其他模式不同。在表示中,xmlns:prefix="uri"是一个属性。在所有其他从属(通过解析序列)模式中,xmlns:prefix="uri"是一个特殊的东西,是一个名称空间前缀声明,它不同于节点或元素上的属性。我没有参考资料,但它在我使用过的至少六种(正确的)XML解析器实现中完全成立,包括IBM, Microsoft和Oracle。

关于重新解析文件的丑陋,我理解你的痛苦,但这是必要的。正如delaney所指出的那样,您可能不认为所有名称空间命名符或前缀都必须位于根元素上。

准备好相同的前缀在文档中的每个节点上用不同的命名空间重新定义的可能性。这可能成立,并且库必须正确地处理它,即使您的文档从未出现过这种情况(或者更糟,如果到目前为止从未出现过)。

考虑是否在可能有更好的解决方案(如XPath或XQuery)的情况下强行执行一些文本处理来解析或查询XML。最近对Saxon的Python包装器进行了一些很好的更改,尽管它们的定价模型发生了变化。

最新更新