Converting between RTF and HTML
Have you ever had the desire to convert some RTF text into HTML or take HTML and generate a RTF document? Probably not. But if you did, then you are in luck! I recently had the need to do this conversion and after some searching found out a way to do it by enhancing a sample distributed in the MSDN library called: XAML to HTML Conversion Demo.
That sample has code which converts HTML to and from a XAML Flow Document. But this doesn’t make things easier until you realize that there is a way to convert RTF to XAML and XAML to RTF easily. The key is to use System.Windows.Controls.RichTextBox which can load RTF/XAML from a stream and save it as XAML/RTF.
RTF to XAML
C#
private static string ConvertRtfToXaml(string rtfText)
{
var richTextBox = new RichTextBox();
if (string.IsNullOrEmpty(rtfText)) return "";
var textRange = new TextRange(richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd);
using (var rtfMemoryStream = new MemoryStream())
{
using (var rtfStreamWriter = new StreamWriter(rtfMemoryStream))
{
rtfStreamWriter.Write(rtfText);
rtfStreamWriter.Flush();
rtfMemoryStream.Seek(0, SeekOrigin.Begin);
textRange.Load(rtfMemoryStream, DataFormats.Rtf);
}
}
using (var rtfMemoryStream = new MemoryStream())
{
textRange = new TextRange(richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd);
textRange.Save(rtfMemoryStream, DataFormats.Xaml);
rtfMemoryStream.Seek(0, SeekOrigin.Begin);
using (var rtfStreamReader = new StreamReader(rtfMemoryStream))
{
return rtfStreamReader.ReadToEnd();
}
}
}
XAML to RTF
C#
private static string ConvertXamlToRtf(string xamlText)
{
var richTextBox = new RichTextBox();
if (string.IsNullOrEmpty(xamlText)) return "";
var textRange = new TextRange(richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd);
using (var xamlMemoryStream = new MemoryStream())
{
using (var xamlStreamWriter = new StreamWriter(xamlMemoryStream))
{
xamlStreamWriter.Write(xamlText);
xamlStreamWriter.Flush();
xamlMemoryStream.Seek(0, SeekOrigin.Begin);
textRange.Load(xamlMemoryStream, DataFormats.Xaml);
}
}
using (var rtfMemoryStream = new MemoryStream())
{
textRange = new TextRange(richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd);
textRange.Save(rtfMemoryStream, DataFormats.Rtf);
rtfMemoryStream.Seek(0, SeekOrigin.Begin);
using (var rtfStreamReader = new StreamReader(rtfMemoryStream))
{
return rtfStreamReader.ReadToEnd();
}
}
}
With this code we have all we need to convert RTF to HTML and HTML to RTF. I modified the MSDN library sample to add this RTF/XAML to XAML/RTF conversion and then I either run that XAML through HTML converter which results in the HTML text or I run the HTML through the XAML converter and generate XAML text. I added an interface for these conversion utilities and converted the sample into a library so that I would be able to use it from other projects. Here is the interface:
C#
public interface IMarkupConverter
{
string ConvertXamlToHtml(string xamlText);
string ConvertHtmlToXaml(string htmlText);
string ConvertRtfToHtml(string rtfText);
string ConvertHtmlToRtf(string htmlText);
}
public class MarkupConverter : IMarkupConverter
{
public string ConvertXamlToHtml(string xamlText)
{
return HtmlFromXamlConverter.ConvertXamlToHtml(xamlText, false);
}
public string ConvertHtmlToXaml(string htmlText)
{
return HtmlToXamlConverter.ConvertHtmlToXaml(htmlText, true);
}
public string ConvertRtfToHtml(string rtfText)
{
return RtfToHtmlConverter.ConvertRtfToHtml(rtfText);
}
public string ConvertHtmlToRtf(string htmlText)
{
return HtmlToRtfConverter.ConvertHtmlToRtf(htmlText);
}
}
With this I am now able to convert from RTF to HTML and from HTML to RTF. However, there is one catch – the conversion uses the RichTextBox WPF control which requires a single threaded apartment (STA). Therefore in order to run your code that calls the ConvertRtfToHtml or ConvertHtmlToRtf functions, they must also be running in a STA. If you can’t have your program run in a STA (for example: when running an ASP .NET website) then you must create a new STA thread to run the conversion. Like this:
C#
MarkupConverter markupConverter = new MarkupConverter();
private string ConvertRtfToHtml(string rtfText)
{
var thread = new Thread(ConvertRtfInSTAThread);
var threadData = new ConvertRtfThreadData { RtfText = rtfText };
thread.SetApartmentState(ApartmentState.STA);
thread.Start(threadData);
thread.Join();
return threadData.HtmlText;
}
private void ConvertRtfInSTAThread(object rtf)
{
var threadData = rtf as ConvertRtfThreadData;
threadData.HtmlText = markupConverter.ConvertRtfToHtml(threadData.RtfText);
}
bjdkfp1688.bandcamp.com
nndkfp1688.bandcamp.com
private class ConvertRtfThreadData
{
public string RtfText { get; set; }
public string HtmlText { get; set; }
}
That is all there is too it! Hopefully, this will come in handy for anyone needing to perform this conversion.