Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 打开外部DTD(w3.org,xhtml1 transitional.DTD)时出错。503服务器不可用_.net_Xml_Xhtml_W3c_Dtd - Fatal编程技术网

.net 打开外部DTD(w3.org,xhtml1 transitional.DTD)时出错。503服务器不可用

.net 打开外部DTD(w3.org,xhtml1 transitional.DTD)时出错。503服务器不可用,.net,xml,xhtml,w3c,dtd,.net,Xml,Xhtml,W3c,Dtd,我正在尝试对xhtml文档执行xpath查询。使用.NET3.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">

我正在尝试对xhtml文档执行xpath查询。使用.NET3.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>
var s = File.OpenRead(fileToRead)
var reader = XmlReader.Create(s, new XmlReaderSettings{ ProhibitDtd=false });
// 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())
    {
     ...
    }
但当我运行它时,它会返回

打开外部DTD“”时出错:远程服务器返回错误:(503)服务器不可用

现在,我知道为什么会出现503错误了

我见过“变通方法”,人们只是禁用DTD。这就是
prohibidtd=true
所能做的,它消除了503错误

但在我的例子中,这会导致其他问题——应用程序没有实体定义,因此不是格式良好的XML。如何在不访问w3.org网站的情况下使用DTD进行验证并获取实体定义


我认为.NET4.0有一个漂亮的内置功能来处理这种情况:。但是我需要一个.NET3.5的解决方案


相关:

-答案是,我必须提供我自己的。我不认为这是.NET3.5内置的。这真令人费解。同样令人困惑的是,我花了这么长时间才偶然发现这个问题。同样令人困惑的是,我找不到其他人已经解决了这个问题

好吧,那么。。XmlResolver。我创建了一个新类,该类派生自XmlResolver,并超越了三个关键因素:凭证(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

我想做的是只解析XHTML1.0中DTD的URI。因此,我编写了ResolveUri和GetEntity来查找那些特定的DTD,并只对它们做出肯定的响应

对于带有DTD语句的XHTML文档,流程如下:

  • XmlReader使用XHTML DTD的公共URI调用ResolveUri,它是
    “-//W3C//DTD XHTML 1.0//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等,也会发生同样的情况。为了使解析器工作,所有这些东西都需要嵌入

    是的,如果解析程序无法解析URI,它将抛出异常。据我所知,这还没有正式的记录。这似乎有点令人惊讶。(严重违反法律)。相反,如果ResolveUri返回null,XmlReader将调用null URI上的GetEntity,这。。。。啊,没有希望了


    这对我有用。它应该适用于从.NET在XHTML上进行XML处理的任何人。如果您想在自己的应用程序中使用它。zip包含完整的源代码。根据

    您可以将其插入到您的XML应用程序中,这些应用程序可以处理XHTML。像这样使用它:

    <!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>
    
    var s = File.OpenRead(fileToRead)
    var reader = XmlReader.Create(s, new XmlReaderSettings{ ProhibitDtd=false });
    
    // 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())
        {
         ...
        }
    

    通过将XmlReaderSettings.XmlResolver属性设置为null,可以禁止XmlReader打开任何外部资源

    System.Xml.XmlReaderSettings xmlReaderSettings = new System.Xml.XmlReaderSettings ();
    xmlReaderSettings.XmlResolver = null;
    System.Xml.XmlReader xmlReader = System.Xml.XmlReader.Create(myUrl, xmlReaderSettings);
    

    当您的
    ResolveUri
    方法获得对类似
    -//W3C//ELEMENTS XHTML Images 1.0//EN
    的URI的“公共”形式的请求时,您的方法是否会抛出并等待以
    http://
    开头的后续类似web的URI

    我没有抛出,而是将公共URI解析为相应的
    http://
    URI(然后在
    GetEntity
    方法中拦截对
    http://
    URI的请求)

    因此,我从来不需要扔东西,我认为这是正确的解决办法



    这是一个聪明的方法。你的字典有多大?我向您指出的库只处理XHTML1.0,并且只需要映射一个公共URI库

    我使用的是“模块化”的XHTML1.1,所以我必须映射大约40个文件

    请注意,框架的行为可能已经改变!我有一个库(包括我的XHTMLResolver类),它是用.NET Framework 2构建的,但是调用它的方式不同,这取决于应用程序(使用库的)是为.NET 2还是.NET 4构建的

    对于.NET 2,当我的ResolveUri方法始终仅透明地委托给XmlUrlResolver时,它将:

  • 要求解决DTD的公共问题
  • 尝试从磁盘获取实体DTD(抛出一个DirectoryNotFoundException)
  • 尝试从http获取实体DTD(我将从本地资源提供)
  • 尝试从http中每隔一个文件获取一个实体(我将从本地资源提供此服务)
  • 对于.NET 4,每个资源都有一个额外的调用:

    • 请求解析子资源(例如,
      *.mod
      文件)的公共URI,我的实现刚刚委托给XMLURLSolver
    • 要求获取子资源的“已解析”公共实体,该子资源是