【问题标题】:How to parse a DTD file in Ruby如何在 Ruby 中解析 DTD 文件
【发布时间】:2014-07-12 16:31:13
【问题描述】:

我试图将 DTD 文件转换为 YAML 文件,并尝试在 libXML 和 Nokogiri 中加载它,但 DTD 文件似乎不是有效的 XML 文件。只要我可以解析 DTD 文件,我就可以使用任何第三方 gem。

我的转换尝试:

wget "http://xml.evernote.com/pub/enml2.dtd"
irb
require 'nokogiri'
xml = Nokogiri::XML::Document.parse('enml2.dtd')
xml.to_yaml
=> "--- !ruby/object:Nokogiri::XML::Document\ndecorators: \nnode_cache: []\nerrors:\n- !ruby/exception:Nokogiri::XML::SyntaxError\n  message: |\n    Start tag expected, '<' not found\n  domain: 1\n  code: 4\n  level: 3\n  file: \n  line: 1\n  str1: \n  str2: \n  str3: \n  int1: 0\n  column: 1\n"

任何在线 XML 验证器也会返回错误“预期开始标记”。我认为这是因为所有有效的 XML 文档都以 &lt;?xml 开头,而似乎缺少这些 DTD 文件。这就是让我得出所有 DTD 文件都是无效 XML 文件的结论的原因,然而,XML 定义语法本身没有被定义为有效 XML 确实让人感到奇怪。为什么?

我正在解析 DTD 文件以从 XML 文件中删除无效属性,以了解要保留哪些属性以及要删除哪些属性,因此我需要一种方法来解析 DTD 文件。

最终,这只是尝试将 HTML 转换为 ENML(Evernote 标记语言)的一个步骤。其中涉及的步骤包括:

  • 将 HTML 转换为有效的 XHTML
  • 将正文转换为注释元素
  • 根据 dtd 文件删除无效标签和属性
  • 根据 dtd 验证 enml 文件

我目前正在考虑从“Understanding the Evernote Markup Language”复制不允许的属性和标签,并使用它来验证我的 XHTML,但我更喜欢使用 DTD 作为我的源。

Nokogiri DTD 类是一个 Node 类,用于保存内联 DTD 节点并针对它进行验证。就我而言,我有一个使用 SYSTEM 属性指定的外部 DTD 文件,Nokogiri does not seem to support。即使它确实有效,我得到的只是验证。

我确实使用以下方法进行了验证:

#dtd = XML::Dtd.new File.read Rails.root.join('lib', 'assets','enml2.dtd')
#enml_document = XML::Document.string enml
#ret = enml_document.validate dtd

我还没有尝试过 REXML。我会试一试并报告。

我正在尝试将 HTML 文档转换为使用给定 DTD 进行验证的 XML 文档。 ENML 模式中不允许大多数 HTML 元素和属性,因此我必须剥离或删除它们。我还需要知道哪些属性是允许的,哪些是不允许的,这样我才能正确解析 XML 并删除/清理有问题的元素和属性。

出于清理目的,我使用Loofah,但要使用它,我需要一个标签列表->属性(每个标签都可以使用哪些属性)。我没有在清理结束时进行多次验证文档,而是循环遍历每个 XML 标记并清理它们。但要知道 如何 清理它们,我需要知道有效架构中支持哪些标签和元素。因此,我需要解析 DTD 文件。

据我了解,XLST 是适合这项工作的工具,但我觉得使用它不够舒适。

【问题讨论】:

  • 你能分享一下你对 libxml 和 nokogiri 的尝试吗?例如,您是否使用过 Nokogiri::XML::DTD (nokogiri.org/Nokogiri/XML/DTD.html) 或使用 REXML 的 DTD 解析器 (rubydoc.info/stdlib/rexml/REXML/DTD/Parser)
  • 您的输入 XML 文件开始时格式不正确?我对你到底在做什么有点模糊;听起来你正在做转换,它不需要首先匹配 DTD——使用 XSLT 或更合理的等效项并过滤掉你不想要的/添加你所做的等等。
  • 我只是想将 DTD 文件转换为 ruby​​ 哈希。你会怎么做呢? (我会同时研究 XSLT)
  • 我添加了更多关于我正在尝试做的事情的详细信息。
  • “执行自定义清理”是什么意思?为什么仅仅根据 DTD 验证 XML 文件还不够?

标签: ruby xml nokogiri dtd evernote


【解决方案1】:

然而,xml 定义语法本身没有被定义为有效的 XML,这让我感到很奇怪。我很想知道这背后的任何原因。

DTD 是 SGML(XML 的前身)的遗留物,因此 DTD 不是 XML 文件实际上并不奇怪。在创建 XML 时,保留 DTD 及其特定语法是经过深思熟虑的决定。

W3C XML Schema 和 RELAX NG 等更现代的模式语言确实使用 XML 语法。


我解析 DTD 文件的原因是我想从 XML 文件中删除无效属性。要知道要保留哪些属性以及要删除哪些属性,我需要一种解析 DTD 文件的方法。(来自问题)

我只是在寻找一种解析 DTD 文件的方法,而不仅仅是使用它们进行验证,因为我想使用 dtd 执行自定义清理和验证。(来自赏金文本)

我不太明白您所说的“自定义清理”是什么意思。我也看不出尝试解析 DTD 的意义。

为了查明 XML 文件中的任何元素或属性是否无效(如果它们违反了相关 DTD 中的规则),您需要使用验证 XML 解析器解析 XML 文件 .然后解析器会告诉您是否有任何需要修复的错误。

Nokogiri 基于提供验证解析器的 libxml2。它确实支持使用&lt;!DOCTYPE foo SYSTEM "bar.dtd"&gt; 语法指定的外部DTD(如何使这项工作在您引用的问题的评论中显示:https://github.com/sparklemotion/nokogiri/issues/440#issuecomment-3031164)。

验证的方法如下:

require 'nokogiri'

xml = File.read("yourfile.xml")
options = Nokogiri::XML::ParseOptions::DTDLOAD   # Needed for the external DTD to be loaded
doc = Nokogiri::XML::Document.parse(xml, nil, nil, options)
puts doc.external_subset.validate(doc) 

如果此代码没有输出,则 XML 文档对 DTD 有效。

【讨论】:

  • 基本上,我需要通过删除无效元素和属性来使验证通过。要知道要删除哪些元素,要保留哪些元素,我需要解析 DTD 文件。
  • 不,您不需要解析 DTD。您需要像我展示的那样解析 XML 文件。如果验证不通过,解析器会告诉你。
  • 一次验证输出是否能一次性告诉我文档的所有问题?
  • 嗯,是的,这取决于。准备好多次运行验证,迭代地修复问题。
  • 要明白自己真正想要什么并不容易。 Matra 是一个可视化 DTD 的工具;它不是 XML 验证器。您将如何使用 Matra(或等效的 Ruby 程序)输出的结果?我已经问过您所说的“执行自定义清理”是什么意思,但您从未澄清过。
猜你喜欢
  • 2014-12-11
  • 2018-12-05
  • 2011-04-22
  • 1970-01-01
  • 2012-04-15
  • 1970-01-01
  • 1970-01-01
  • 2013-04-28
相关资源
最近更新 更多