我们收到一个XML String,我们需要在解组之前清理一个属性值。问题是xml的类型非常松散,并且无法保证属性将以任何特定顺序存在或甚至存在。
<message>
<set name=".." value="garbled string" type="name" />
<set age=".." value="32" />
<set something=".." value="value=\"\"\"\"" />
..
</message>
在这个String中我需要调用一个模式,这样我只需要获取XML的value属性的字符串,编码任何特殊字符(StringEscapeUtils.escapeXml())并替换它的值。即使值包含字符串&#34;值&#34;里面不应该导致任何正则表达式模式不匹配。
请帮忙。
答案 0 :(得分:0)
您可以将正则表达式(?<=value\=")(?:[^"\\<]|\\"|\\\\)++(?=")
与Matcher#find()
结合使用,以查找XML属性value
的所有值。
String input = "<message>\n <set name=\"..\" value=\"garbled string\" type=\"name\" />\n <set age=\"..\" value=\"32\" />\n <set something=\"..\" value=\"value=\\\"\\\"\\\"\\\"\" />\n ..\n</message>";
Pattern pattern = Pattern.compile("(?<=value\\=\")(?:[^\"\\\\<]|\\\\\"|\\\\\\\\|\\\\<)++(?=\")");
Matcher matcher = pattern.matcher(input);
StringBuilder convertedInput = new StringBuilder();
int trailing = 0;
while (matcher.find()) {
String value = matcher.group();
String convertedValue = StringEscapeUtils.escapeXml(value);
convertedInput.append(input.substring(trailing, matcher.start()));
convertedInput.append(convertedValue);
trailing = matcher.end();
}
if (trailing < input.length()) {
convertedInput.append(input.substring(trailing, input.length()));
}
System.out.println(convertedInput);
运行时,convertedInput
应包含input
- 具体取决于StringEscapeUtils#escapeXml(String)
的功能 - 每个value
属性的所有值都是转义的XML字符串。我将<
添加到没有反斜杠转义的值中不得包含的字符中,否则,name="value="
等属性(感谢@Thomas将其指向注释中)会导致正则表达式去干草。
有关使用的正则表达式的详细信息,请访问this链接。
答案 1 :(得分:0)
我最近必须做类似的事情(即编码特殊字符以便让unmarshaller / parser完成它的工作)。我想出的解决方案如下:
java.io.FilterReader
实施FilterReader的read
方法,以便在读取特殊字符时对其进行编码,例如:
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
int charsWithoutEntity = len / 4;
int read = super.read(myBuffer, off, charsWithoutEntity <= myBuffer.length ? charsWithoutEntity : myBuffer.length);
int j = 0;
for (int i = 0; i < read; i++, j++) {
cbuf[j] = myBuffer[i];
if (myBuffer[i] == '&') {
cbuf[++j] = 'a';
cbuf[++j] = 'm';
cbuf[++j] = 'p';
cbuf[++j] = ';';
}
}
return read > 0 ? j : read;
}
我选择流解析器的原因与此问题无关,我非常确定您可以将FilterReader
提供给JAXB Unmarshaller
,因此相同的解决方案可能也适用于您不想/需要使用解析器的情况。