java - Java XML 解析器添加了不必要的 xmlns 和 xml:space 属性
问题描述
我在 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"
,似乎完全不正确;我想只有像<pre>
应该设置的元素。xml:space="preserve"
(更新: HTML5规范表明默认情况下 HTML 会保留空间,并且xml:space
不能在 HTML 中序列化,所以这可能是这里推理的一部分。我将改进我的 HTML 序列化程序以忽略该xml:space
属性,这将部分缓解这个问题.)
还要注意version="-//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 强制删除具有隐含默认值的属性。)但这非常低效;在解析时完全关闭它会很好。
解决方案
您是否尝试过nonvalidating/load-dtd-grammar
Xerces 配置功能?
但是,我一直在研究如何在 Saxon 中执行此操作,并且我不会要求 XML 解析器不报告默认属性,而是在报告默认属性时将其丢弃。我使用 Xerces 作为 SAX 解析器而不是 DOM 解析器。(在 SAX 中,使用 报告默认属性Attributes2.isDefaulted()
)。
推荐阅读
- ruby-on-rails - 使用 Devise 退出 - 发出不必要的 DELETE 请求
- javascript - 按下空格键时在图像之间切换
- android - 在 androidx 片段之间传递数据
- javascript - 允许字母数字和空格的正则表达式
- postgresql - Hibernate将camelCase字段映射到snake_case
- javascript - 在 JavaScript 中反序列化通过 websocket 接收的简单数组
- python-3.x - 如何检查一个值是否在熊猫的同一列中多次出现?
- docker - 我的 docker 无法连接到互联网 - 即使使用正确的 dns
- python - 根据条件比较 2 个数据框列后,如何创建新的 pandas 数据框?
- kubernetes - Spring批量迁移到kubernetes平台