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

时间:2018-11-16 09:08:05

标签: java regex xml string regular-language

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

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

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'>
]> 

请让我知道我使用的正则表达式是否错误或需要采取任何其他措施。

1 个答案:

答案 0 :(得分:3)

您的方法行不通,因为在"正则表达式中,最终>之前需要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多个字符
  • >-一个>字符。