2011-12-07 2 views
1

J'utilise JSoup parser pour trouver des parties particulières d'un document html (défini par regex) et le mettre en surbrillance en enveloppant la chaîne trouvée dans la balise <span>. Voici mon code qui fait la mise en évidence -Mettre en évidence en utilisant Regex dans JSOUP pour android

public String highlightRegex() { 
Document doc = Jsoup.parse(htmlContent); 

     NodeTraversor nd = new NodeTraversor(new NodeVisitor() { 

      @Override 
      public void tail(Node node, int depth) { 
       if (node instanceof Element) { 

        Element elem = (Element) node; 

        StringBuffer obtainedText; 
        for(Element tn : elem.getElementsMatchingOwnText(pat)) { 

         Log.e("HELLO", tn.baseUri()); 
         Log.e("HELLO", tn.text()); 
         obtainedText = new StringBuffer(tn.ownText()); 
         mat = pat.matcher(obtainedText.toString()); 
         int nextStart = 0; 
         while(mat.find(nextStart)) { 
          obtainedText = obtainedText.replace(mat.start(), mat.end(), "<span>" + mat.group() + "</span>"); 
          nextStart = mat.end() + 1; 
         } 
         tn.text(obtainedText.toString()); 
         Log.e("HELLO" , "AFTER:" + tn.text()); 

        } 
       } 
      } 

      @Override 
      public void head(Node node, int depth) {   
      } 
     }); 

     nd.traverse(doc.body()); 
     return doc.toString(); 
    } 

Il fonctionne, mais la balise <span> est visible à l'intérieur du WebView. Qu'est-ce que je fais mal?

Répondre

0

On dirait que personne ne le sait. Voici un code que j'ai trouvé. Lent et inefficace mais fonctionne quand même. Les suggestions sont acceptées :)

Cette classe peut être utilisée pour mettre en évidence n'importe quel HTML en utilisant une regex.

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; 
     } 
    } 
} 

vous devez appeler ces deux méthodes pour obtenir le code html surligné -

Highlighter hl = new Highlighter("abc def", htmlString); 
String newhtmlString = hl.getHighlightedHtml(); 

Cela mettra en lumière tout ce qui correspond à la regex (abc)|(def)*. Vous pouvez changer la façon dont vous voulez que l'expression rationnelle soit construite par la fonction modifying buildRegexFromQuery().

Questions connexes