【问题标题】:Anything better than JSoup for Android?有什么比 JSoup for Android 更好的吗?
【发布时间】:2012-01-26 15:09:45
【问题描述】:

我想做什么...

我的 android 应用中有一个 webview。我从服务器获得一个巨大的 html 内容作为字符串和来自应用程序用户(android 手机用户)的搜索字符串。现在我打破搜索字符串并从中创建一个正则表达式。我希望在将与我的正则表达式匹配的所有 html 内容显示到我的 WebView 时突出显示它。

我尝试了什么...

由于是html,我只想将正则表达式匹配的单词包装成一对黄色背景的标签。

  1. 我得到的 html 内容上的简单正则表达式和 replaceAll。非常错误,因为它甚至会替换 '' 中的内容。
  2. 我尝试使用 Matcher 和 Pattern 组合。很难省略标签内的内容。
  3. 我使用了 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();

我确信我正在做的不是最理想的方式。但我似乎想不出别的了。

我想 - 减少突出显示它所需的时间。 - 减少库的大小

有什么建议吗?

【问题讨论】:

    标签: android html html-parsing jsoup


    【解决方案1】:

    JTidy 和 HTMLCleaner 也是最好的 Java HTML 解析器之一。

    Comparison between different Java HTML Parser

    What are the pros and cons of the leading Java HTML parsers?

    【讨论】:

    • 我们可以用 JTidy 或 HTML Cleaner 遍历 DOM 树吗?有任何代码 sn-ps 或链接吗?
    【解决方案2】:

    如何使用 javascript 突出显示它们?

    你知道,每个人都喜欢 javascript,你可以找到像 this blog 这样的例子。

    【讨论】:

    • 他们可以,但我不想在我的 webview 上启用 javascript。
    猜你喜欢
    • 2012-08-28
    • 1970-01-01
    • 2011-07-27
    • 1970-01-01
    • 2010-12-23
    • 2010-09-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多