[英]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.