¿Cómo evita que los analizadores .NET XML expandan las entidades de parámetros en XML?

Cuando bash analizar el xml a continuación (con el código a continuación), sigo recibiendo &question;&signature;

expandido a

 Why couldn't I publish my books directly in standard SGML? — William Shakespeare. 

O

  

Ya que estoy trabajando en un algoritmo de fusión de 3 vías XML, me gustaría recuperar el &question;&signature;

Yo he tratado:

  • Analizando el xml normaly (esto da como resultado la etiqueta sgml expandida)
  • Al eliminar el Doctype desde el principio en el XML, esto da como resultado una etiqueta sgml vacía)
  • Varios ajustes de DTD de XmlReader

Tengo el siguiente archivo XML:

 <!DOCTYPE sgml [      ]> &question;&signature; 

Aquí está el código que he intentado (varios bashs):

 using System.IO; using System.Xml; using System.Xml.Linq; using System.Reflection; class Program { static void Main(string[] args) { string xml = @"C:\src\Apps\Wit\MergingAlgorithmTest\MergingAlgorithmTest\Tests\XMLMerge-DocTypeExpansion\DocTypeExpansion.0.xml"; var xmlSettingsIgnore = new XmlReaderSettings { CheckCharacters = false, DtdProcessing = DtdProcessing.Ignore }; var xmlSettingsParse = new XmlReaderSettings { CheckCharacters = false, DtdProcessing = DtdProcessing.Parse }; using (var fs = File.Open(xml, FileMode.Open, FileAccess.Read)) { using (var xmkReaderIgnore = XmlReader.Create(fs, xmlSettingsIgnore)) { // Prevents Exception "Reference to undeclared entity 'question'" PropertyInfo propertyInfo = xmkReaderIgnore.GetType().GetProperty("DisableUndeclaredEntityCheck", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); propertyInfo.SetValue(xmkReaderIgnore, true, null); var doc = XDocument.Load(xmkReaderIgnore); Console.WriteLine(doc.Root.ToString()); // outputs  not &question;&signature; }// using xml ignore fs.Position = 0; using (var xmkReaderIgnore = XmlReader.Create(fs, xmlSettingsParse)) { var doc = XDocument.Load(xmkReaderIgnore); Console.WriteLine(doc.Root.ToString()); // outputs Why couldn't I publish my books directly in standard SGML? - William Shakespeare. not &question;&signature; } fs.Position = 0; string parseXmlString = String.Empty; using (StreamReader sr = new StreamReader(fs)) { for (int i = 0; i < 7; ++i) // Skip DocType sr.ReadLine(); parseXmlString = sr.ReadLine(); } using (XmlReader xmlReaderSkip = XmlReader.Create(new StringReader(parseXmlString),xmlSettingsParse)) { // Prevents Exception "Reference to undeclared entity 'question'" PropertyInfo propertyInfo = xmlReaderSkip.GetType().GetProperty("DisableUndeclaredEntityCheck", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); propertyInfo.SetValue(xmlReaderSkip, true, null); var doc2 = XDocument.Load(xmlReaderSkip); // Empty sgml tag } }//using FileStream } } 

Linq-to-XML no admite el modelado de referencias de entidades, se expanden automáticamente a sus valores ( fuente 1 , fuente 2 ). Simplemente no hay una subclase de XObject definida para una referencia de entidad general.

Sin embargo, suponiendo que su XML sea válido (es decir, las referencias de la entidad existen en la DTD, como lo hacen en su ejemplo), puede usar el antiguo Modelo de Objeto de Documento XML para analizar su XML e insertar nodos XmlEntityReference en su árbol DOM XML, en lugar de expandir La entidad hace referencia en texto plano:

  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 &question;&signature; 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 } 

los ChildNodes de cada XmlEntityReference tendrán el valor de texto de la entidad general. Si una entidad general se refiere a otras entidades generales, como se hace en su caso, la correspondiente XmlEntityReference interna se XmlEntityReference en los ChildNodes de la externa. Luego puede comparar el XML antiguo y el nuevo utilizando la antigua API XmlDocument .

Tenga en cuenta que también necesita usar el antiguo XmlTextReader y establecer EntityHandling = EntityHandling.ExpandCharEntities .