Что я хочу сделать ...
У меня есть веб-просмотр в моем приложении для Android.Я получаю огромный HTML-контент с сервера в виде строки и строки поиска от пользователя приложения (пользователя телефона Android).Теперь я ломаю строку поиска и создаю из нее регулярное выражение.Я хочу, чтобы весь HTML-контент, соответствующий моему регулярному выражению, выделялся при его отображении в моем WebView.
То, что я пробовал ...
Поскольку это HTML, я просто хочу обернуть слова, соответствующие регулярному выражению, в пару тегов с желтым фоном.
- Простое регулярное выражение и замена всех на HTML-контент, который я получаю.Очень неправильно, потому что он привинчивает и заменяет даже то, что находится внутри '<' и '>'.
- Я пытался использовать комбинацию Matcher и Pattern.Трудно опустить то, что находится внутри тегов.
- Я использовал JSOUP Parser, и это сработало!
Я просматриваю HTML, используя класс NodeTraversor.Я использовал классы Matcher и Pattern, чтобы найти и заменить совпадающие слова тегами, как я хотел.
Но это очень медленно.И я в основном хочу использовать его на Android, и его размер составляет около 284 КБ.Я удалил некоторые ненужные классы, и теперь он составляет 201 КБ, но это все еще слишком много для устройства Android.Кроме того, HTML-контент может быть очень большим.Я также посмотрел на источник JSoup.Он выполняет итерацию по каждому отдельному символу при анализе.Я не знаю, все ли парсеры делают то же самое, но это определенно медленно для больших HTML-документов.
Вот мой код -
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Highlighter {
private String regex;
private String htmlContent;
Pattern pat;
Matcher mat;
public Highlighter(String searchString, String htmlString) {
regex = buildRegexFromQuery(searchString);
htmlContent = htmlString;
pat = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
}
public String getHighlightedHtml() {
Document doc = Jsoup.parse(htmlContent);
final List<TextNode> nodesToChange = new ArrayList<TextNode>();
NodeTraversor nd = new NodeTraversor(new NodeVisitor() {
@Override
public void tail(Node node, int depth) {
if (node instanceof TextNode) {
TextNode textNode = (TextNode) node;
String text = textNode.getWholeText();
mat = pat.matcher(text);
if(mat.find()) {
nodesToChange.add(textNode);
}
}
}
@Override
public void head(Node node, int depth) {
}
});
nd.traverse(doc.body());
for (TextNode textNode : nodesToChange) {
Node newNode = buildElementForText(textNode);
textNode.replaceWith(newNode);
}
return doc.toString();
}
private static String buildRegexFromQuery(String queryString) {
String regex = "";
String queryToConvert = queryString;
/* Clean up query */
queryToConvert = queryToConvert.replaceAll("[\\p{Punct}]*", " ");
queryToConvert = queryToConvert.replaceAll("[\\s]*", " ");
String[] regexArray = queryString.split(" ");
regex = "(";
for(int i = 0; i < regexArray.length - 1; i++) {
String item = regexArray[i];
regex += "(\\b)" + item + "(\\b)|";
}
regex += "(\\b)" + regexArray[regexArray.length - 1] + "[a-zA-Z0-9]*?(\\b))";
return regex;
}
private Node buildElementForText(TextNode textNode) {
String text = textNode.getWholeText().trim();
ArrayList<MatchedWord> matchedWordSet = new ArrayList<MatchedWord>();
mat = pat.matcher(text);
while(mat.find()) {
matchedWordSet.add(new MatchedWord(mat.start(), mat.end()));
}
StringBuffer newText = new StringBuffer(text);
for(int i = matchedWordSet.size() - 1; i >= 0; i-- ) {
String wordToReplace = newText.substring(matchedWordSet.get(i).start, matchedWordSet.get(i).end);
wordToReplace = "<b>" + wordToReplace+ "</b>";
newText = newText.replace(matchedWordSet.get(i).start, matchedWordSet.get(i).end, wordToReplace);
}
return new DataNode(newText.toString(), textNode.baseUri());
}
class MatchedWord {
public int start;
public int end;
public MatchedWord(int start, int end) {
this.start = start;
this.end = end;
}
}
}
Вот как я это называю -
htmlString = getHtmlFromServer();
Highlighter hl = new Highlighter("Hello World!", htmlString);
new htmlString = hl.getHighlightedHTML();
Я уверен, что то, что я делаю, не самый оптимальный способ,Но я не могу думать ни о чем другом.
Я хочу - сократить время, которое требуется, чтобы выделить это.- уменьшить размер библиотеки
Есть предложения?