如何使.NET XML解析器不在XML中扩展参数实体?

时间:2015-06-02 14:24:18

标签: c# .net xml dtd

当我尝试解析下面的xml时(下面的代码)我不断得到replaced

扩展到

<sgml>&question;&signature;</sgml>

OR

<sgml>Why couldn’t I publish my books directly in standard SGML? — William Shakespeare.</sgml>

由于我正在研究XML 3-way Merging算法,我想检索未扩展的 <sgml></sgml>

我试过了:

  • 正常解析xml(这会导致扩展的sgml标记)
  • 从xml开头删除Doctype会导致空sgml标记)
  • 各种XmlReader DTD设置

我有以下XML文件:

<sgml>&question;&signature;</sgml>

以下是我尝试的代码(多次尝试):

<!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>

1 个答案:

答案 0 :(得分:1)

Linq-to-XML不支持实体引用的建模 - 它们会自动扩展为其值(source 1source 2)。根本没有为一般实体引用定义XObject的子类。

但是,假设您的XML有效(即DTD中存在实体引用,它们在您的示例中执行),您可以使用XML Document Object Model 来解析XML并插入将XmlEntityReference个节点放入XML DOM树中,而不是将实体引用扩展为纯文本:

        using (var sr = new StreamReader(xml))
        using (var xtr = new XmlTextReader(sr))
        {
            xtr.EntityHandling = EntityHandling.ExpandCharEntities; // Expands character entities and returns general entities as System.Xml.XmlNodeType.EntityReference
            var oldDoc = new XmlDocument();
            oldDoc.Load(xtr);
            Debug.WriteLine(oldDoc.DocumentElement.OuterXml); // Outputs <sgml>&question;&signature;</sgml>
            Debug.Assert(oldDoc.DocumentElement.OuterXml.Contains("&question;")); // Verify that the entity references are still there - no assert
            Debug.Assert(oldDoc.DocumentElement.OuterXml.Contains("&signature;")); // Verify that the entity references are still there - no assert
        }

每个XmlEntityReference的{​​{3}}将具有一般实体的文本值。如果一般实体引用其他一般实体,就像您的情况一样,相应的内部XmlEntityReference将嵌套在外部的ChildNodes中。然后,您可以使用旧的XmlDocument API比较旧XML和新XML。

请注意,您还需要使用旧版ChildNodes并设置XmlTextReader