首页 > 解决方案 > 使用java从xml中删除包含实体的doctype

问题描述

我正在尝试处理一个 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'>
]> 

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

标签: javaregexxmlstringregular-language

解决方案


您的方法不起作用,因为您在正则表达式的"final 之前需要。你可以用那里替换。>ENTITIY\"['\"]

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

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

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

请参阅正则表达式演示

细节

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

推荐阅读