使用 java 从 xml 中删除包含实体的文档类型

Remove doctype containing entity from xml using java

我正在尝试处理 xml,在此之前我需要从输入 xml 中删除文档类型和实体声明。

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

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

这将删除实体,然后删除文档类型。 如果 xml 在 xml:

中包含以下文档类型声明,则此操作正常
<!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;]>

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

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

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

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

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

但是,有一个更好的方法:将两个正则表达式合并为一个:

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

参见regex demo

详情

  • (?i) - 不区分大小写 Pattern.CASE_INSENSITIVE 内联修饰符
  • <!DOCTYPE - 文字
  • [^<>]* - <>
  • 以外的 0+ 个字符
  • (?:<!ENTITY[^<>]*>[^<>]*)? - 可选的出现
    • <!ENTITY
    • [^<>]* - <>
    • 以外的 0+ 个字符
    • > - 一个 > 字符
    • [^<>]* - <>
    • 以外的 0+ 个字符
  • > - 一个 > 字符。