2010-09-17 19 views
6

Es necesario cargar varios archivos XHTML que tienen esta en la parte superior:Cómo acelerar DTD carga a través DOCTYPE

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> 

Cada archivo se carga en un System.Xml.XmlDocument separada. Debido a la declaración DOCTYPE tardan mucho tiempo en cargarse. Intenté configurar XmlResolver = null, pero luego recibí XmlException lanzado porque tengo entidades no válidas (por ejemplo, ”). Así que pensé que podría descargar el DTD solo para el primer XmlDocument y de alguna manera reutilizarlo para los siguientes XmlDocuments (y así evitar el impacto en el rendimiento), pero no tengo idea de cómo hacerlo.

Estoy usando .Net 3.5.

Gracias.

Respuesta

4

Creo que debería poder resolver este problema de resolución usando XmlPreloadedResolver. Sin embargo, tengo algunas dificultades para hacerlo funcionar yo mismo. Parece que XHTML 1.0 sería más fácil de admitir ya que es un DTD "conocido": XmlKnownDtds mientras que XHTML 1.1 no es actualmente "conocido", lo que significa que tendrás que volver a cargar un montón de URI.

Por ejemplo:

XmlPreloadedResolver xmlPreloadedResolver = new XmlPreloadedResolver(XmlKnownDtds.Xhtml10); 
xmlPreloadedResolver.Add(new Uri("http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"), File.ReadAllBytes("D:\\xhtml11.dtd")); 
xmlPreloadedResolver.Add(new Uri("http://www.w3.org/TR/xhtml-modularization/DTD/xhtml-inlstyle-1.mod"), File.ReadAllBytes("D:\\xhtml-inlstyle-1.mod")); 
xmlPreloadedResolver.Add(new Uri("http://www.w3.org/TR/xhtml-modularization/DTD/xhtml-framework-1.mod"), File.ReadAllBytes("D:\\xhtml-framework-1.mod")); 
xmlPreloadedResolver.Add(new Uri("http://www.w3.org/TR/xhtml-modularization/DTD/xhtml-text-1.mod"), File.ReadAllBytes("D:\\xhtml-text-1.mod")); 
xmlPreloadedResolver.Add(new Uri("http://www.w3.org/TR/xhtml-modularization/DTD/xhtml-hypertext-1.mod"), File.ReadAllBytes("D:\\xhtml-hypertext-1.mod")); 
xmlPreloadedResolver.Add(new Uri("http://www.w3.org/TR/xhtml-modularization/DTD/xhtml-list-1.mod"), File.ReadAllBytes("D:\\xhtml-list-1.mod")); 
xmlPreloadedResolver.Add(new Uri("http://www.w3.org/TR/xhtml-modularization/DTD/xhtml-edit-1.mod"), File.ReadAllBytes("D:\\xhtml-edit-1.mod")); 
xmlPreloadedResolver.Add(new Uri("http://www.w3.org/TR/xhtml-modularization/DTD/xhtml-bdo-1.mod"), File.ReadAllBytes("D:\\xhtml-bdo-1.mod")); 
xmlPreloadedResolver.Add(new Uri("http://www.w3.org/TR/ruby/xhtml-ruby-1.mod"), File.ReadAllBytes("D:\\xhtml-ruby-1.mod")); 
xmlPreloadedResolver.Add(new Uri("http://www.w3.org/TR/xhtml-modularization/DTD/xhtml-pres-1.mod"), File.ReadAllBytes("D:\\xhtml-pres-1.mod")); 
// TODO: Add other modules here (see the xhtml11.dtd for the full list) 
XmlDocument xmlDocument = new XmlDocument(); 
xmlDocument.XmlResolver = xmlPreloadedResolver; 
xmlDocument.Load("D:\\doc1.xml"); 
+0

Gracias, pero es XmlPreloadedResolver .Net 4 solamente :-(Estoy en 3.5. – Polyfun

+1

Podrías crear tu propia derivación de 'XmlResolver' que hace básicamente lo mismo. –

+0

gracias esto es lo que he hecho, usando el ejemplo aquí http://www.codeproject.com/KB/XML/HTML2XHTML.aspx? pantalla = Imprimir. – Polyfun

1

Para .NET Framework 3.5 y por debajo, que podría haber sido posible utilizar el XmlUrlResolver, como se muestra en this answer. Sin embargo, este enfoque descarga las DTD del sitio web del W3C en tiempo de ejecución, lo que no es una buena idea, sobre todo porque el W3C parece estar bloqueando actualmente dichas solicitudes. El other answer sugiere almacenar en caché los DTD como recursos incrustados en el ensamblado, similar a su HTML2XHTML.

Para otros lectores que usan .NET Framework 4.0 y superior, puede usar XmlPreloadedResolver, como se sugiere by Daniel Renshaw, que es compatible con XHTML 1.0. Para admitir XHTML 1.1, puede simplificar su implementación utilizando la versión plana de la DTD, disponible en el xhtml11-flat.dtd en el sitio web de W3C. Defino un método de extensión para este propósito:

public static class XmlPreloadedResolverExtensions 
{ 
    private const string Xhtml11DtdPublicId = "-//W3C//DTD XHTML 1.1//EN"; 
    private const string Xhtml11DtdSystemId = "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"; 

    public static void AddXhtml11(this XmlPreloadedResolver resolver, bool @override = false) 
    { 
     Add(resolver, new Uri(Xhtml11DtdPublicId, UriKind.RelativeOrAbsolute), ManifestResources.xhtml11_flat_dtd, @override); 
     Add(resolver, new Uri(Xhtml11DtdSystemId, UriKind.RelativeOrAbsolute), ManifestResources.xhtml11_flat_dtd, @override); 
    } 

    public static bool Add(this XmlPreloadedResolver resolver, Uri uri, Stream value, bool @override) 
    { 
     if (@override || !resolver.PreloadedUris.Contains(uri)) 
     { 
      resolver.Add(uri, value); 
      return true; 
     } 

     return false; 
    } 
} 

Esto podría ser utilizado como ordinarios XmlResolver casos:

var xmlResolver = new XmlPreloadedResolver(); 
xmlResolver.AddXhtml11(); 

XmlReaderSettings settings = new XmlReaderSettings(); 
settings.DtdProcessing = DtdProcessing.Parse; 
settings.XmlResolver = xmlResolver; 

XDocument document; 
using (var xmlReader = XmlReader.Create(input, settings)) 
    document = XDocument.Load(xmlReader); 
Cuestiones relacionadas