You have RTF — from a database column, a rich-text editor, an older document system or an email gateway — and your Java application needs HTML. Most teams try one of three things first: Swing’s RTFEditorKit, which ships with the JDK; LibreOffice in headless mode, usually driven by JODConverter; or a dedicated converter library such as ScroogeXHTML. We ran the same RTF files through all three and compared the results.

How we tested

We used 11 files. Eight come from our own regression tests: character formatting, bullet and numbered lists, tables, nested tables, embedded pictures, Japanese text, a list document saved by Word, and our 466 KB Getting Started guide. Three are hostile: 4,000 levels of nested groups, a font name that tries to inject CSS, and a hyperlink with a javascript: target.

The tools:

  • Swing: Java 17, with RTFEditorKit reading the RTF and HTMLEditorKit writing the HTML.
  • LibreOffice 26.8: from the command line (soffice --headless --convert-to html).
  • ScroogeXHTML 11.5: with its default settings, which now include tables and hyperlinks, plus picture embedding switched on.

Results

Swing RTFEditorKitLibreOffice (headless)ScroogeXHTML
TablesLost; cell text runs togetherYes, including nested tablesYes; nested tables through an option
ListsBullets and numbers kept as plain text, no list markupYesYes
HyperlinksLost, including the link textYesYes
Embedded picturesDroppedWritten as separate image filesEmbedded as data URIs (Pictures add-on, experimental)
Japanese textCorrectCorrectCorrect
javascript: linkText lostWritten out unchangedLink removed, text kept, warning logged
MarkupDated, with a <span> for every run of textHTML5 doctype, but <font> tagsHTML5 or XHTML with CSS
Time per documentMillisecondsAbout 1.4 s per command-line callMilliseconds
FootprintPart of the JDKAbout 900 MB install, plus office processesJar under 200 KB, plus SLF4J

Swing RTFEditorKit: free, fast, and flat

It’s already in the JDK, it’s fast, and it handled our hostile files without trouble. But everything beyond formatted paragraphs is gone: no tables, no list markup, no pictures, no links. Worse, it dropped the visible text of hyperlinks, so readers see missing words, not just missing formatting. It’s a good fit for short formatted text, such as notes or comment fields.

LibreOffice and JODConverter: high fidelity, heavy machinery

LibreOffice gave the most faithful result in our test: nested tables, numbered lists with the right start values, and all hyperlinks. It also reads DOC, DOCX and ODT, which matters if RTF isn’t your only format. And it’s free: LibreOffice is licensed under MPL 2.0 and JODConverter under Apache 2.0.

The cost is operational. Every server or container needs a LibreOffice installation (about 900 MB on our Windows test machine), plus office processes that someone has to start, pool and restart. A command-line conversion took about 1.4 seconds. JODConverter keeps the process running, so it’s faster than that, but the conversion still happens outside your application.

The HTML is dated, too:

  • it uses <font> tags;
  • it writes pictures as separate files that you have to store and serve;
  • in our test it took the document language from the server’s locale.

For untrusted input, plan a sandbox. LibreOffice wrote our javascript: link into the HTML unchanged, which is cross-site scripting as soon as the page is shown in a browser. And a full office suite is a large attack surface: LibreOffice has announced 22 security advisories in 2026 so far.

ScroogeXHTML: RTF to HTML, and nothing else

ScroogeXHTML does one job. The library is a single jar under 200 KB with one dependency (SLF4J). It runs inside your application and converts a document in milliseconds. Since 11.5, tables and hyperlinks are converted by default:

ScroogeXHTML converter = new ScroogeXHTML();
converter.setAddOuterHTML(true);      // write a complete HTML document
String html = converter.convert(rtf); // tables and hyperlinks included

Security is part of the design:

  • links are only written for http, https and mailto targets;
  • CSS values taken from the document are sanitized;
  • resource limits stop hostile input.

In our test it removed the javascript: link but kept its text, dropped the CSS injection attempt, and rejected the 4,000-level file with a clear exception. The details are in SECURITY.md, which ships with the library.

What it doesn’t do: it reads RTF only, not DOCX or ODT. It supports a subset of RTF, listed in the feature matrix. Nested tables are switched off by default, footnotes are dropped by default (including links inside them), and embedding pictures as data URIs is experimental. And it’s a commercial library, licensed per developer.

Which one should you use?

  • Short formatted text, no tables or links: RTFEditorKit is enough.
  • Many document formats, the highest fidelity, trusted documents, and a team that can run office processes: LibreOffice with JODConverter.
  • RTF that ends up in your web pages, possibly from untrusted users, converted by a lightweight Java service: ScroogeXHTML.

Try it with your own documents

The online demo on scroogexhtml.com converts an uploaded RTF file of up to 1 MB and shows the result. Maybe your documents can’t leave your network, or you want to try the API in your own code. Then request a free 30-day evaluation of the Jar Edition, through the link in the download section. It’s the normal library, without watermarks or functional restrictions, for business customers and for evaluation only.

Please note

These results come from our own test files on one Windows machine. Your documents may give different results, and the timings are orders of magnitude, not benchmarks. LibreOffice is a registered trademark of The Document Foundation. Java is a registered trademark of Oracle and/or its affiliates.

Visited 8 times, 1 visit(s) today