我想做什么...
我的 android 应用程序中有一个 webview。我从服务器获得大量 html 内容作为字符串和来自应用程序用户(android 手机用户)的搜索字符串。现在我打破搜索字符串并从中创建一个正则表达式。我希望所有与我的正则表达式匹配的 html 内容在我将其显示到我的 WebView 中时突出显示。
我试过的...
既然是html,我只想把regex匹配的词包裹成一对黄色背景的标签。
- 我得到的 html 内容上的简单正则表达式和 replaceAll。非常错误,因为它甚至会破坏和替换“<”和“>”中的内容。
- 我尝试使用匹配器和模式组合。很难省略标签内的内容。
- 我使用了 JSOUP 解析器,它成功了!
我使用 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();
我确定我正在做的不是最佳方式。但我似乎想不出别的。
我要 - 减少突出显示它所需的时间。 - 减少库的大小
有什么建议吗?
最佳答案
如何使用 javascript 突出显示它们?
你知道,每个人都喜欢 javascript,你可以找到像 this blog 这样的例子.
关于android - 有什么比适用于 Android 的 JSoup 更好的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8612976/