gpt4 book ai didi

C# FlowDocument 到 HTML 的转换

转载 作者:太空狗 更新时间:2023-10-29 20:03:37 25 4
gpt4 key购买 nike

基本上,我有一个 RichTextBox,我想将它的格式化内容转换为 HTML,以便它可以作为电子邮件发送。

我目前使用的方法根本没有给出任何格式:

string message = new TextRange(messageTextBox.Document.ContentStart,
messageTextBox.Document.ContentEnd).Text;

于是我四处寻找,找到了this ,但是,它已经超过 5 年了,在评论中,一位 MSFT 用户评论说它不再受支持 - “此示例已从我们的示例集中删除,不再受支持”,并且它生成的 HTML 格式比现代 HTML 或 XHTML 更旧,如果有的话会更好。

谁能告诉我如何将 RichTextBox 的格式化内容转换为 HTML?

(因此,当电子邮件发送给收件人时,收件人会看到带有格式的电子邮件)

最佳答案

一般技术是使用 XamlWriterFlowDocument 内容转换为 XML 流,然后使用 XSLT 转换将 XML 转换为 HTML。这不是一个很好的答案,但那是因为任何给定的 FlowDocument 都有大量可能的 HTML 表示形式。

例如,此转换将每个顶级 Section 转换为 div,将每个 Paragraph 转换为 p,以及每一个 Run 到一个 span,它的类告诉你它是斜体、粗体、下划线,还是以上的任意组合。它对我编写它的目的很有用,但将其称为有损转换是一种轻描淡写的说法:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="msxsl x">

<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>

<xsl:template match="x:Section[not(parent::x:Section)]">
<div>
<xsl:apply-templates select="node()"/>
</div>
</xsl:template>

<xsl:template match="x:Section">
<xsl:apply-templates select="node()"/>
</xsl:template>

<xsl:template match="x:Paragraph">
<p>
<xsl:apply-templates select="node()"/>
</p>
</xsl:template>

<xsl:template match="x:Run">
<xsl:variable name="class">
<xsl:if test="@FontStyle='Italic'">
<xsl:text>i </xsl:text>
</xsl:if>
<xsl:if test="@FontWeight='Bold'">
<xsl:text>b </xsl:text>
</xsl:if>
<xsl:if test="contains(@TextDecorations, 'Underline')">
<xsl:text>u </xsl:text>
</xsl:if>
</xsl:variable>
<span>
<xsl:if test="normalize-space($class) != ''">
<xsl:attribute name="class">
<xsl:value-of select="normalize-space($class)"/>
</xsl:attribute>
</xsl:if>
<xsl:value-of select="text()"/>
</span>
</xsl:template>

</xsl:stylesheet>

这是我编写的用于进行转换的值转换器 - 请注意,为了使用值转换器,您还必须四处寻找并实现一个将内容公开为依赖项的 RichTextBox 版本属性(property)。整个项目真的很痛苦。

public class FlowDocumentToHtmlConverter : IValueConverter
{
private static XslCompiledTransform ToHtmlTransform;
private static XslCompiledTransform ToXamlTransform;

public FlowDocumentToHtmlConverter()
{
if (ToHtmlTransform == null)
{
ToHtmlTransform = LoadTransformResource("Converters/FlowDocumentToXhtml.xslt");
}
if (ToXamlTransform == null)
{
ToXamlTransform = LoadTransformResource("Converters/XhtmlToFlowDocument.xslt");
}
}
private static XslCompiledTransform LoadTransformResource(string path)
{
Uri uri = new Uri(path, UriKind.Relative);
XmlReader xr = XmlReader.Create(Application.GetResourceStream(uri).Stream);
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(xr);
return xslt;
}

#region IValueConverter Members

public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (!(value is FlowDocument))
{
return null;
}
if (targetType == typeof(FlowDocument))
{
return value;
}

if (targetType != typeof(string))
{
throw new InvalidOperationException(
"FlowDocumentToHtmlConverter can only convert back from a FlowDocument to a string.");
}

FlowDocument d = (FlowDocument)value;

using (MemoryStream ms = new MemoryStream())
{
// write XAML out to a MemoryStream
TextRange tr = new TextRange(
d.ContentStart,
d.ContentEnd);
tr.Save(ms, DataFormats.Xaml);
ms.Seek(0, SeekOrigin.Begin);

// transform the contents of the MemoryStream to HTML
StringBuilder sb = new StringBuilder();
using (StringWriter sw = new StringWriter(sb))
{
XmlWriterSettings xws = new XmlWriterSettings();
xws.OmitXmlDeclaration = true;
XmlReader xr = XmlReader.Create(ms);
XmlWriter xw = XmlWriter.Create(sw, xws);
ToHtmlTransform.Transform(xr, xw);
}
return sb.ToString();
}
}

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value == null)
{
return new FlowDocument();
}
if (value is FlowDocument)
{
return value;
}
if (targetType != typeof(FlowDocument))
{
throw new InvalidOperationException(
"FlowDocumentToHtmlConverter can only convert to a FlowDocument.");
}
if (!(value is string))
{
throw new InvalidOperationException(
"FlowDocumentToHtmlConverter can only convert from a string or FlowDocument.");
}

string s = (string)value;

FlowDocument d;

using (MemoryStream ms = new MemoryStream())
using (StringReader sr = new StringReader(s))
{
XmlWriterSettings xws = new XmlWriterSettings();
xws.OmitXmlDeclaration = true;
using (XmlReader xr = XmlReader.Create(sr))
using (XmlWriter xw = XmlWriter.Create(ms, xws))
{
ToXamlTransform.Transform(xr, xw);
}
ms.Seek(0, SeekOrigin.Begin);

d = XamlReader.Load(ms) as FlowDocument;
}
XamlWriter.Save(d, Console.Out);
return d;
}

#endregion
}

关于C# FlowDocument 到 HTML 的转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6236483/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com