c# - 如何通过代理使用 .dtd 而不是使用 system.net.defaultproxy 来验证 xml

标签 c# xml proxy dtd

其他人已经问过类似的问题:Validate an Xml file against a DTD with a proxy. C# 2.0

这是我的问题:我们有一个网站应用程序需要使用内部和外部资源。

  1. 我们有一堆内部 网页服务。对 CANNOT 的请求 通过代理。如果我们尝试这样做,我们会收到 404 错误,因为代理 DNS 不知道我们的内部网络服务域。
  2. 我们生成一个 几个必须有效的 xml 文件。 我想使用提供的 dtd 用于验证 xml 的文档。这 dtd url 在我们的网络之外,并且 必须通过代理。

有没有办法在不使用 system.net.defaultproxy 的情况下通过代理通过 dtd 进行验证?如果我们使用 defaultproxy,内部 web 服务会被破坏,但 dtd 验证有效。#

这是我现在正在做的验证 xml 的操作:

public static XDocument ValidateXmlUsingDtd(string xml)
{
    var xrSettings = new XmlReaderSettings {
        ValidationType = ValidationType.DTD,
        ProhibitDtd = false
    };

    var sr = new StringReader(xml.Trim());

    XmlReader xRead = XmlReader.Create(sr, xrSettings);
    return XDocument.Load(xRead);
}

理想情况下,可以通过某种方式将代理分配给 XmlReader,就像您可以将代理分配给 HttpWebRequest 对象一样。或者也许有一种方法可以以编程方式打开或关闭 defaultproxy?这样我就可以在调用 Load the Xdocument 时打开它,然后再次关闭它?

仅供引用 - 我对如何解决这个问题持开放态度 - 请注意代理位于另一个域中,他们不想为我们的内部网络服务地址设置到我们的 dns 服务器的 dns 查找.

干杯, 兰斯

最佳答案

是的,你可以解决这个问题。

一种选择是创建您自己的解析器来处理 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 ,我 build 了a custom resolver myself, for XHTML ,也许您可​​以重复使用它。

另请参阅,a related link .


为了便于说明,这里是自定义 Uri 解析器中 ResolveUri 的代码。

/// <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 .

如果您的解析器执行网络通信,那么对于一般解决方案,您可能需要覆盖 Credentials 属性。

public override System.Net.ICredentials Credentials
{
    set { ... }
}

另外,您可能想要公开一个 Proxy 属性。或不。正如我上面所说,您可能希望根据 DTD URI 自动确定要使用的代理。

关于c# - 如何通过代理使用 .dtd 而不是使用 system.net.defaultproxy 来验证 xml,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2766357/

相关文章:

c# - 以编程方式清除 asp.net core 中的缓存配置文件

c# - 控制任务的实际并发性

c# - 什么时候使用方法而不是属性来定义类?

.net - web.config 的 appsettings 内的标签值。如何?

html - Perl 在 HTML/XML 标签内的单词周围添加 <an></a>

ruby-on-rails - websense 和防火墙后面的 Windows 7 中的 Ruby on Rails 问题

proxy - cntlm 服务未运行

c# - 测量以指定宽度包裹的文本高度

java - Android:使用 getResources 可能会导致我的应用程序崩溃

browser - 在浏览器上设置 SOCKS5 代理以便在其他应用程序上使用