我需要加载一些在顶部有这个的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。
感谢。
答案 0 :(得分:4)
我认为您应该能够使用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");
答案 1 :(得分:1)
对于.NET Framework 3.5及更低版本,可能可以使用XmlUrlResolver
,如this answer所示。但是,这种方法在运行时从W3C网站下载DTD,这不是一个好主意,尤其是因为W3C似乎正在阻止此类请求。 other answer建议将DTD缓存为程序集中的嵌入资源,类似于HTML2XHTML。
对于使用.NET Framework 4.0及更高版本的其他读者,您可以使用XmlPreloadedResolver
,如支持XHTML 1.0的建议by Daniel Renshaw。为了支持XHTML 1.1,您可以使用DT3的展平版本(可在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);