如何在Ruby中解析DTD文件

时间:2014-07-12 16:31:13

标签: ruby xml nokogiri dtd 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"

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

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

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

  • 将HTML转换为有效的XHTML
  • 将正文转换为en-note元素
  • 根据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,但要使用它,我需要一个tag-&gt;属性列表(每个标签都有这些属性)。我没有进行多次验证文档,而是在清理结束时进行验证,而只是循环遍历每个XML标记并清理它们。但是要知道如何来清理它们,我需要知道有效模式中支持哪些标记和元素。因此,我需要解析DTD文件。

根据我的理解,XLST是适合这项工作的合适工具,但我不习惯使用它。

1 个答案:

答案 0 :(得分:2)

  

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

DTD是XML的前身SGML的延续,因此DTD不是XML文件实际上并不奇怪。在创建XML时,保留DTD及其特定语法是一个慎重的决定。

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


  

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

     

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

我真的不明白你的意思&#34;定制清理&#34;。我也没有看到尝试解析DTD的重点。

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

Nokogiri基于libxml2,它提供了一个验证解析器。它支持使用<!DOCTYPE foo SYSTEM "bar.dtd">语法指定的外部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有效。

相关问题