在Python中解析XBRL文件
我正在做一个 XML 解析器。 我的目标是解析一些不同的 XML 文件,这些文件的前缀和标签是一致的,但命名空间会变化。
因此,我尝试了以下几种方法:
- 直接解析 XML,使用
<prefix:tags>
的形式,而不去处理(替换)前缀和命名空间。前缀在不同的文档中保持不变。 - 自动加载命名空间,这样就可以用正确的命名空间替换标识符(
<prefix:tag>
)。 - 仅仅通过标签解析 XML。
我尝试过使用 xml.etree.ElementTree
。
我也看过 lxml
,但是在 lxml 的 XMLParser 中没有找到任何配置选项可以帮助我,尽管在 这里我看到一个答案,作者建议 lxml
应该能够自动收集命名空间。
有趣的是,parsed_file = etree.XML(file)
这行代码出错了,错误信息是:
lxml.etree.XMLSyntaxError: Start tag expected, '<' not found, line 1, column 1
我想解析的文件的一个例子可以在 这里找到。
2 个回答
别太在意前缀,关注完整的命名空间
有时候,人们会关注那些短短的前缀,但其实它们并不是最重要的。前缀只是对完整命名空间的简短引用。例如:
xmlns:trw="http://www.trw.com/20131231"
在 XML 中,这意味着从现在开始,"trw:"
代表完整的命名空间 "http://www.trw.com/20131231"
。需要注意的是,这个前缀可以在后面的元素中被重新定义,可能会有完全不同的含义。
另一方面,当你真正关心的是完整的含义时,可以把 "trw:row"
理解为 "{http://www.trw.com/20131231}row"
。这个翻译的含义是可靠的,不会因为前缀的变化而改变。
解析引用的 XML
链接 http://edgar.sec.gov/Archives/edgar/data/1267097/000104746914000925/trw-20131231.xml 指向一个 XML 文件,这个文件可以通过 xmlstarlet
验证,并且 lxml
可以解析。
你看到的错误信息是指向流的第一个字符,这意味着你可能在文件中遇到了 BOM 字节,或者你正在尝试读取一个被压缩的 XML 文件,这个文件需要先解压。
lxml 和命名空间
lxml
对命名空间的处理非常好。它允许你使用包含命名空间的 XPath 表达式。不过,控制输出中的命名空间前缀会稍微复杂一些,因为这取决于 xmlns
属性,这些属性是序列化文档的一部分。如果你想修改前缀,必须以某种方式组织这些 xmlns
属性,通常是把它们都移动到根元素。同时,lxml
会跟踪每个元素的完整命名空间,所以在序列化时,它会尊重这个完整名称以及当前有效的前缀。
处理这些 xmlns
属性需要写更多的代码,可以参考 lxml
的文档。
items = tree.xpath("*[local-name(.) = 'a_tag_goes_here']")
这个方法有效。不过,我还得手动查看生成的列表 items
,才能定义我想要的其他过滤功能。