所以在org.apache.commons.lang3.text中有一个名为StrSubstitutor的类可以接收这样的地图:
Map<String, String> params = new HashMap<String, String>();
params.put("name","Vivek");
params.put("id","900");
params.put("somethingelse","blah");
和这样的模板字符串:
<data>
<id>${id}</id>
<name>${name}</name>
<something>${somethingelse}</something>
</data>
生成这样的输出字符串:
<data>
<id>900</id>
<name>Vivek</name>
<something>blah</something>
</data>
我想要的是相反的。有没有办法可以使用输出字符串和模板填充地图,模板变量作为键,字符串中的相应值作为值?
PS - 我将使用的字符串不一定总是XML。这只是一个例子。
编辑:我认为有些人感到困惑,因为变量名称和标签名称是相同的。标签只是说明性的,与问题无关。我担心的是$ {}内的变量。我添加了另一个标签来表明我的意思。答案 0 :(得分:0)
您可以使用模式将格式字符串转换为正则表达式,然后使用此正则表达式来进行输入字符串,在示例类下面:
public final class FormatReader {
private final Pattern formatPattern;
private final List<String> names;
private FormatReader(
final Pattern formatPattern,
final List<String> names) {
////
this.formatPattern = formatPattern;
this.names = names;
}
public static FormatReader of(
final String prefix,
final String suffix,
final String format) {
////
return of(prefix, suffix, format, true);
}
public static FormatReader of(
final String prefix,
final String suffix,
final String format,
final boolean allowSurroundingWhitespace) {
////
// This method is somewhat ugly...
final List<String> names = new ArrayList<>();
final StringBuilder sb = new StringBuilder("(?m)");
boolean skip = allowSurroundingWhitespace;
if (skip)
sb.append("\\s*");
for (int i = 0, last = 0, prefixLength = prefix.length(), suffixLength = suffix.length();;) {
if (i == format.length()) {
if (!skip)
sb.append(Pattern.quote(format.substring(last)));
break;
}
if (format.startsWith(prefix, i)) {
skip = true;
sb.append(Pattern.quote(format.substring(last, i))).append("(.+)");
final int off = i + prefixLength;
names.add(format.substring(off, i = format.indexOf(suffix, off)));
i += suffixLength;
continue;
}
if (Character.isWhitespace(format.charAt(i))) {
if (!skip) {
skip = true;
// Replace '\s*' with '\s+' if at least one whitespace has to be present
sb.append(Pattern.quote(format.substring(last, i))).append("\\s*");
}
} else if (skip) {
last = i;
skip = false;
}
i++;
}
if (!skip && allowSurroundingWhitespace)
sb.append("\\s*");
return new FormatReader(Pattern.compile(sb.toString()), names);
}
public Map<String, String> toMap(
final String input) {
////
final Matcher m = formatPattern.matcher(input);
if (!m.matches())
throw new IllegalArgumentException("Argument does not match format");
final Map<String, String> map = new HashMap<>();
for (int i = 0; i < m.groupCount();)
map.put(names.get(i), m.group(++i));
return map;
}
public static void main(
final String[] args) {
////
final FormatReader r = of("${", "}", ""
+ " <data>\n"
+ " <id>${id}</id>\n"
+ " <name>${name}</name>\n"
+ " </data>");
final String s = ""
+ " <data>\n"
+ " <id>900</id> "
+ " <name>Vivek</name>\n"
+ " </data> ";
// The created pattern (accepts any count of whitespace):
// 'id' 'name'
// (?m)\s*\Q<data>\E\s*\Q<id>\E(.+)\Q</id>\E\s*\Q<name>\E(.+)\Q</name>\E\s*\Q</data>\E\s*
System.out.println(r.toMap(s)); // {name=Vivek, id=900}
}
}
答案 1 :(得分:0)
这是另一种选择:
import java.util.HashMap;
import java.util.Map;
public class Test{
public static void main(String[] args){
//simulate template. Assuming no more than on param in line
String[] template = new String[]{
"<data>",
"<id>${id}</id>",
"<name>${name}</name>",
"<something>${somethingelse}</something>",
"</data>"
};
String[] output = new String[]{
"<data>",
"<id>900</id>",
"<name>Vivek</name>",
"<somethingelse>blah</somethingelse>",
"</data>"
};
Map<String, String> params = getParams(template);
getValues(params, output);
for(String key : params.keySet()) {
System.out.println(key +" : " + params.get(key));
}
}
private static Map<String, String> getParams(String[] template) {
Map<String, String> params = new HashMap<String, String>();
for (String line : template) {
//get location of 3 chars ${}
int index$ = line.indexOf("$");
int indexLeftB = line.indexOf("{");
int indexRightB = line.indexOf("}");
//make sure all ${} are present
if((index$ <0) || (indexLeftB <0) || (indexRightB <0) ) {
continue;
}
//make sure they are in the right order
if( ((indexLeftB - index$) !=1) || (indexRightB < indexLeftB)) {
continue;
}
//get param
String param = getParamFromLine(line, indexLeftB+1 , indexRightB);
if(param != null) {
params.put(param,null);
}
}
return params;
}
private static void getValues(Map<String, String> params, String[] output) {
//iterate over map
for(String param : params.keySet()) {
String tag = "<"+param+">"; //like <name>
String closeTag = "</"+param+">"; //like <name>
//iterate over output
for(String line : output) {
line = line.trim(); //remove all whitespace
//look for first occurrence of patternToSearch
int index1 = line.indexOf(tag, 0);
int index2 = line.indexOf(closeTag, index1);
//make sure there are 2 occurrences in
if((index1 < 0) || (index2 < 0)) {
continue;
}
String value = getParamFromLine(line, index1+ tag.length(), index2);
if(value != null) {
params.put(param, value);
}
}
}
}
private static String getParamFromLine(String line, int indexLeftB, int indexRightB) {
String param = line.substring(indexLeftB, indexRightB);
return (param.trim().length() == 0) ? null : param.trim();
}
}