使用 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+ 个字符
>
- 一个 >
字符。
我正在尝试处理 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+ 个字符
>
- 一个>
字符。