2010-09-17 18 views
6

ho bisogno di caricare un certo numero di file XHTML che hanno questo in alto:Come aumentare la velocità di caricamento del DTD attraverso 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"> 

Ogni file verrà caricato in uno System.Xml.XmlDocument separata. A causa della dichiarazione DOCTYPE, impiegano molto tempo per caricarsi. Ho provato a impostare XmlResolver = null, ma poi ho generato XmlException perché non ho entità non valide (ad es., ”). Così ho pensato di poter scaricare il DTD solo per il primo XmlDocument e in qualche modo riutilizzarlo per i successivi XmlDocuments (e quindi evitare il colpo di performance), ma non ho idea di come farlo.

Sto usando .Net 3.5.

Grazie.

risposta

4

Penso che dovresti essere in grado di risolvere questo problema del resolver usando XmlPreloadedResolver. Tuttavia, sto avendo qualche difficoltà a farlo funzionare da solo. Sembra che XHTML 1.0 sia più facile da supportare in quanto è una DTD "nota": XmlKnownDtds mentre XHTML 1.1 non è attualmente "noto", il che significa che dovrai ricaricare un sacco di URI.

Ad esempio:

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

Grazie, ma XmlPreloadedResolver è .Net 4 solo :-(Sono su 3,5. – Polyfun

+1

Si potrebbe creare la propria derivazione di 'XmlResolver' che fondamentalmente fa la stessa cosa –

+0

grazie a ciò che ho fatto, usando l'esempio qui http://www.codeproject.com/KB/XML/HTML2XHTML.aspx? Display = Stampa. – Polyfun

1

NET Framework 3.5 e sotto, sarebbe stato possibile utilizzare il XmlUrlResolver, come mostrato in this answer. Tuttavia, questo approccio scarica i DTD dal sito Web W3C in fase di runtime, il che non è una buona idea, non ultimo perché W3C sembra attualmente bloccando tali richieste. Il other answer suggerisce di memorizzare nella cache i DTD come risorse incorporate nell'assieme, in modo simile al proprio HTML2XHTML.

Per altri lettori che utilizzano .NET Framework 4.0 e versioni successive, è possibile utilizzare XmlPreloadedResolver, come suggerito by Daniel Renshaw, che supporta XHTML 1.0. Per supportare XHTML 1.1, è possibile semplificare l'implementazione utilizzando la versione appiattita della DTD, disponibile su xhtml11-flat.dtd sul sito Web W3C. Mi definisco un metodo di estensione per questo scopo:

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; 
    } 
} 

Questo potrebbe quindi essere utilizzato come normali XmlResolver casi:

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); 
Problemi correlati