如何在Ruby中解析DTD文件

Nem*_*emo 8 ruby xml dtd nokogiri evernote

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

我尝试转换:

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"
Run Code Online (Sandbox Code Playgroud)

任何在线XML验证器也会返回错误"Start tag expected".我认为这是因为所有有效的XML文档都以<?xml,DTD文件似乎缺失.这就是我得出的结论,即所有DTD文件都是无效的XML文件,但是,XML定义语法本身没有被定义为有效的XML,这确实让人感到奇怪.为什么?

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

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

  • 将HTML转换为有效的XHTML
  • 将正文转换为en-note元素
  • 根据dtd文件删除无效标记和属性
  • 针对dtd验证enml文件

我目前正在考虑从" 理解Evernote标记语言 "中复制不允许的属性和标记,并使用它来验证我的XHTML,但我更喜欢使用DTD作为我的源代码.

Nokogiri DTD类是一个Node类,用于保存内联DTD节点并对其进行验证.在我的例子中,我有一个使用SYSTEM属性指定的外部DTD文件,Nokogiri似乎不支持.即使它确实有效,我所得到的只是验证.

我确实使用以下方法验证了正常工作:

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

我还没试过REXML.我会给你一个回报并报告.

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

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

据我所知,XLST是适合这项工作的合适工具,但我对使用它感到不舒服.

mzj*_*zjn 3

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

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

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


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

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

我不太明白你所说的“自定义清理”是什么意思。我也不认为首先尝试解析 DTD 有何意义。

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

Nokogiri 基于 libxml2,它提供了一个验证解析器。它确实支持使用语法指定的外部 DTD <!DOCTYPE foo SYSTEM "bar.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) 
Run Code Online (Sandbox Code Playgroud)

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