是的,你可以解決這個問題。
一種選擇是創建處理DTD分辨率的自己的解析器。它可以使用任何它喜歡的機制,包括爲出站通信使用非默認代理。
var xmlReaderSettings = new XmlReaderSettings
{
ProhibitDtd = false,
ValidationType = ValidationType.DTD,
XmlResolver = new MyCustomDtdResolver()
};
在爲MyCustomDtdResolver的代碼,你會指定所需的代理設置。它可能因DTD而異。
您沒有指定,但是如果您正在解決的DTD是固定且不變的,那麼Silverlight和.NET 4.0具有內置的解析器,它不會觸及網絡(無代理,無任何http通信) 。它被稱爲XmlPreloadedResolver。它知道如何解析RSS091和XHTML1.0。如果您有其他DTD(包括您自己的自定義DTD),並且它們是固定的或不變的,則可以將它們加載到此解析器中並在運行時使用它,並完全避免HTTP通信和代理複雜化。
More on that.
如果你沒有使用.NET 4.0,那麼你可以建立一個「無網絡」解析器自己。爲了避免W3C traffic limit,我建了a custom resolver myself, for XHTML,也許你可以重新使用它。另外,a related link。
例如,以下是ResolveUri在自定義Uri解析器中的代碼。
/// <summary>
/// Resolves URIs.
/// </summary>
/// <remarks>
/// <para>
/// The only Uri's supported are those for W3C XHTML 1.0.
/// </para>
/// </remarks>
public override Uri ResolveUri(Uri baseUri, string relativeUri)
{
if (baseUri == null)
{
if (relativeUri.StartsWith("http://"))
{
Trace(" returning {0}", relativeUri);
return new Uri(relativeUri);
}
// throw if Uri scheme is unknown/unhandled
throw new ArgumentException();
}
if (relativeUri == null)
return baseUri;
// both are non-null
var uri = baseUri.AbsoluteUri;
foreach (var key in knownDtds.Keys)
{
// look up the URI in the table of known URIs
var dtdUriRoot = knownDtds[key];
if (uri.StartsWith(dtdUriRoot))
{
string newUri = uri.Substring(0,dtdUriRoot.Length) + relativeUri;
return new Uri(newUri);
}
}
// must throw if Uri is unknown/unhandled
throw new ArgumentException();
}
這裏是爲GetEntity
/// <summary>
/// Gets the entity associated to the given Uri, role, and
/// Type.
/// </summary>
/// <remarks>
/// <para>
/// The only Type that is supported is the System.IO.Stream.
/// </para>
/// <para>
/// The only Uri's supported are those for W3C XHTML 1.0.
/// </para>
/// </remarks>
public override object GetEntity(Uri absoluteUri, string role, Type t)
{
// only handle streams
if (t != typeof(System.IO.Stream))
throw new ArgumentException();
if (absoluteUri == null)
throw new ArgumentException();
var uri = absoluteUri.AbsoluteUri;
foreach (var key in knownDtds.Keys)
{
if (uri.StartsWith(knownDtds[key]))
{
// Return the stream containing the requested DTD.
// This can be a FileStream, HttpResponseStream, MemoryStream,
// or whatever other stream you like. I used a Resource stream
// myself. If you retrieve the DTDs via HTTP, you could use your
// own IWebProxy here.
var resourceName = GetResourceName(key, uri.Substring(knownDtds[key].Length));
return GetStreamForNamedResource(resourceName);
}
}
throw new ArgumentException();
}
完整的工作代碼的代碼爲我的自定義解析is available。
如果您的解析程序執行網絡通信,那麼對於一般的解決方案,您可能需要重寫憑證屬性。
public override System.Net.ICredentials Credentials
{
set { ... }
}
另外,您可能希望公開Proxy屬性。或不。正如我上面所說的,您可能想要從DTD URI自動確定要使用的代理。
感謝Cheeso的回覆。 你能爲MyCustomDtdResolver顯示一些代碼嗎?就像你在http://stackoverflow.com/questions/2558021/an-error-has-occurred-opening-extern-dtd-w3-org-xhtml1-transitional-dtd-503/2559056#2559056中說的那樣,文檔非常* *很少。我特別感興趣的是ResolveUri和GetEntity方法應該包含什麼以啓用通過代理獲取dtd。 – Lanceomagnifico 2010-05-05 08:28:51
哦,我沒有忘記提到這個解決方案需要在.NET 3.5 – Lanceomagnifico 2010-05-05 08:31:53
中工作好,我會用一些代碼更新答案。 – Cheeso 2010-05-05 13:05:21