¿Cómo puedo resolver entidades al cargar en un XDocument?

Intento cargar un documento XHTML en un XDocument pero recibo excepciones de “referencia a entidades no declaradas”. Necesito resolver entidades como ® y » .

Creo que mi documento está formado correctamente, aquí está la cabeza:

    

Cuando hago un XDocument.Load() es cuando XDocument.Load() estas excepciones.

Esta es una colaboración de publicaciones msdn y blog.

  XDocument document; using (var stringReader = new StringReader(output)) { var settings = new XmlReaderSettings { ProhibitDtd = false, XmlResolver = new LocalXhtmlXmlResolver(bool.Parse(ConfigurationManager.AppSettings["CacheDTDs"])) }; document = XDocument.Load(XmlReader.Create(stringReader, settings)); } private class LocalXhtmlXmlResolver : XmlUrlResolver { private static readonly Dictionary KnownUris = new Dictionary { { "-//W3C//DTD XHTML 1.0 Strict//EN", new Uri("http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd") }, { "-//W3C XHTML 1.0 Transitional//EN", new Uri("http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd") }, { "-//W3C//DTD XHTML 1.0 Transitional//EN", new Uri("http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd") }, { "-//W3C XHTML 1.0 Frameset//EN", new Uri("http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd") }, { "-//W3C//DTD XHTML 1.1//EN", new Uri("http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd") } }; private bool enableHttpCaching; private ICredentials credentials; public LocalXhtmlXmlResolver(bool enableHttpCaching) { this.enableHttpCaching = enableHttpCaching; } public override Uri ResolveUri(Uri baseUri, string relativeUri) { Debug.WriteLineIf(!KnownUris.ContainsKey(relativeUri), "Could not find: " + relativeUri); return KnownUris.ContainsKey(relativeUri) ? KnownUris[relativeUri] : base.ResolveUri(baseUri, relativeUri); } public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn) { if (absoluteUri == null) { throw new ArgumentNullException("absoluteUri"); } //resolve resources from cache (if possible) if (absoluteUri.Scheme == "http" && this.enableHttpCaching && (ofObjectToReturn == null || ofObjectToReturn == typeof(Stream))) { var request = WebRequest.Create(absoluteUri); request.CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.Default); if (this.credentials != null) { request.Credentials = this.credentials; } var response = request.GetResponse(); return response.GetResponseStream(); } //otherwise use the default behavior of the XmlUrlResolver class (resolve resources from source) return base.GetEntity(absoluteUri, role, ofObjectToReturn); } } 

Tuve el mismo problema que Dave y encontré esta pregunta que me ayudó mucho. Basado en la respuesta de Dave y la sugerencia de Pavel para la optimización, actualicé la clase. Ahora las DTD pueden almacenarse como recursos integrados y cargarse si es necesario. Sé que esta publicación tiene algunos años, pero quizás esto pueda ayudar a alguien.

Ejemplo de uso:

 XmlReaderSettings readerSettings = new XmlReaderSettings { DtdProcessing = DtdProcessing.Parse, XmlResolver = new LocalXhtmlXmlResolver() }; using (XmlReader reader = XmlReader.Create(xhtmlStream, readerSettings)) { XDocument xhtml = XDocument.Load(reader); ... } 

Clase LocalXhtmlXmlResolver:

 public class LocalXhtmlXmlResolver : XmlUrlResolver { private const string ResourcePrefix = "Your.Namespace.Here."; private static readonly Dictionary _knownDtds = new Dictionary { { "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd", ResourcePrefix + "xhtml1-strict.dtd" }, { "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd", ResourcePrefix + "xhtml1-transitional.dtd" }, { "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd", ResourcePrefix + "xhtml1-frameset.dtd" }, { "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd", ResourcePrefix + "xhtml11.dtd" }, { "http://www.w3.org/TR/xhtml1/DTD/-//W3C//ENTITIES Latin 1 for XHTML//EN", ResourcePrefix + "xhtml-lat1.ent" }, { "http://www.w3.org/TR/xhtml1/DTD/-//W3C//ENTITIES Special for XHTML//EN", ResourcePrefix + "xhtml-special.ent" }, { "http://www.w3.org/TR/xhtml1/DTD/-//W3C//ENTITIES Symbols for XHTML//EN", ResourcePrefix + "xhtml-symbol.ent" } }; private static readonly Dictionary _knownUris = new Dictionary { { "-//W3C//DTD XHTML 1.0 Strict//EN", new Uri("http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd") }, { "-//W3C XHTML 1.0 Transitional//EN", new Uri("http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd") }, { "-//W3C//DTD XHTML 1.0 Transitional//EN", new Uri("http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd") }, { "-//W3C XHTML 1.0 Frameset//EN", new Uri("http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd") }, { "-//W3C//DTD XHTML 1.1//EN", new Uri("http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd") } }; public override Uri ResolveUri(Uri baseUri, string relativeUri) { return _knownUris.ContainsKey(relativeUri) ? _knownUris[relativeUri] : base.ResolveUri(baseUri, relativeUri); } public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn) { if (absoluteUri == null) { throw new ArgumentNullException("absoluteUri"); } if (_knownDtds.ContainsKey(absoluteUri.OriginalString)) { string resourceName = _knownDtds[absoluteUri.OriginalString]; Assembly assembly = Assembly.GetAssembly(typeof(LocalXhtmlXmlResolver)); return assembly.GetManifestResourceStream(resourceName); } return base.GetEntity(absoluteUri, role, ofObjectToReturn); } }