2010-09-17 2 views
6

J'ai besoin de charger un certain nombre de fichiers xhtml qui ont ce au sommet:Comment accélérer DTD de chargement par 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"> 

Chaque fichier sera chargé dans un System.Xml.XmlDocument séparé. En raison de la déclaration DOCTYPE, ils prennent beaucoup de temps à charger. J'ai essayé de définir XmlResolver = null, mais ensuite je reçois XmlException levé parce que j'ai des entités invalides (par exemple, ”). J'ai donc pensé pouvoir télécharger la DTD juste pour le premier XmlDocument et en quelque sorte la réutiliser pour les XmlDocuments suivants (et donc éviter les hits de performance), mais je n'ai aucune idée de comment faire cela. J'utilise .Net 3.5.

Merci.

Répondre

4

Je pense que vous devriez être capable de résoudre ce problème de résolution en utilisant XmlPreloadedResolver. Cependant, j'ai de la difficulté à le faire fonctionner moi-même. Il semble que XHTML 1.0 soit plus facile à supporter puisqu'il s'agit d'une DTD "connue": XmlKnownDtds tandis que XHTML 1.1 n'est pas "connu" actuellement, ce qui signifie que vous devrez recharger un tas d'URI.

Par exemple:

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

Merci, mais XmlPreloadedResolver est .Net 4 seulement :-(Je suis sur 3,5. – Polyfun

+1

Vous pouvez créer votre propre dérivation de 'XmlResolver' qui fait fondamentalement la même chose: –

+0

merci c'est ce que j'ai fait, en utilisant l'exemple ici http://www.codeproject.com/KB/XML/HTML2XHTML.aspx? display = Imprimer. – Polyfun

1

Pour .NET Framework 3.5 et au-dessous, il aurait été possible d'utiliser le XmlUrlResolver, comme le montre this answer. Cependant, cette approche télécharge les DTD du site Web du W3C au moment de l'exécution, ce qui n'est pas une bonne idée, d'autant plus que le W3C semble bloquer actuellement de telles demandes. Le other answer suggère de mettre en cache les DTD en tant que ressources incorporées dans l'assembly, similaire à votre HTML2XHTML.

Pour les autres lecteurs utilisant .NET Framework 4.0 et supérieur, vous pouvez utiliser XmlPreloadedResolver, comme suggéré by Daniel Renshaw, qui prend en charge XHTML 1.0. Pour prendre en charge XHTML 1.1, vous pouvez simplifier votre implémentation en utilisant la version aplatie de la DTD, disponible au xhtml11-flat.dtd sur le site Web du W3C. Je définir une méthode d'extension à cet effet:

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

Cela pourrait alors être utilisé comme cas XmlResolver ordinaires:

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); 
Questions connexes