我在整理从SEC的edgar数据库返回的格式错误的XML代码时遇到了问题。
由于某些原因,它们的xml格式很糟糕。包含任何类型字符串的标签都不是封闭的,它实际上可以在其他标签中包含其他xml或html文档。通常我会把它交给Tidy,但现在没有维护。
我试过使用Nokogiri::XML::SAX::Parser,但这似乎是窒息,因为标签没有关闭。它似乎工作得很好,直到它击中了第一个结束标签,然后它就不会再发射了。但它吐出了正确的字符。
class Filing < Nokogiri::XML::SAX::Document
def start_element name, attrs = []
puts "starting: #{name}"
end
def characters str
puts "chars: #{str}"
end
def end_element name
puts "ending: #{name}"
end
end
这似乎是最好的选择,因为我可以简单地让它忽略其他xml或html文档。此外,这也是最有意义的,因为有些文档可能会变得非常大,所以将整个dom存储在内存中可能行不通。
下面是一些示例文件:1 2 3我开始想我只需要写我自己的自定义解析器
Nokogiri的正常DOM模式能够自动修复XML,使其在语法上是正确的,或者是一个合理的副本。它有时会变得混乱,并且会改变结束标记,但是如果需要的话,您可以预处理文件以向正确的方向推动它。
我将XML #1保存为文档并加载它:
require 'nokogiri'
doc = ''
File.open('./test.xml') do |fi|
doc = Nokogiri::XML(fi)
end
puts doc.to_xml
解析后,您可以检查Nokogiri::XML::Document实例的errors
方法,以查看生成了哪些错误。
doc.errors
如果使用Nokogiri的DOM模型还不够好,您是否考虑过使用XMLLint来预处理和清理数据,发出干净的XML,以便SAX能够工作?它的--recover
选项可能有用。
xmllint --recover test.xml
它将在stderr上输出错误,在stdout上输出代码,因此您可以轻松地将其管道传输到另一个文件。
至于编写自己的解析器…为什么?您还有其他可用的选择,重新设计一个实现得很好的转轮并不是在浪费时间。