From ab182c4b63fd52c67692ade92cff43461f0b9587 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Tue, 1 Nov 2016 12:01:21 +0100 Subject: Replace jsoup's example html to plain text parser with adaptation thereof --- .../core/util/syndication/HtmlToPlainText.java | 89 ++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/util/syndication/HtmlToPlainText.java (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/syndication/HtmlToPlainText.java b/core/src/main/java/de/danoeh/antennapod/core/util/syndication/HtmlToPlainText.java new file mode 100644 index 000000000..bd40f398d --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/util/syndication/HtmlToPlainText.java @@ -0,0 +1,89 @@ +package de.danoeh.antennapod.core.util.syndication; + +import org.jsoup.helper.StringUtil; +import org.jsoup.nodes.Element; +import org.jsoup.nodes.Node; +import org.jsoup.nodes.TextNode; +import org.jsoup.select.NodeTraversor; +import org.jsoup.select.NodeVisitor; + +/** + * This class is based on HtmlToPlainText from jsoup's examples package. + * + * HTML to plain-text. This example program demonstrates the use of jsoup to convert HTML input to lightly-formatted + * plain-text. That is divergent from the general goal of jsoup's .text() methods, which is to get clean data from a + * scrape. + *

+ * Note that this is a fairly simplistic formatter -- for real world use you'll want to embrace and extend. + *

+ *

+ * To invoke from the command line, assuming you've downloaded the jsoup jar to your current directory:

+ *

java -cp jsoup.jar org.jsoup.examples.HtmlToPlainText url [selector]

+ * where url is the URL to fetch, and selector is an optional CSS selector. + * + * @author Jonathan Hedley, jonathan@hedley.net + * @author AntennaPod open source community + */ +public class HtmlToPlainText { + + /** + * Format an Element to plain-text + * @param element the root element to format + * @return formatted text + */ + public String getPlainText(Element element) { + FormattingVisitor formatter = new FormattingVisitor(); + NodeTraversor traversor = new NodeTraversor(formatter); + traversor.traverse(element); // walk the DOM, and call .head() and .tail() for each node + + return formatter.toString(); + } + + // the formatting rules, implemented in a breadth-first DOM traverse + private class FormattingVisitor implements NodeVisitor { + + private StringBuilder accum = new StringBuilder(); // holds the accumulated text + + // hit when the node is first seen + public void head(Node node, int depth) { + String name = node.nodeName(); + if (node instanceof TextNode) { + append(((TextNode) node).text()); // TextNodes carry all user-readable text in the DOM. + } + else if (name.equals("li")) { + append("\n * "); + } + else if (name.equals("dt")) { + append(" "); + } + else if (StringUtil.in(name, "p", "h1", "h2", "h3", "h4", "h5", "tr")) { + append("\n"); + } + } + + // hit when all of the node's children (if any) have been visited + public void tail(Node node, int depth) { + String name = node.nodeName(); + if (StringUtil.in(name, "br", "dd", "dt", "p", "h1", "h2", "h3", "h4", "h5")) { + append("\n"); + } else if (name.equals("a")) { + append(String.format(" <%s>", node.absUrl("href"))); + } + } + + // appends text to the string builder with a simple word wrap method + private void append(String text) { + if (text.equals(" ") && + (accum.length() == 0 || StringUtil.in(accum.substring(accum.length() - 1), " ", "\n"))) { + return; // don't accumulate long runs of empty spaces + } + + accum.append(text); + } + + @Override + public String toString() { + return accum.toString(); + } + } +} -- cgit v1.2.3