使用Regex修复Java中未转义的XML实体?

Gre*_*tes 5 java regex xml entities automata

我有一些格式错误的XML,我必须解析.无法解决上游问题.

(当前)问题是&符号并不总是正确转义,所以我需要转换&&

如果&amp;已经存在,我不想将其更改为&amp;amp;.一般来说,如果任何格式良好的实体已经存在,我不想破坏它.我不认为通常可以知道可能出现在任何特定XML文档中的所有实体,所以我想要一个&<characters>;保留任何类似的解决方案.

<characters>初始&和结束之间定义实体的一组字符在哪里;.特别是,<>不是原本表示XML元素的文字.

现在,在解析时,如果我看到&<characters>我不知道我是否会遇到a ;, (space), end-of-line, or another &.因此,我认为我必须记住,<characters>因为我向前看一个会告诉我如何处理原始角色的角色&.

我认为我需要使用Push Down Automaton的功能来实现这一点,我认为有限状态机不会因为我认为是内存要求而起作用 - 这是正确的吗?如果我需要PDA,那么调用中的正则表达式String.replaceAll(String, String)将无法工作.或者是否有可以解决此问题的Java正则表达式?

请记住:每行可能有多个替换.

(我知道这个问题,但它没有提供我正在寻找的答案.)

Ben*_*ing 8

这是你正在寻找的正则表达式:&([^;\\W]*([^;\\w]|$))和相应的替换字符串&amp;$1.它匹配&,后跟零个或多个非分号或分词(它需要允许零来匹配独立的&符号),然后是不是分号(或行结束)的分词.捕获组允许您使用&amp;您正在寻找的替换进行替换.

以下是使用它的一些示例代码:

String s = "&amp; & &nsbp; &tc., &tc. &tc";
final String regex = "&([^;\\W]*([^;\\w]|$))";
final String replacement = "&amp;$1";
final String t = s.replaceAll(regex, replacement);
Run Code Online (Sandbox Code Playgroud)

在沙盒中运行后,我得到以下t的结果:

&amp; &amp; &nsbp; &amp;tc., &amp;tc. &amp;tc
Run Code Online (Sandbox Code Playgroud)

如您所见,原始&amp;&nbsp;保持不变.但是,如果你用"&&"尝试它,你会得到&amp;&,如果你用"&&&"尝试它,你会得到&amp;&&amp;,我把它作为你所暗示的前瞻问题的症状.但是,如果您更换该行:

final String t = s.replaceAll(regex, replacement);
Run Code Online (Sandbox Code Playgroud)

有:

final String t = s.replaceAll(regex, replacement).replaceAll(regex, replacement);
Run Code Online (Sandbox Code Playgroud)

它适用于所有这些字符串以及我能想到的任何其他字符串.(在完成的产品中,您可能会编写一个可以执行此双重replaceAll调用的例程.)


iX3*_*iX3 5

我想你也可以使用前瞻来查看&字符后跟字符和分号(例如&(?!\w+;)).这是一个例子:

import java.util.*;
import java.util.regex.*;

public class HelloWorld{
    private static final Pattern UNESCAPED_AMPERSAND =
        Pattern.compile("&(?!(#\\d+|\\w+);)");
     public static void main(String []args){
        for (String s : Arrays.asList(
            "http://www.example.com/?a=1&b=2&amp;c=3/",
            "Three in a row: &amp;&&amp;",
            "&lt; is <, &gt; is >, &apos; is ', etc."
        )) {
            System.out.println(
                UNESCAPED_AMPERSAND.matcher(s).replaceAll("&amp;")
            );        
        }
     }
}

// Output:
// http://www.example.com/?a=1&amp;b=2&amp;c=3/
// Three in a row: &amp;&amp;&amp;
// &lt; is <, &gt; is >, &apos; is ', etc.
Run Code Online (Sandbox Code Playgroud)

  • 如果使用`&(?!(#\ d + |\w +);)`,它将处理数字转义,例如`&#160;` (2认同)

Jes*_*ebb 1

不要尝试对所有可能的不良数据进行一般性处理,而只需一次处理一个不良数据的出现。很可能生成 XML 的任何内容都会弄乱一两个字符,但不会弄乱全部字符。这当然是一个假设。

尝试将所有 & 替换为 &,除非 & 后面跟着 amp;。如果您遇到的下一个编码错误的字符是 <,则将它们全部替换为 <。保持规则集小且易于管理,只处理你知道是错误的事情。

如果你尝试做太多事情,你最终可能会替换掉你不打算替换的东西,并且自己搞乱数据。

我还想指出,最好的解决方案是鼓励生成 XML 的人修复其最终的编码。这可能很难问,但如果您专业地向他们解释他们没有生成有效的 XML,他们可能愿意修复错误。这将为下一个必须使用它的人带来额外的好处,而无需执行一些疯狂的自定义代码来解决应该从源头解决的问题。至少考虑一下。可能发生的更糟糕的事情是,你提出要求,他们说不,而你就在现在的位置。