像(?<!&#?[0-9a-zA-Z]+);
这样的正则表达式可能会做到这一点。这将阻止匹配终止实体引用或字符引用的分号,尽管它也捕获了一些在技术上不是规范的情况(例如,它不会匹配&#foo;
or末尾的分号&123;
)。
(?<!...)
是一个“负向后看”,因此您可以将此正则表达式读取为匹配一个分号,该分号前面没有匹配的子字符串&#?[0-9a-zA-Z]+
(即&符号、可选哈希和一个或多个字母数字)。但是,lookbehinds 必须对它们可以匹配的字符数有一个上限,而这+
没有,因此您必须使用有界重复计数,{1,5}
而不是 unbounded +
。上限必须至少与您可能看到的最长实体引用一样长,如果您的数据可能包含任意实体引用,那么您将不得不使用字符串长度之类的东西作为上限。
String[] keyValuePairs = theString.split(
"(?<!&#?[0-9a-zA-Z]{1," + theString.length() + "});");
如果您可以指定更小的界限,那么这可能会更有效。
编辑:Android 显然不喜欢这种向后看,即使有限制的重复,所以你可能无法使用单个正则表达式String.split
来做你所追求的,你必须自己做循环,例如
Pattern p = Pattern.compile("(?:&#?[0-9a-zA-Z]+)?;");
Matcher m = p.matcher(theString);
List<String> splits = new ArrayList<String>();
int lastEltStart = 0;
while(m.find()) {
if(m.end() - m.start() > 1) {
// this match was an entity/character reference so don't split here
continue;
}
if(m.start() > lastEltStart) {
// non-empty part
splits.add(theString.substring(lastEltStart, m.start()));
}
lastEltStart = m.end();
}
if(lastEltStart < theString.length()) {
// non-empty final part
splits.add(theString.substring(lastEltStart));
}