使用java从xml中删除包含实体的doctype

Posted

技术标签:

【中文标题】使用java从xml中删除包含实体的doctype【英文标题】:Remove doctype containing entity from xml using java 【发布时间】:2019-04-19 10:46:57 【问题描述】:

我正在尝试处理一个 xml,在此之前我需要从输入 xml 中删除 doctype 和实体声明。

我正在使用下面的代码来删除文档类型和实体:

fileContent = fileContent.replaceAll("<!ENTITY ((.|\n|\r)*?)\">", "");
fileContent = fileContent.replaceAll("<!DOCTYPE((.|\n|\r)*?)>", "");

这将删除实体,然后删除文档类型。 如果 xml 在 xml 中包含以下 doctype 声明,这可以正常工作:

<!DOCTYPE ichicsr SYSTEM "http://www.w3.org/TR/html4/frameset.dtd">

<!DOCTYPE ichicsr SYSTEM "D:\UPGRADE\NTServices\Server\\Xml21.dtd"
[<!ENTITY % entitydoc SYSTEM "D:\UPGRADE\NTServices\Server\\latin-entities.dtd"> %entitydoc;]>

但是,如果我有下面给出的 doctype,它就不起作用,并且 xml 中的根标记被剥离:

<!DOCTYPE ichicsr SYSTEM "D:\UPGRADE\NTServices\Server\\Xml21.dtd" 
[<!ENTITY % entitydoc SYSTEM 'D:\UPGRADE\NTServices\Server\\Xml21.dtd'>
]> 

如果我使用的正则表达式不正确或需要采取任何其他措施,请告诉我。

【问题讨论】:

永远不要使用(.|\n|\r)*?,将.*?Pattern.DOTALL(或内联(?s)变体)一起使用,或至少使用[\s\S]*? 尝试单个替换replaceAll("&lt;!DOCTYPE[^&lt;&gt;]*(?:&lt;!ENTITY[^&lt;&gt;]*&gt;[^&lt;&gt;]*)?&gt;", "") 感谢维克托。它对我有用。但是,有没有办法使用单一模式来处理大写和小写的文档类型和实体? 好吧,你的行不通,因为在 ENTITIY 正则表达式中 &gt; 之前需要 "。您可以在那里将\" 替换为['\"] 好的..明白了。但是,有没有办法使用单一模式处理大写和小写文档类型和实体 【参考方案1】:

您的方法不起作用,因为您在 ENTITIY 正则表达式中的最终 &gt; 之前需要 "。您可以在那里将\" 替换为['\"]

此外,切勿在任何正则表达式中使用(.|\n|\r)*?,因为它是性能杀手。相反,将.*?Pattern.DOTALL(或内联(?s) 变体)一起使用,或至少使用[\s\S]*?

不过,还有一个更好的办法:将两个正则表达式合并为一个:

fileContent = fileContent.replaceAll("(?i)<!DOCTYPE[^<>]*(?:<!ENTITY[^<>]*>[^<>]*)?>", "");

请参阅regex demo。

详情

(?i) - 不区分大小写 Pattern.CASE_INSENSITIVE 内联修饰符 &lt;!DOCTYPE - 文字文本 [^&lt;&gt;]* - 除了 &lt;&gt; 之外的 0+ 个字符 (?:&lt;!ENTITY[^&lt;&gt;]*&gt;[^&lt;&gt;]*)? - 可选出现 &lt;!ENTITY [^&lt;&gt;]* - 除了 &lt;&gt; 之外的 0+ 个字符 &gt; - 一个 &gt; 字符 [^&lt;&gt;]* - 除了 &lt;&gt; 之外的 0+ 个字符 &gt; - &gt; 字符。

【讨论】:

非常感谢wiktor的解决方案。

以上是关于使用java从xml中删除包含实体的doctype的主要内容,如果未能解决你的问题,请参考以下文章

JPA删除实体

使用声明的 encoding=utf-8 从 xml 中删除非 UTF-8 字符 - Java

Java - 从动态 XML 中删除子节点

XML External Entity 漏洞

javax.xml.transform.Transformer 的漂亮打印输出,仅使用标准 java api(缩进和 Doctype 定位)

Entity Framework Core 删除包含已读取实体的实体