簡體   English   中英

如何加快通過DOCTYPE加載DTD

[英]How to speed up loading DTD through DOCTYPE

我需要加載一些在頂部有這個的xhtml文件:

<?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">

每個文件都將加載到單獨的System.Xml.XmlDocument中。 由於DOCTYPE聲明,它們需要很長時間才能加載。 我嘗試設置XmlResolver = null,但后來我拋出了XmlException,因為我有無效的實體(例如,“)。 所以我認為我可以為第一個XmlDocument下載DTD,並以某種方式將其重用於后續的XmlDocuments(從而避免性能損失),但我不知道如何做到這一點。

我正在使用.Net 3.5。

謝謝。

我認為你應該能夠使用XmlPreloadedResolver來解決這個解析器問題。 但是,我在使自己工作時遇到了一些困難。 看起來XHTML 1.0更容易支持,因為它是一個“已知的”DTD: XmlKnownDtds而XHTML 1.1當前不是“已知”,這意味着你將不得不重新加載一堆URI。

例如:

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");

對於.NET Framework 3.5及更低版本,可能可以使用XmlUrlResolver ,如本答案所示。 但是,這種方法在運行時從W3C網站下載DTD,這不是一個好主意,尤其是因為W3C似乎正在阻止此類請求。 另一個答案建議將DTD緩存為程序集中的嵌入資源,類似於HTML2XHTML

對於使用.NET Framework 4.0及更高版本的其他讀者,您可以使用XmlPreloadedResolver ,如Daniel Renshaw所建議 ,它支持XHTML 1.0。 為了支持XHTML 1.1,您可以使用DTD的展平版本來簡化您的實現,該版本可以在W3C網站的xhtml11-flat.dtd上找到。 我為此目的定義了一個擴展方法:

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

然后可以像普通的XmlResolver實例一樣使用它:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM