2

我有数以千计的 SGML 文档,有些格式正确,有些格式不太好。我需要获取文档中的某些元素,但每次我去加载并尝试将它们读入 XDocument、XMLDocument 甚至只是 StreamReader 时,我都会收到不同的各种 XMLException 错误。

诸如“'[' 是一个意外的标记。”之类的东西。为什么?因为我有一个像 DOCTYPE 这样的文档

<!DOCTYPE RChapter PUBLIC "-//LSC//DTD R Chapter for Authoring//EN" [] >

而且我了解到“[]”内部需要有一些有效的东西。同样,我不控制文档的创建,但我必须“破解”它们并获取我想要的数据。另一个例子是有一个“未封闭”的元素,例如:

<Caption>Plants, and facilities<hardhyphen><hyphen>Inspection.</Caption>

此 XMLException 是“第 27 行的 '连字符' 开始标记与 'Caption' 的结束标记不匹配。第 27 行,位置 58。” 很明显,对吧?

但接下来的问题是,您如何才能在不遇到 XMLExceptions 的情况下真正获得这些文档中的某些 ELEMENTS。SAX 解析器是正确的方法吗?我基本上想打开文档,直接找到我想要的元素(不用担心附近的格式是否正确),提取数据,然后继续。我是否应该忘记使用 XMLDocument、XDocument 进行解析,而只进行简单的字符串替换,例如

str.Replace("<hardhypen><hyphen>", "-")

然后尝试将其加载到 XML 解析器之一。关于策略的任何提示?

4

2 回答 2

3

问题是您正在尝试使用 XML 工具解析 SGML。他们不一样。如果您想使用 XML 工具/语言来访问数据,您可能需要在尝试解析之前将 SGML 转换为 XML。

理想情况下,您要么使用支持 SGML 的语言/工具(如 OmniMark),要么使用可以处理“类似 XML”的数据的工具(如第一个答案中的 nokogiri?)。

这可能非常简单,但在某些时候可能会变得棘手。特别是如果您正在谈论多种文档类型(DTD)。(此外,没有“格式良好的”SGML 这样的东西。是的,元素/等必须正确嵌套,但 SGML必须有一个 DTD。)

以下是您需要处理的 SGML 和 XML 之间的一些差异。(您可能不想走这条路,但无论如何它可能有助于提供信息。):

  1. DOCTYPE 声明

    您示例中的 DOCTYPE 声明是一个完全有效的 SGML 文档类型。([]内部子集)不必包含任何内容。如果您在内部子集中确实有声明(通常是实体声明),那么您很可能必须在 XML 中保留一个 doctype 声明。

    XML 解析器遇到的问题是您在声明中没有系统标识符。在 XML 文档类型声明中,如果有公共标识符,则需要系统标识符。在 SGML 文档类型声明中,它不是必需的。

    底线:除非您需要将 XML 解析为 DTD/Schema 或在内部子集中有声明,否则请去除 doctype 声明。如果 XML 确实必须有效,那么您至少需要添加一个系统标识符。不要忘记添加<?xml ...?>处理指令。

  2. 没有结束标签的元素

    <hardhyphen><hyphen>元素是有效的 SGML 。SGML DTD 允许您指定标记最小化。这意味着您可以指定是否需要结束标记。(您也可以使开始标记成为可选的,但这是疯狂的说法。)在 XML 中,您必须关闭这些元素(如<hardhyphen/><hardhyphen></hardhyphen>

    最好的办法是查看您的 SGML DTD 并查看哪些元素具有可选的结束标记。标签最小化在元素声明中的元素名称之后指定。'-' 表示该标签是必需的。'o'(字母 'oh')表示标签是可选的。例如,如果您看到<!ELEMENT hyphen - o (#PCDATA)>,这意味着开始标签是必需的 ( -),而结束标签是可选的 ( o)。如果您看到<!ELEMENT hyphen - - (#PCDATA)>,则开始和结束标记都是必需的。

    底线:正确关闭所有没有结束标签的元素

  3. 处理指令

    SGML 中的处理指令 (PI) 在?像 XML 那样关闭时没有第二个。您需要添加第二个?.

    SGML PI 示例:<?asdf jkl>

    示例 XML PI: <?asdf jkl?>

  4. 包含/排除

    您可能不必担心这一点,但在 SGML DTD 中,您可以在元素声明中指定另一个元素在该元素内部的任何位置都允许(或不允许)。如果您的目标 XML 需要解析为 DTD,这可能会很痛苦;XML DTD 不允许包含/排除。

    这可能是一个包含的样子:

    <!ELEMENT chapter - - (section)+ +(revst|revend)>

    这就是说revstorrevend被允许在chapter. 如果元素声明有,则-(revst|revend)意味着revst或者不允许在.revendchapter

希望这可以帮助。

于 2010-11-20T07:49:24.983 回答
1

是的,使用Nokogiri

在该页面上向下滚动一点,然后将“概要”下的代码复制到一个文件中,例如xml-parser.rb. 然后,如果您使用的是 Mac(Mac 上已经安装了 Ruby。),请从终端运行gem install nokogiri,然后使用以下命令运行文件:ruby xml-parser.rb.

然后,您也可以irb直接从终端输入,然后require 'nokogiri'开始实时使用 nokogiri api。一定要喜欢交互式 Ruby。:)

如果你在 Windows 上,试试这个Windows 的 Ruby 安装程序

于 2010-11-20T04:01:58.203 回答