我想做什么......
我的Android应用程序中有一个webview。我从服务器获取一个巨大的html内容作为字符串和来自应用程序用户(Android手机用户)的搜索字符串。现在我打破搜索字符串并创建一个正则表达式。当我将其显示在我的WebView中时,我希望突出显示与我的正则表达式匹配的所有html内容。
我尝试了什么...
因为它是html,我只想将正则表达式匹配的单词包装成一对带黄色背景的标签。
我使用NodeTraversor类遍历html。我使用Matcher和Pattern类来查找匹配的单词并将其替换为我想要的标签。
但它很慢。我基本上想在Android上使用它,它的大小就像284kB。我删除了一些不需要的类,它现在是201kB,但对于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();
我确信我所做的并不是最佳方式。但我似乎无法想到其他任何事情。
我想 - 减少突出显示它所需的时间。 - 减小库的大小
有什么建议吗?
答案 0 :(得分:2)
如何使用javascript突出显示它们?
你知道,每个人都喜欢javascript,你可以找到像this blog这样的例子。
答案 1 :(得分:0)
JTidy和HTMLCleaner是最好的Java HTML Parser之一。
见 Comparison between different Java HTML Parser
和
What are the pros and cons of the leading Java HTML parsers?