2011-12-07 2 views
1

JSext 파서를 사용하여 HTML 문서의 특정 부분 (정규식으로 정의 됨)을 찾고 발견 된 문자열을 <span> 태그로 감싸서 강조 표시합니다.JSOUP에서 android 용 Regex를 사용하여 강조 표시

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

그것은 작업을 수행하지만, 태그 <span>는 웹보기 내부 볼 수 있습니다 - 여기에 강조 표시를하지 내 코드입니다. 내가 도대체 ​​뭘 잘못하고있는 겁니까?

답변

0

아무도 모르는 것처럼 보입니다. 여기에 몇 가지 코드가 있습니다. 느리고 비효율적이지만 어쨌든 작동합니다. 제안이 수락됩니다 :)

이 클래스는 정규식을 사용하여 모든 HTML을 강조 표시하는 데 사용할 수 있습니다. 이것은 정규식 (abc)|(def)* 일치하는 모든 것을 강조합니다

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

-

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

당신은 강조 표시된 HTML를 얻기 위해이 두 메소드를 호출해야합니다. modifying buildRegexFromQuery() 함수를 사용하여 정규 표현식을 작성하는 방식을 변경할 수 있습니다.

관련 문제