use regex on html tags but keep delimiters

Viewed 55

I'm trying to split up a string of html tags from a rich text field in my database into ordered tags and words. I want to keep the delimiters in order so I can rebuild the string. I'm using language translation APIs to convert the words.

String original = "<b>hello!</b><br><br><b><u>this is an example</u></b><br>";
String reg = "(?=<(“[^”]*”|'[^’]*’|[^'”>])*>)";
String[] conversion = original.split(reg);

for(String token : conversion) {
    System.out.println(token);
} 

I'm getting the following output:

<b>hello!
</b>
<br>
<br>
<b>
<u>this is an example
</u>
</b>
<br>

Which is super close. I tried using Lookbehind regex (?=<(“[^”]*”|'[^’]*’|[^'”>])*>)|(?<=<(“[^”]*”|'[^’]*’|[^'”>])*>) but I run into an error "Invalid regex: Look-behind group does not have an obvious maximum length near index 62". Its pointing at this section:

(?=<(“[^”]*”|'[^’]*’|[^'”>])*>)|(?<=<(“[^”]*”|'[^’]*’|[^'”>])*>)
                                                              ^

I'm trying to get this output for each line:

<b>
hello!
</b>
<br>
<br>
<b>
<u>
this is an example
</u>
</b>
<br>

I'm newer to regex and this all looks like witchcraft to me. Anyone know any Java-friendly lookbehind or techniques to accomplish this?

1 Answers

You can split with an empty location before <, after > BUT not when at the start of the string:

original.split("(?!^)(?:(?<=>)|(?=<))")

See the regex demo. Details:

  • (?!^) - make sure the position is not at the start of the string
  • (?:(?<=>)|(?=<)) - either of the two:
    • (?<=>) - a positive lookbehind that matches a position that is immediately preceded with a > char
    • | - or
    • (?=<) - a positive lookahead that matches a position that is immediately followed with a < char.

See the Java demo:

String original = "<b>hello!</b><br><br><b><u>this is an example</u></b><br>";
String separator = "(?!^)(?:(?<=>)|(?=<))";
String[] results = original.split(separator);
System.out.println(Arrays.toString(results));
Related