使用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("<!DOCTYPE[^<>]*(?:<!ENTITY[^<>]*>[^<>]*)?>", "")
感谢维克托。它对我有用。但是,有没有办法使用单一模式来处理大写和小写的文档类型和实体?
好吧,你的行不通,因为在 ENTITIY 正则表达式中 >
之前需要 "
。您可以在那里将\"
替换为['\"]
。
好的..明白了。但是,有没有办法使用单一模式处理大写和小写文档类型和实体
【参考方案1】:
您的方法不起作用,因为您在 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+ 个字符
>
- >
字符。
【讨论】:
非常感谢wiktor的解决方案。以上是关于使用java从xml中删除包含实体的doctype的主要内容,如果未能解决你的问题,请参考以下文章
使用声明的 encoding=utf-8 从 xml 中删除非 UTF-8 字符 - Java
javax.xml.transform.Transformer 的漂亮打印输出,仅使用标准 java api(缩进和 Doctype 定位)