1

I have String as XML. I'm trying to transform String by regexp:

public String replaceValueByTag(final String source, String tag, String value) {
     return replaceFirst(source, "(?<=<" + tag + ">).*?(?=</" + tag + ">)", value);
}

then create map with tag, new value:

Map<String, String> params = TAGS.stream().collect(toMap(tag -> tag, tag -> substringByTag(request, tag)));

and use map to replace values in XML:

public String getConfirm(String request) {
    String[] answer = {template}; 
    Map<String, String> params = TAGS.stream().collect(toMap(tag -> tag, tag -> substringByTag(request, tag)));   
    params.entrySet().forEach(entry -> answer[0] = replaceValueByTag(answer[0], entry.getKey(), entry.getValue()));
    return answer[0];
}

How to write lambda expression without saving in array (lambda takes String, converts it by map and returns a String)?

3
  • 5
    Regular expressions are not the right tool to work on XML. Commented Feb 16, 2018 at 8:32
  • 4
    You need to be aware that your regular expression will match occurrences of the string within element and attribute names, attribute values, etc, and will produce invalid XML in such cases. A vast proportion of the SO traffic on XML forums is caused by people generating invalid XML as a result of careless coding like this. Commented Feb 16, 2018 at 9:55
  • 1
    Besides the incorrectness of this approach, the repeated “convert the entire string” steps are horribly inefficient. Commented Feb 16, 2018 at 12:42

2 Answers 2

2

You can use reduce to apply all the elements of the Stream of map entries on your template String.

I'm not sure, though, how the combiner should look like (i.e. how to combine two partially transformed Strings into a String that contains all transformations), but if a sequential Stream is sufficient, you don't need the combiner:

String result = 
    params.entrySet()
          .stream()
          .reduce(template,
                  (t,e) -> replaceValueByTag(t, e.getKey(), e.getValue()),
                  (s1,s2)->s1); // dummy combiner
Sign up to request clarification or add additional context in comments.

Comments

0

instead of using an intermediate map you could directly apply the terminal operation, I'll use the .reduce() operation like @Eran suggested:

String result = TAGS.stream()
     .reduce(
         template, 
         (tmpl, tag) -> replaceValueByTag(tmpl, tag, substringByTag(request, tag),
         (left, right) -> left) // TODO: combine them
     );

This way you wont have as much overhead.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.