如何使用 DOM 解析器解析 xhtml 忽略 DOCTYPE 声明

Posted

技术标签:

【中文标题】如何使用 DOM 解析器解析 xhtml 忽略 DOCTYPE 声明【英文标题】:How to parse a xhtml ignoring the DOCTYPE declaration using DOM parser 【发布时间】:2011-02-08 02:36:55 【问题描述】:

我在使用 DOM 解析器解析带有 DOCTYPE 声明的 xhtml 时遇到问题。

错误: java.io.IOException:服务器返回 HTTP 响应代码:503 用于 URL: http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd%20

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

有没有办法将 xhtml 解析为 Document 对象而忽略 DOCTYPE 声明。

【问题讨论】:

【参考方案1】:

下面的代码 sn-p 指示解析器真正忽略 DOCTYPE 声明中的外部 DTD,而不是假解析器:

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;

(...)

DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
f.setValidating(false);
f.setAttribute("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
DocumentBuilder builder = f.newDocumentBuilder();
Document document = builder.parse( ... )

【讨论】:

【参考方案2】:

一个对我有用的解决方案是给 DocumentBuilder 一个返回空流的假解析器。这里有一个很好的解释(查看 kdgregory 的最后一条消息)

http://forums.sun.com/thread.jspa?threadID=5362097

这是 kdgregory 的解决方案:

documentBuilder.setEntityResolver(new EntityResolver()
        
            public InputSource resolveEntity(String publicId, String systemId)
                throws SAXException, IOException
            
                return new InputSource(new StringReader(""));
            
        );

【讨论】:

【参考方案3】:

最简单的做法是在 DocumentBuilderFactory 中设置 validating=false。如果要进行验证,请下载 DTD 并使用本地副本。正如上面 Rachel 所评论的,这在The WWW Consortium.

上进行了讨论

简而言之,因为默认的 DocumentBuilderFactory 每次验证时都会下载 DTD,所以每次典型程序员尝试解析 Java 中的 XHTML 文件时,W3 都会受到打击。他们负担不起这么多的流量,所以他们以错误响应。

【讨论】:

【参考方案4】:

解析器对于下载 DTD 是必需的,但您可以通过在 <?xml... ?> 行上设置独立属性来绕过它。

但是请注意,此特定错误很可能是由 XML Schema 定义和 DTD URL 之间的混淆触发的。有关详细信息,请参阅http://www.w3schools.com/xhtml/xhtml_dtd.asp。正确的是:

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

【讨论】:

我使用了相同的 DOCTYPE。将独立属性设置为“是”时,它仍然会给出相同的错误。下面是我在我的 xhtml 上添加的: ttp://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" rel="nofollow" target="_blank">w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd "> 我仍然遇到同样的错误。 java.io.IOException:服务器返回 HTTP 响应代码:503 用于 URL:w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd%20 .dtd" 之间有一个空格 这似乎是博客中讨论的常见问题,w3.org/2005/06/blog/systeam/2008/02/08/…

以上是关于如何使用 DOM 解析器解析 xhtml 忽略 DOCTYPE 声明的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 dom php 解析器

用于 XML 编辑、更新的 DOM 解析器

在使用简单的HTML Dom解析器进行解析之前,我如何登录Web表单网站?

Java XML 解析:避免实体引用解析

如何在python中忽略BeautifulSoup解析器中的换行符

如何在 android 中使用 DOM 或 SAX 解析器从 XML 读取子节点