什么比JSoup for Android更好?

时间:2011-12-23 06:34:40

标签: android html html-parsing jsoup

我想做什么......

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

我尝试了什么...

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

  1. 我得到的html内容上的简单正则表达式和replaceAll。非常错误,因为它会拧紧并取代“'<&#;和'>'。
  2. 我尝试使用Matcher和Pattern组合。很难省略标签内的内容。
  3. 我使用了JSOUP Parser并且它有效!
  4. 我使用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();
    

    我确信我所做的并不是最佳方式。但我似乎无法想到其他任何事情。

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

    有什么建议吗?

2 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:0)