.net – 打开extern DTD(w3.org,xhtml1-transitional.dtd)时发生错误. 503服务器不可用

我正在尝试通过xhtml文档执行xpath查询.使用.NET 3.5.

该文档如下所示:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
  <head>
   ....
  </head>
  <body>
    ...
  </body>
</html>

因为文档包含各种char实体(& nbsp;等等),所以我需要使用DTD,以便加载一个XmlReader.所以我的代码如下所示:

var s = File.OpenRead(filetoRead)
var reader = XmlReader.Create(s,new XmlReaderSettings{ ProhibitDtd=false });

但是当我运行它时,它返回

An error has occurred while opening external DTD ‘07001’: The Remote Server returned an error: (503) Server Unavailable.

现在,我知道为什么我得到503错误. W3C explained it very clearly.

我看到“解决方法”,人们只是禁用DTD.这是ProhibitDtd = true可以做的,它消除了503错误.

但是在我的情况下,导致其他问题 – 应用程序没有获得实体定义,因此XML格式格式不正确.如何使用DTD进行验证,并获取实体定义,而不必打到w3.org网站?

我认为.NET 4.0有一个漂亮的内置功能来处理这种情况:XmlPreloadedResolver.但是我需要一个.NET 3.5的解决方案.

有关:
java.io.IOException: Server returned HTTP response code: 503

解决方法

答案是,我必须提供自己的 XmlResolver.我不认为这是内置的.NET 3.5.这真让人困惑这也让我感到困惑,这使我长久以来绊倒了这个问题.这也是令人困惑的,我找不到已经解决了这个问题的其他人?

好的,所以.. XmlResolver.我创建了一个新类,派生自XmlResolver,并且覆盖了三个关键的事情:Credentials(set),ResolveUri和GetEntity.

public sealed class XhtmlResolver : XmlResolver
{
    public override System.Net.ICredentials Credentials
    {
        set { throw new NotSupportedException();}
    }

    public override object GetEntity(Uri absoluteUri,string role,Type t)
    {
       ...
    }

    public override Uri ResolveUri(Uri baseUri,string relativeUri)
    {
      ...
    }
}

关于这个东西的文件很简单,所以我会告诉你我学到了什么.这个类的操作是这样的:XmlReader首先调用ResolveUri,然后给定一个解决的Uri,然后调用GetEntity.该方法预期返回类型t的对象(作为参数传递).我只看过它请求一个System.IO.Stream.

我的想法是使用csc.exe / resource选项将DTD的本地副本及其XHTML1.0的依赖项嵌入到程序集中,然后检索该资源的流.

private System.IO.Stream GetStreamForNamedResource(string resourceName)
{
    Assembly a = Assembly.GetExecutingAssembly();
    return  a.GetManifestResourceStream(resourceName);
}

很简单这从GetEntity()调用.

但我可以改善这一点.我们首先将它们以简明的方式嵌入DTD中,然后修改上述方法,如下所示:

private System.IO.Stream GetStreamForNamedResource(string resourceName)
{
    Assembly a = Assembly.GetExecutingAssembly();
    return  new System.IO.Compression.GZipStream(a.GetManifestResourceStream(resourceName),System.IO.Compression.CompressionMode.Decompress);
}

代码打开嵌入式资源的流,并返回配置为解压缩的GZipStream.读者得到明文DTD.

我想做的只是解决Xhtml 1.0中DTD的URI.所以我写了ResolveUri和GetEntity来寻找这些特定的DTD,并且只对他们作出肯定的回应.

对于具有DTD语句的XHTML文档,流程是这样的;

> XmlReader调用ResolveUri与XHTML DTD的公共URI,它是“ – // W3C // DTD XHTML 1.0 Transitional // EN”.如果XmlResolver可以解析,它应该返回一个有效的URI.如果不能解决,应该抛出.我的实现只是抛出公共URI.
> XmlReader然后使用DTD的系统标识符调用ResolveUri,在这种情况下,它是“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”.在这种情况下,XhtmlResolver返回一个有效的Uri.
> XmlReader然后使用该URI调用GetEntity. XhtmlResolver抓住嵌入的资源流并返回.

对于依赖项 – xhtml_lat1.ent等也是一样的事情.为了使解析器工作,所有这些事情都需要嵌入.

是的,如果Resolver无法解析URI,那么预计会抛出异常.据我所知,这并没有正式记录.这似乎有点令人惊讶(严重违反the principle of least astonishment).如果相反,ResolveUri返回null,XmlReader将调用GetAntity的空URI,哪个….啊,是绝望的.

这对我有用它应该适用于从.NET处理XHTML的任何人.如果你想在你自己的应用程序中使用这个,grab the DLL.该zip包含完整的源代码.根据MS Public License许可.

您可以将其插入到XHTML中的XML应用程序中.使用它像这样:

// for an XmlDocument...
System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
doc.XmlResolver = new Ionic.Xml.XhtmlResolver();
doc.Load(xhtmlFile);

// for an XmlReader...
var xmlReaderSettings = new XmlReaderSettings
    {
        ProhibitDtd = false,XmlResolver = new XhtmlResolver()
    };
using (var stream = File.OpenRead(filetoRead))
{
    XmlReader reader = XmlReader.Create(stream,xmlReaderSettings);
    while (reader.Read())
    {
     ...
    }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Mip是什么意思以及作用有哪些
怎么测试Mip页面运行情况
MIP安装的具体步骤有哪些
HTML添加超链接、锚点的方法及作用详解(附视频)
MIP的规则有哪些
Mip轮播图组件中的重要属性讲解
Mip的内联框架组件是什么
怎么创建初始的MIP配置及模板文件
HTML实现多选框及无法提交多数据的原因分析(附视频)
HTML如何设置复选框、单选框以及默认选项?(图文+视频)
怎么使用MIP组件
Div垂直居中效果怎么实现
HTML如何实现视频在线播放
如何使用Mip代码校验工具
Mip中弹出层组件是什么
如何用HTML实现简单按钮样式
Mip中快速回顶组件怎么用
Div内容居中效果如何实现
Div水平居中效果怎么实现
Mip中列表组件怎么用