2010-03-22 12 views
5

Java'da HTML önizleme yapan herhangi bir yardımcı program (veya örnek kaynak kodu) var mı? İstemcide değil, sunucudaki kısaltmayı yapmak istiyorum.html truncator java

HTML ayrıştırmak için HTMLUnit kullanıyorum.

GÜNCELLEME:
HTML'yi önizleyebilmeyi istiyorum, bu nedenle truncator, istenen çıktı uzunluğundan sonra öğeleri sıyırırken HTML yapısını koruyacaktır.

+0

Eğer bunu yapmaya "truncator" istediğini açıklayabilir içeren senin html ("daha az kısaltın :)) Ne arıyorsun? –

+0

Ana gönderide UPDATE başlığı altında bir yorum eklendi – smahesh

+0

Hala ne demek istediğini anlama/görselleştirme konusunda zor bir zamanım var. sadece istediğin o display ** sadece ** 'html.substring (0, someMaxLength);' ve hala geçerli işaretlemede? – BalusC

cevap

1

Bunu başarmak için kendi XML çözümleyicinizi yazmanız gerekecek. Gövde düğümünü dışarı çekin, ikili uzunluğu < sabit boyutuna kadar düğümler ekleyin ve sonra belgeyi yeniden oluşturun. HTMLUnit, semantik XHTML oluşturmuyorsa, tagsoup'u öneririm.

XML ayrıştırıcı/işleyicisine ihtiyacınız varsa, XOM'u öneririm.

+0

Sanırım yapmam gereken şey bu. Orada zaten başka bir şey olup olmadığını görmek istedim ... – smahesh

+0

Daha önce bunu yapması gerekeni hiç duymadım, o yüzden bu yüzden orada hiçbir (kolay bulmak, en azından) çözüm yok. –

+0

Ayrıca, XOM ile en azından grafiğin uzunluğunu kolayca kontrol edebilirsiniz. root.toXML(). GetBytes().length(), geçerli XML ağacının dize temsili için bayt sayısını döndürür. Ağacınızı aşamalı olarak oluşturursanız, her adımda baytları kontrol edebilir ve bayt> istenen bayttan bir kez geri dönebilirsiniz. –

0

Size bunu yazdığım bir Python betiği sunabilirim: http://www.ellipsix.net/ext-tmp/summarize.txt. Ne yazık ki bir Java sürümüm yok, ancak bunu kendiniz çevirmek ve istediğiniz gibi ihtiyaçlarınıza göre değiştirmek için çekinmeyin. Çok karmaşık değil, sadece web sitem için bir araya getirdiğim bir şey var, ama bir yıldan daha uzun bir süredir kullanıyordum ve genelde iyi çalışıyor gibi görünüyor.

Güçlü bir şey istiyorsanız, bir XML (veya SGML) ayrıştırıcısı neredeyse yaptığımdan daha iyi bir fikirdir.

+0

@David - Teşekkürler, ben kontrol edeceğim. – smahesh

1

burada öyle bir PHP işlevi vardır: Ben ilk versiyonunun hızlı ve kirli Java portu yaptık http://snippets.dzone.com/posts/show/7125

ama dikkate değer olabilir yorumlarda sonradan geliştirilmiş versiyonları özellikle (vardır) tam sözcükleri ile ilgilenen tek:

public static String truncateHtml(String s, int l) { 
    Pattern p = Pattern.compile("<[^>]+>([^<]*)"); 

    int i = 0; 
    List<String> tags = new ArrayList<String>(); 

    Matcher m = p.matcher(s); 
    while(m.find()) { 
     if (m.start(0) - i >= l) { 
      break; 
     } 

     String t = StringUtils.split(m.group(0), " \t\n\r\0\u000B>")[0].substring(1); 
     if (t.charAt(0) != '/') { 
      tags.add(t); 
     } else if (tags.get(tags.size()-1).equals(t.substring(1))) { 
      tags.remove(tags.size()-1); 
     } 
     i += m.start(1) - m.start(0); 
    } 

    Collections.reverse(tags); 
    return s.substring(0, Math.min(s.length(), l+i)) 
     + ((tags.size() > 0) ? "</"+StringUtils.join(tags, "></")+">" : "") 
     + ((s.length() > l) ? "\u2026" : ""); 

} 

Not: Sen StringUtils.join() için Apache Commons Lang gerekir.

2

truncateHTML'in başka bir java sürümünü yazıyorum. Bu işlev, tüm kelimeleri ve HTML etiketlerini korurken bir dizi karaktere kadar bir dizgeyi keser.

public static String truncateHTML(String text, int length, String suffix) { 
    // if the plain text is shorter than the maximum length, return the whole text 
    if (text.replaceAll("<.*?>", "").length() <= length) { 
     return text; 
    } 
    String result = ""; 
    boolean trimmed = false; 
    if (suffix == null) { 
     suffix = "..."; 
    } 

    /* 
    * This pattern creates tokens, where each line starts with the tag. 
    * For example, "One, <b>Two</b>, Three" produces the following: 
    *  One, 
    *  <b>Two 
    *  </b>, Three 
    */ 
    Pattern tagPattern = Pattern.compile("(<.+?>)?([^<>]*)"); 

    /* 
    * Checks for an empty tag, for example img, br, etc. 
    */ 
    Pattern emptyTagPattern = Pattern.compile("^<\\s*(img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param).*>$"); 

    /* 
    * Modified the pattern to also include H1-H6 tags 
    * Checks for closing tags, allowing leading and ending space inside the brackets 
    */ 
    Pattern closingTagPattern = Pattern.compile("^<\\s*/\\s*([a-zA-Z]+[1-6]?)\\s*>$"); 

    /* 
    * Modified the pattern to also include H1-H6 tags 
    * Checks for opening tags, allowing leading and ending space inside the brackets 
    */ 
    Pattern openingTagPattern = Pattern.compile("^<\\s*([a-zA-Z]+[1-6]?).*?>$"); 

    /* 
    * Find &nbsp; &gt; ... 
    */ 
    Pattern entityPattern = Pattern.compile("(&[0-9a-z]{2,8};|&#[0-9]{1,7};|[0-9a-f]{1,6};)"); 

    // splits all html-tags to scanable lines 
    Matcher tagMatcher = tagPattern.matcher(text); 
    int numTags = tagMatcher.groupCount(); 

    int totalLength = suffix.length(); 
    List<String> openTags = new ArrayList<String>(); 

    boolean proposingChop = false; 
    while (tagMatcher.find()) { 
     String tagText = tagMatcher.group(1); 
     String plainText = tagMatcher.group(2); 

     if (proposingChop && 
       tagText != null && tagText.length() != 0 && 
       plainText != null && plainText.length() != 0) { 
      trimmed = true; 
      break; 
     } 

     // if there is any html-tag in this line, handle it and add it (uncounted) to the output 
     if (tagText != null && tagText.length() > 0) { 
      boolean foundMatch = false; 

      // if it's an "empty element" with or without xhtml-conform closing slash 
      Matcher matcher = emptyTagPattern.matcher(tagText); 
      if (matcher.find()) { 
       foundMatch = true; 
       // do nothing 
      } 

      // closing tag? 
      if (!foundMatch) { 
       matcher = closingTagPattern.matcher(tagText); 
       if (matcher.find()) { 
        foundMatch = true; 
        // delete tag from openTags list 
        String tagName = matcher.group(1); 
        openTags.remove(tagName.toLowerCase()); 
       } 
      } 

      // opening tag? 
      if (!foundMatch) { 
       matcher = openingTagPattern.matcher(tagText); 
       if (matcher.find()) { 
        // add tag to the beginning of openTags list 
        String tagName = matcher.group(1); 
        openTags.add(0, tagName.toLowerCase()); 
       } 
      } 

      // add html-tag to result 
      result += tagText; 
     } 

     // calculate the length of the plain text part of the line; handle entities (e.g. &nbsp;) as one character 
     int contentLength = plainText.replaceAll("&[0-9a-z]{2,8};|&#[0-9]{1,7};|[0-9a-f]{1,6};", " ").length(); 
     if (totalLength + contentLength > length) { 
      // the number of characters which are left 
      int numCharsRemaining = length - totalLength; 
      int entitiesLength = 0; 
      Matcher entityMatcher = entityPattern.matcher(plainText); 
      while (entityMatcher.find()) { 
       String entity = entityMatcher.group(1); 
       if (numCharsRemaining > 0) { 
        numCharsRemaining--; 
        entitiesLength += entity.length(); 
       } else { 
        // no more characters left 
        break; 
       } 
      } 

      // keep us from chopping words in half 
      int proposedChopPosition = numCharsRemaining + entitiesLength; 
      int endOfWordPosition = plainText.indexOf(" ", proposedChopPosition-1); 
      if (endOfWordPosition == -1) { 
       endOfWordPosition = plainText.length(); 
      } 
      int endOfWordOffset = endOfWordPosition - proposedChopPosition; 
      if (endOfWordOffset > 6) { // chop the word if it's extra long 
       endOfWordOffset = 0; 
      } 

      proposedChopPosition = numCharsRemaining + entitiesLength + endOfWordOffset; 
      if (plainText.length() >= proposedChopPosition) { 
       result += plainText.substring(0, proposedChopPosition); 
       proposingChop = true; 
       if (proposedChopPosition < plainText.length()) { 
        trimmed = true; 
        break; // maximum length is reached, so get off the loop 
       } 
      } else { 
       result += plainText; 
      } 
     } else { 
      result += plainText; 
      totalLength += contentLength; 
     } 
     // if the maximum length is reached, get off the loop 
     if(totalLength >= length) { 
      trimmed = true; 
      break; 
     } 
    } 

    for (String openTag : openTags) { 
     result += "</" + openTag + ">"; 
    } 
    if (trimmed) { 
     result += suffix; 
    } 
    return result; 
} 
0
public class SimpleHtmlTruncator { 

    public static String truncateHtmlWords(String text, int max_length) { 
     String input = text.trim(); 
     if (max_length > input.length()) { 
      return input; 
     } 
     if (max_length < 0) { 
      return new String(); 
     } 
     StringBuilder output = new StringBuilder(); 
     /** 
     * Pattern pattern_opentag = Pattern.compile("(<[^/].*?[^/]>).*"); 
     * Pattern pattern_closetag = Pattern.compile("(</.*?[^/]>).*"); Pattern 
     * pattern_selfclosetag = Pattern.compile("(<.*?/>).*");* 
     */ 
     String HTML_TAG_PATTERN = "<(\"[^\"]*\"|'[^']*'|[^'\">])*>"; 
     Pattern pattern_overall = Pattern.compile(HTML_TAG_PATTERN + "|" + "\\s*\\w*\\s*"); 
     Pattern pattern_html = Pattern.compile("(" + HTML_TAG_PATTERN + ")" + ".*"); 
     Pattern pattern_words = Pattern.compile("(\\s*\\w*\\s*).*"); 
     int characters = 0; 
     Matcher all = pattern_overall.matcher(input); 
     while (all.find()) { 
      String matched = all.group(); 
      Matcher html_matcher = pattern_html.matcher(matched); 
      Matcher word_matcher = pattern_words.matcher(matched); 
      if (html_matcher.matches()) { 
       output.append(html_matcher.group()); 
      } else if (word_matcher.matches()) { 
       if (characters < max_length) { 
        String word = word_matcher.group(); 
        if (characters + word.length() < max_length) { 
         output.append(word); 
        } else { 
         output.append(word.substring(0, 
           (max_length - characters) > word.length() 
           ? word.length() : (max_length - characters))); 
        } 
        characters += word.length(); 
       } 
      } 
     } 
     return output.toString(); 
    } 

    public static void main(String[] args) { 
     String text = SimpleHtmlTruncator.truncateHtmlWords("<html><body><br/><p>abc</p><p>defghij</p><p>ghi</p></body></html>", 4); 
     System.out.println(text); 
    } 
} 
+3

_why_ ve bu sorunun nasıl cevaplandığını açıklar mısınız? – Ben

+0

Bu snippet'te içerik kesiliyor ve html yapısı korunur. Yani soruya cevap veriyor. Fonksiyonun ikinci parametresi, maksimum karakter uzunluğudur. – user3615395