Как сохранить разрывы строк при использовании jsoup для преобразования html в обычный текст? - PullRequest
94 голосов
/ 12 апреля 2011

У меня есть следующий код:

 public class NewClass {
     public String noTags(String str){
         return Jsoup.parse(str).text();
     }


     public static void main(String args[]) {
         String strings="<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN \">" +
         "<HTML> <HEAD> <TITLE></TITLE> <style>body{ font-size: 12px;font-family: verdana, arial, helvetica, sans-serif;}</style> </HEAD> <BODY><p><b>hello world</b></p><p><br><b>yo</b> <a href=\"http://google.com\">googlez</a></p></BODY> </HTML> ";

         NewClass text = new NewClass();
         System.out.println((text.noTags(strings)));
}

И у меня есть результат:

hello world yo googlez

Но я хочу нарушить черту:

hello world
yo googlez

Я посмотрел на TextNode # jsoup getWholeText () , но не могу понять, как его использовать.

Если в разметке, которую я анализирую, есть <br>, как я могу получить разрыв строки в полученном результате?

Ответы [ 15 ]

90 голосов
/ 26 октября 2013

Реальное решение, которое сохраняет разрывы строк, должно выглядеть следующим образом:

public static String br2nl(String html) {
    if(html==null)
        return html;
    Document document = Jsoup.parse(html);
    document.outputSettings(new Document.OutputSettings().prettyPrint(false));//makes html() preserve linebreaks and spacing
    document.select("br").append("\\n");
    document.select("p").prepend("\\n\\n");
    String s = document.html().replaceAll("\\\\n", "\n");
    return Jsoup.clean(s, "", Whitelist.none(), new Document.OutputSettings().prettyPrint(false));
}

Он удовлетворяет следующим требованиям:

  1. если исходный HTML содержит символ новой строки (\ n), он сохраняется
  2. если исходный HTML-файл содержит теги br или p, они переводятся на новую строку (\ n).
43 голосов
/ 23 апреля 2013
Jsoup.clean(unsafeString, "", Whitelist.none(), new OutputSettings().prettyPrint(false));

Мы используем этот метод здесь:

public static String clean(String bodyHtml,
                       String baseUri,
                       Whitelist whitelist,
                       Document.OutputSettings outputSettings)

Передавая Whitelist.none(), мы гарантируем, что весь HTML удален.

Проходя new OutputSettings().prettyPrint(false) мыубедитесь, что выходные данные не переформатированы, а разрывы строк сохранены.

42 голосов
/ 17 мая 2011

С

Jsoup.parse("A\nB").text();

у вас есть вывод

"A B" 

, а не

A

B

Для этого я использую:

descrizione = Jsoup.parse(html.replaceAll("(?i)<br[^>]*>", "br2n")).text();
text = descrizione.replaceAll("br2n", "\n");
23 голосов
/ 24 июня 2013

Попробуйте это с помощью jsoup:

public static String cleanPreserveLineBreaks(String bodyHtml) {

    // get pretty printed html with preserved br and p tags
    String prettyPrintedBodyFragment = Jsoup.clean(bodyHtml, "", Whitelist.none().addTags("br", "p"), new OutputSettings().prettyPrint(true));
    // get plain text with preserved line breaks by disabled prettyPrint
    return Jsoup.clean(prettyPrintedBodyFragment, "", Whitelist.none(), new OutputSettings().prettyPrint(false));
}
6 голосов
/ 01 августа 2013

Вы можете пройти данный элемент

public String convertNodeToText(Element element)
{
    final StringBuilder buffer = new StringBuilder();

    new NodeTraversor(new NodeVisitor() {
        boolean isNewline = true;

        @Override
        public void head(Node node, int depth) {
            if (node instanceof TextNode) {
                TextNode textNode = (TextNode) node;
                String text = textNode.text().replace('\u00A0', ' ').trim();                    
                if(!text.isEmpty())
                {                        
                    buffer.append(text);
                    isNewline = false;
                }
            } else if (node instanceof Element) {
                Element element = (Element) node;
                if (!isNewline)
                {
                    if((element.isBlock() || element.tagName().equals("br")))
                    {
                        buffer.append("\n");
                        isNewline = true;
                    }
                }
            }                
        }

        @Override
        public void tail(Node node, int depth) {                
        }                        
    }).traverse(element);        

    return buffer.toString();               
}

И для своего кода

String result = convertNodeToText(JSoup.parse(html))
5 голосов
/ 17 мая 2018

В Jsoup v1.11.2 теперь мы можем использовать Element.wholeText().

Пример кода:

String cleanString = Jsoup.parse(htmlString).wholeText();

user121196's ответ все еще работает. Но wholeText() сохраняет выравнивание текстов.

4 голосов
/ 24 июля 2014
text = Jsoup.parse(html.replaceAll("(?i)<br[^>]*>", "br2n")).text();
text = descrizione.replaceAll("br2n", "\n");

работает, если сам HTML не содержит "br2n"

Итак,

.
<code>text = Jsoup.parse(html.replaceAll("(?i)<br[^>]*>", "<pre>\n
")) Текст ();

работает надежнее и проще.

3 голосов
/ 21 сентября 2017

Для более сложного HTML ни одно из вышеперечисленных решений не сработало; Мне удалось успешно выполнить преобразование, сохранив разрывы строк с помощью:

Document document = Jsoup.parse(myHtml);
String text = new HtmlToPlainText().getPlainText(document);

(версия 1.10.3)

3 голосов
/ 08 сентября 2017

Попробуйте это с помощью jsoup:

    doc.outputSettings(new OutputSettings().prettyPrint(false));

    //select all <br> tags and append \n after that
    doc.select("br").after("\\n");

    //select all <p> tags and prepend \n before that
    doc.select("p").before("\\n");

    //get the HTML from the document, and retaining original new lines
    String str = doc.html().replaceAll("\\\\n", "\n");
3 голосов
/ 05 июня 2016

Это моя версия перевода html в текст (на самом деле измененная версия ответа user121196).

Это не только сохраняет разрывы строк, но также форматирует текст и удаляет лишние разрывы строк, экранирующие символы HTML, и вы получите намного лучший результат из своего HTML (в моем случае я получаю его отmail).

Первоначально он написан на Scala, но вы можете легко изменить его на Java

def html2text( rawHtml : String ) : String = {

    val htmlDoc = Jsoup.parseBodyFragment( rawHtml, "/" )
    htmlDoc.select("br").append("\\nl")
    htmlDoc.select("div").append("\\nl")
    htmlDoc.select("p").prepend("\\nl\\nl")
    htmlDoc.select("p").append("\\nl\\nl")

    org.jsoup.parser.Parser.unescapeEntities(
        Jsoup.clean(
          htmlDoc.html(),
          "",
          Whitelist.none(),
          new org.jsoup.nodes.Document.OutputSettings().prettyPrint(true)
        ),false
    ).
    replaceAll("\\\\nl", "\n").
    replaceAll("\r","").
    replaceAll("\n\\s+\n","\n").
    replaceAll("\n\n+","\n\n").     
    trim()      
}
...