【问题标题】:Are parameter entity references in sgml/xml parsible using .NET?是否可以使用 .NET 解析 sgml/xml 中的参数实体引用?
【发布时间】:2015-05-29 16:11:34
【问题描述】:

当我尝试使用 XDocument 解析以下数据时,出现以下错误:

“XMLException:内部标记中不允许参数实体引用”

这是我尝试解析的示例数据:

<!DOCTYPE sgml [
  <!ELEMENT sgml ANY>
  <!ENTITY % std       "standard SGML">
  <!ENTITY % signature " &#x2014; &author;.">
  <!ENTITY % question  "Why couldn&#x2019;t I publish my books directly in %std;?">
  <!ENTITY % author    "William Shakespeare">
]>
<sgml>&question;&signature;</sgml>

这是试图解析上述文件的代码:

string caFile = @"pathToFile";
using (var caStream = File.Open(caFile, FileMode.Open, FileAccess.Read))
{
    var caDoc = XDocument.Load(caStream); // Exception thrown here!
}

有没有办法让内置的 .NET xml 解析库来处理实体引用,或者至少忽略嵌入的 !Doctype 并解析根元素?

注意:我假设参数实体引用在 XML 中有效。 (see here)

【问题讨论】:

  • 我猜你的例子来自Wikipedia。那只是有效的 SGML,而不是 XML。见talk page

标签: c# .net xml sgml


【解决方案1】:

这里有一些问题,但主要是您应该使用General Entities

  1. 您将实体定义为参数实体。这些基本上是仅在 DTD 本身内部使用的宏。来自XML Specification

    参数实体引用不得出现在 DTD 之外。

    来自XML in a Nutshell 2nd Edition

    最好定义一个常量,该常量可以保存所有五种列表的内容规范的公共部分,并从每个元素的内容规范内部引用该常量。 ...

    实体引用是这里的明显候选者。但是,一般实体引用不允许为内容规范或属性列表提供替换文本,只能用于将包含在 XML 文档本身中的部分 DTD。相反,XML 提供了一个专门用于 DTD 内部的新构造,即参数实体,由参数实体引用引用。参数实体的行为和声明几乎完全像一般实体。但是,它们使用 % 而不是 &,并且它们只能在 DTD 中使用,而一般实体只能在文档内容中使用。

    然而,您的 XML 指的是其文档内容中的实体。这表明您应该使用general entities 而不是参数实体。

  2. 您的一个参数实体%question 在其替换文本中嵌入了对另一个参数实体%std; 的引用。 XML Specification 明确禁止这样做:

    在内部 DTD 子集中,参数实体引用不得出现在标记声明中;它们可能发生在可以发生标记声明的地方。 (这不适用于出现在外部参数实体或外部子集中的引用。)

    再次看来,您应该使用一般实体而不是参数实体,因为前者可以使用 "inside the DTD in places where they will eventually be included in the body of an XML document, for instance ... in the replacement text of another entity."

  3. 您需要通过设置XmlReaderSettings.ProhibitDtd = false(.Net 3.5)或XmlReaderSettings.DtdProcessing = DtdProcessing.Parse(更高版本)来启用DTD处理。

把这些放在一起,下面的代码:

    string xmlGood = @"<!DOCTYPE sgml [
  <!ELEMENT sgml ANY>
  <!ENTITY std       ""standard SGML"">
  <!ENTITY signature "" &#x2014; &author;."">
  <!ENTITY question  ""Why couldn&#x2019;t I publish my books directly in &std;?"">
  <!ENTITY author    ""William Shakespeare"">
]>
<sgml>&question;&signature;</sgml>";

    var settings = new XmlReaderSettings { DtdProcessing = DtdProcessing.Parse };

    using (var sr = new StringReader(xmlGood))
    using (var xmlReader = XmlReader.Create(sr, settings))
    {
        var doc = XDocument.Load(xmlReader);
        Console.WriteLine(doc);
    }               

产生以下输出:

<!DOCTYPE sgml [
  <!ELEMENT sgml ANY>
  <!ENTITY std       "standard SGML">
  <!ENTITY signature " — &author;.">
  <!ENTITY question  "Why couldn’t I publish my books directly in &std;?">
  <!ENTITY author    "William Shakespeare">
]>
<sgml>Why couldn’t I publish my books directly in standard SGML? — William Shakespeare.</sgml>

正如您所见,一般实体已被解析和扩展。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-06
  • 2015-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-09
相关资源
最近更新 更多