如何在Ruby中整理格式不正确的XML

3

我遇到了一个问题,无法整理从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 我开始觉得我只能写自己的定制解析器了。

请定义“相当大”的含义,当您指的是大文件时。如今,大多数机器都可以轻松处理几个GB的文件。 - the Tin Man
1个回答

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上输出代码,因此您可以轻松地将其管道传输到另一个文件。
至于编写自己的解析器...为什么?您有其他可用选项,并且重新发明一个已经很好实现的轮子不是一个好的时间利用方式。

这两种解决方案都无法与示例文件配合使用。它们将大多数闭合标签放在末尾。 - hadees
2
这正是为什么我说有时候你必须预处理文件,为解析器提供足够的信息以正确执行操作。 - the Tin Man
@hadees,这两种解决方案都不可行,因为它们试图恢复格式不正确的XML,而这是标准明确禁止的。工具无法知道在哪里关闭标签。 - Serabe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接