我正在Windows 10上使用Java 11(AdoptOpenJDK 11.0.5 2019-10-15)。我正在解析一些遗留的XHTML 1.1文件,它们通常具有以下形式:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" http://www.w3.org/MarkUp/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>XHTML 1.1 Skeleton</title>
</head>
<body>
</body>
</html>
我正在使用一个简单的非验证解析器:
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
final Document document;
try (InputStream inputStream = new BufferedInputStream(getClass().getResourceAsStream("xhtml-1.1-test.xhtml"))) {
document = documentBuilder.parse(inputStream);
}
由于某些原因,它会在各个地方添加额外的属性,例如
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
和xml:space = "preserve"
。<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" version="-//W3C//DTD XHTML 1.1//EN" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml:lang="en">
<head xmlns="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<title xmlns="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">XHTML 1.1 Skeleton</title>
</head>
<body xmlns="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml:space="preserve"></body>
</html>
我知道DTD可以提供默认的属性值,但我不明白为什么要添加xmlns:xsi属性,因为似乎没有元素或属性在该命名空间中。
此外,xml:space="preserve"似乎完全不正确;只有像
这样的元素应该设置xml:space="preserve",我认为。(更新:HTML5规范指出,默认情况下HTML保留空格,而且在HTML中不能序列化xml:space属性,所以可能这是这里的部分原因。我将改进我的HTML序列化程序,忽略xml:space属性,这将部分缓解这个问题。)
还要注意版本为"-//W3C//DTD XHTML 1.1//EN";这是我不需要也不想要的。
我是否做错了什么?有没有办法配置解析器不包括这些不必要的东西?
有趣的是,这在XHTML 1.0 strict中不是问题。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>XHTML 1.0 Skeleton</title>
</head>
<body>
</body>
</html>
当解析时,会得到预期的结果:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>XHTML 1.0 Skeleton</title>
</head>
<body>
</body>
</html>
但这是一个与“-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN”有关的问题。因此,这似乎只是XHTML 1.1的问题。
更新:我有一些潜在有用的消息:如果我创建一个没有DTD的新文档,并将整个文档树导入到新文档中,所有这些不必要的内容(显然来自DTD中的隐含属性)都会消失,因为目标文档根本没有DTD。(请参见如何强制从Java XML DOM中的DTD中删除具有暗示默认值的属性)。但这非常低效;在解析时完全关闭这个功能会很好。
DefaultEntityResolver
?此外,关于“由于某种原因它添加了额外的属性”,你是否指它被添加到了原始的xml文件中?如果不是,那么你如何将Document
对象转换为XML字符串(或保存到文件中)? - Eng.FouadDefaultEntityResolver
是一个实体解析器,可以本地提供实体(例如 DTD),而不是从互联网下载。如果您想要验证实体内容,请参见票 https://globalmentor.atlassian.net/browse/JAVA-175 或克隆提交 https://bitbucket.org/globalmentor/%7B15a9ee2f-e9fa-4dd1-8185-9ef4e2f6c713%7D/commits/4f74e003fa6c91600ab11fc379ea1712b86ab415。 - Garret WilsonDefaultEntityResolver
,那么它甚至无法解析,并且由于http://www.w3.org/TR/xhtml11/DTD/xhtml-datatypes-1.mod
的java.io.FileNotFoundException
而崩溃。显然,W3C已经从其网站中完全删除了此实体。(那么没有人再使用标准Java XML解析器解析XHTML 1.1文件吗?这是完全错误的。)因此,我必须使用具有本地存储实体的自定义实体解析器,否则它甚至无法解析。@Olivier你自己试过吗? - Garret Wilsonhttp://www.w3.org/MarkUp/DTD/xhtml11.dtd
,即使不使用DefaultEntityResolver
,它也可以成功解析(尽管在我的系统上访问DTD大约需要10分钟)。不幸的是,结果相同。我将更新问题以使用此工作URL,并删除DefaultEntityResolver
。我已经创建了https://stackoverflow.com/q/60655704/421049,关于另一个URL中缺少的实体。 - Garret Wilson