AxDa.XamlDocConverter.Html 1.0.0

Prefix Reserved
Additional Details

Used project reference instead of package reference for AxDa.XamlDocConverter.Abstractions. This has been corrected in 1.0.1.

There is a newer version of this package available.
See the version list below for details.
dotnet add package AxDa.XamlDocConverter.Html --version 1.0.0
                    
NuGet\Install-Package AxDa.XamlDocConverter.Html -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="AxDa.XamlDocConverter.Html" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="AxDa.XamlDocConverter.Html" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="AxDa.XamlDocConverter.Html" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add AxDa.XamlDocConverter.Html --version 1.0.0
                    
#r "nuget: AxDa.XamlDocConverter.Html, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package AxDa.XamlDocConverter.Html@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=AxDa.XamlDocConverter.Html&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=AxDa.XamlDocConverter.Html&version=1.0.0
                    
Install as a Cake Tool

WPF Flow Document HTML Converter

WPF Flow Document HTML Converter provides high-performance, low-allocating conversion from WPF flow document content to HTML and vice-versa.

Easily convert WPF flow document text content specified by a Microsoft WPF TextRange object or a XAML stream to the HTML language format, and vice versa.

WPF Flow Document HTML Converter uses .NET capabilities. It provides powerful conversion options and empowers developers to use the HTML text format in WPF applications.

HtmlXamlDocConverter overview

WPF Flow Document HTML Converter provides extensive conversion capabilities for serializing Microsoft WPF flow document content content to HTML, and vice versa.

Conversion is versatile. WPF Flow Document HTML Converter not only accepts and generates HTML documents, but also HTML document fragments.

Following is a simple example, converting a HTML document fragment to WPF flow document content:

using System.IO;

using AxDa.XamlDocConverter.Html;

// prepare HTML input ...

string html =
@"<body>
  <h1>This is a heading.</h1>

  <table>
    <thead>
      <tr>
        <th>Column 1</th>
        <th>Column 2</th>
      </tr>
    </thead>

    <tbody>
      <tr>
        <th>Value 1</th>
        <th>Value 2</th>
      </tr>
    </tbody>
  </table>
</body>";

using MemoryStream htmlStream = new MemoryStream();
using MemoryStream xamlStream = new MemoryStream();

StreamWriter htmlWriter = new StreamWriter(htmlStream);
htmlWriter.Write(html);
htmlWriter.Flush();
htmlStream.Position = 0L;

// convert HTML to XAML ...

new HtmlXamlDocConverter().HtmlToXaml(htmlStream, xamlStream);

// output XAML ...

StreamReader xamlReader = new StreamReader(xamlStream);
xamlStream.Position = 0L;
string xaml = xamlReader.ReadToEnd();

The above code assigns the following result to the xaml string variable:

<?xml version="1.0" encoding="UTF-8"?>
<Section xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
  <Paragraph FontSize="24">
    <Run>This is a heading.</Run>
  </Paragraph>
  <Table>
    <TableRowGroup>
      <TableRow>
        <TableCell>
          <Paragraph>
            <Run>Column 1</Run>
          </Paragraph>
        </TableCell>
        <TableCell>
          <Paragraph>
            <Run>Column 2</Run>
          </Paragraph>
        </TableCell>
      </TableRow>
    </TableRowGroup>
    <TableRowGroup>
      <TableRow>
        <TableCell>
          <Paragraph>
            <Run>Value 1</Run>
          </Paragraph>
        </TableCell>
        <TableCell>
          <Paragraph>
            <Run>Value 2</Run>
          </Paragraph>
        </TableCell>
      </TableRow>
    </TableRowGroup>
  </Table>
</Section>

How to Use

Converting WPF Flow Document content to HTML content, or vice versa, is easy:

In a WPF application, convert WPF document content to HTML by retrieving the TextRange object from a Flow Document control and pass it to the HtmlXamlDocConverter.XamlToHtml() method, along with a destination Stream to receive the converted HTML content.

Conversely, to populate a WPF Flow Document control with rendered HTML content, provide the HtmlXamlDocConverter.HtmlToXaml() method with a source Stream containing HTML source code and the TextRange object from a Flow Document control to be populated.

Instead of a TextRange object, you can alternatively use a XAML stream, for example, from TextRange.Save().

Mapping HTML to WPF Flow Documents

The WPF flow document feature is designed to optimize text viewing and readability. Rather than being set to one predefined layout, flow documents dynamically adjust and reflow their content based on run-time variables such as window size, device resolution, and optional user preferences.

However, WPF Flow Documents do not support some features common to HTML. For example, heading, horizontal rule or quote block classes are missing from the System.Windows.Documents namespace.

To be able to convert these elements from HTML to WPF XAML, and vice versa, the HtmlXamlDocConverter class assumes a set of conventions for identifying XAML flow document elements as heading, horizontal rule, quotation block or code.

  • Heading

    A Paragraph element is identified as a heading element if the following conditions are met:

    1. The font size matches one of the font sizes defined in the HeadingSizes array property in XamlDocConverterOptions.
    Example

    Assuming that the font size array in XamlDocConverterOptions.HeadingSizes is equal to [24, 20, 18, 16, 15, 14, 13], then

    <Paragraph FontSize="24">
      <Run>This is heading level 1</Run>
    </Paragraph>
    <Paragraph FontSize="20">
      <Run>This is heading level 2</Run>
    </Paragraph>
    <Paragraph FontSize="18">
      <Run>This is heading level 3</Run>
    </Paragraph>
    <Paragraph FontSize="16">
      <Run>This is heading level 4</Run>
    </Paragraph>
    

    is converted to

    <h1>This is heading level 1</h1>
    <h2>This is heading level 2</h2>
    <h3>This is heading level 3</h3>
    <h4>This is heading level 4</h4>
    

    On the other hand, to have a paragraph with a specific font size not being recognized as a heading, set the paragraph's font size to any value other than the values defined in HtmlXamlDocConverterOptions.HeadingSizes.

    Example
    <Paragraph FontSize="24.001">
      <Run>This is not a heading</Run>
    </Paragraph>
    

    is converted to

    <p style="font-size: 24.001pt;">This is not a heading</p>
    
  • Horizontal Rule

    A Section element is identified as a horizontal rule element if the following conditions are met:

    1. It contains no child element
    2. It contains no text
    3. It has a top border – and only a border at the top – defined with the BorderBrush and BorderThickness properties set
    4. The thickness of the top border corresponds to the HorizontalLineThickness property defined in HtmlXamlDocConverterOptions. All other border thickness values must be 0.
    Example
    <Section BorderThickness="0, 3, 0 ,0" BorderBrush="Silver"></Section>
    

    is converted to

    <hr/>
    
  • Quote Block

    A Section element is identified as a quote block element if the following conditions are met:

    1. It has a left border – and only a border on the left side – defined with the BorderBrush and BorderThickness properties set
    2. The left border thickness corresponds to the BlockQuoteLineThickness property defined in HtmlXamlDocConverterOptions. All other border thickness values must be 0.
    Example
    <Section BorderThickness="3, 0, 0 ,0" BorderBrush="Silver">
      <Paragraph>
        <Run>“This is the truth”.</Run>
      </Paragraph>
    </Section>
    

    is converted to

    <blockquote>“This is the truth”.</blockquote>
    
  • Code Block

    A Section element is identified as a code block element if the following conditions are met:

    1. It is assigned a font family name that matches the font family name defined in the MonospaceFontName property of the HtmlXamlDocConverterOptions object.
    2. Optionally, a computer language acronym has been assigned to the Tag attribute.
    Example
    <Section FontFamily="Courier New" xml:space="preserve" Tag="c#">
      <Paragraph>
        <Run><![CDATA[int = 1;
    
    return i;]]></Run>
      </Paragraph>
    </Section>
    

    is converted to

    <pre class="language-c#">int = 1;
    
    return i;</pre>
    

    The computer language acronym is mapped to the resulting HTML element's language-* class, and vice versa. This enables JavaScript code syntax highlighters to recognize and colorize the corresponding section appropriately.

  • Inline Code

    A Run or Span element is identified as an inline code element if the following conditions are met:

    1. It is assigned a font family name that matches the font family name defined in the MonospaceFontName property of the HtmlXamlDocConverterOptions object.
    Example
    <Paragraph>
      <Run>The value is </Run>
      <Run FontFamily="Courier New" xml:space="preserve">true</Run>
      <Run>.</Run>
    </Paragraph>
    

    is converted to

    <p>The value is <code>true</code>.</p>
    

Implementation Details

HTML to XAML Flow Document Element Mapping

As explained above, XAML and HTML are similar in syntax but not in semantics. For example, HTML recognizes headings, while XAML flow documents do not.

To ensure acceptable yet comprehensive conversion, the HtmlXamlDocConverter class makes some style assumptions for element mapping.

The following table provides some technical details about these features:

<dl> <dt> Headings <h1> … <h7></dt> <dd><br/>

A HTML heading is mapped to a Paragraph object with a FontSize attribute that matches one of the values in the HtmlXamlDocConverterOptions.HeadingSizes array, and vice versa.

For example,

  • HtmlXamlDocConverterOptions.HeadingSizes[0] matches <h1>
  • HtmlXamlDocConverterOptions.HeadingSizes[3] matches <h4>

The font size value must match exactly when converting from XAML to HTML. If you want to use a Paragraph font size for decoration purposes but not for designating a heading, add a small fraction to either the corresponding Paragraph object's FontSize attribute or change the corresponding HtmlXamlDocConverterOptions.HeadingSizes value. Then they won't be equal anymore and the corresponding Paragraph object won't be interpreted as a heading.</dd>

<dt>Block Quote <blockquote></dt> <dd><br/>

A HTML block quote is mapped to a Section object with BorderBrush attribute set to an arbitrary value and left border thickness equals the HtmlXamlDocConverterOptions.BlockQuoteLineThickness property value while all other border thicknesses are equal to 0.

Example:

<Section BorderBrush="Silver" BorderThickness="3,0,0,0">

Section BorderBrush property value is taken from HtmlXamlDocConverterOptions.BlockQuoteLineColor when converting from HTML to XAML.

When converting from XAML to Html, the actual color value is ignored, yet the BorderBrush attribute must be present for the section being recognized as a block quote.

The Section BorderThickness property value must match exactly when converting from XAML to HTML. If you want to use a border for decoration purposes but not for designating a block quote, add a small fraction to either any value of the corresponding Section object's BorderThickness attribute or change the HtmlXamlDocConverterOptions.BlockQuoteLineThickness value. Then they won't be equal anymore and the corresponding Section object won't be interpreted as a block quote.</dd>

<dt>Horizontal Rule <hr></dt> <dd><br/>

A HTML horizontal rule is mapped to a Section object that does not contain content, the BorderBrush attribute is set to an arbitrary value and top border thickness equals the HtmlXamlDocConverterOptions.HorizontalLineThickness property value while all other border thicknesses are equal to 0.

Example:

<Section BorderBrush="Silver" BorderThickness="0,3,0,0"/>

Section BorderBrush property value is taken from HtmlXamlDocConverterOptions.HorizontalLineColor when converting from HTML to XAML.

When converting from XAML to HTML, the actual color value is ignored, yet the BorderBrush attribute must be present for the section being recognized as a horizontal rule.

The Section BorderThickness property value must match exactly when converting from XAML to HTML. If you want to use a border for decoration purposes but not for designating a horizontal rule, add a small fraction to either any value of the corresponding Section object's BorderThickness attribute or change the HtmlXamlDocConverterOptions.HorizontalLineThickness value. Then they won't be equal anymore and the corresponding Section object won't be interpreted as a horizontal rule.</dd>

<dt>Code Block <pre></dt> <dd><br/>

A HTML code block is mapped to a Section object with a FontFamily attribute set to a font matching Options.MonospaceFontName.

When converting from XAML to HTML, the font family name must match exactly the font name from the Options.MonospaceFontName property. Otherwise, the Section will become a <div> element with the font name applied as a CSS style rule.</dd>

<dt>Inline Code <code></dt> <dd><br/>

HTML inline code is mapped to a Run or Span object with a FontFamily attribute set to a font matching Options.MonospaceFontName.

When converting from XAML to HTML, the font family name must match exactly the font name from the Options.MonospaceFontName property. Otherwise, the Run or Span will become a <span> element with the font name applied as a CSS style rule.</dd> </dl>

Supported Elements

The following table lists all HTML elements that are supported:

HTML Element
body
li
p
span
br
b
i
u
a
table
thead
tbody
tfoot
tr
th
td

The following table lists all XAML elements that are supported:

XAML Element
Section
Paragraph
Span
Run
Bold
Italic
Underline
Hyperlink
Floater
LineBreak
ListItem
Table
TableRowGroup
TableRow
TableCell

Supported Text Attributes and Mappings

The following table lists all CSS rules and WPF attributes that are allowed and mapped to each other:

CSS Rule XAML Attribute
margin Margin
padding Padding
width Width
height Height
color Foreground
background-color Background
list-style-type MarkerStyle
font-family FontFamily
font-size FontSize
font-weight FontWeight
font-style FontStyle
font-width FontStretch
border-color BorderBrush
border-width BorderThickness
text-align TextAlignment
float HorizontalAlignment   (mapped to Floater element)
vertical-align VerticalAlignment
white-space xml:space

<br/>

The following table lists all HTML attributes and WPF attributes that are allowed and mapped to each other:

HTML Attribute XAML Attribute
id Name
href NavigateUri
class Tag   (Only if HTML class name begins with "language-". The text following the<br/>            dash is assigned to the XAML element's Tag attribute and vice versa.<br/>            This feature provides for code syntax highlighting.)
xml:lang xml:lang
lang xml:lang
xml:space xml:space

Remarks On Styles

The WPF Flow Document HTML Converter efficiently maps WPF XAML elements and attributes to HTML elements, attributes, and CSS rules, and vice versa.

The WPF Flow Document HTML Converter is text-based. It does not use a web browser to evaluate computed HTML element properties. Therefore, the converter only recognizes CSS styles applied directly to HTML elements. CSS classes, selectors, and stylesheets are ignored. The same applies to XAML, meaning styles and resources are ignored. Furthermore, property/style inheritance is not recognized in either XAML or HTML.

The properties of text elements in WPF flow documents and HTML CSS rules do not align. For example, compare WPF's device-independent units with CSS lengths, or the multitude of HTML elements with the limited number of elements in WPF flow documents. Due to the inherent differences between these two languages, it is impossible to convert a WPF flow document to HTML and vice versa without causing some discrepancies in appearance.

Only a limited number of HTML attributes and CSS rules are recognized and accepted for being mapped to WPF properties and vice versa. Any other HTML attributes, CSS rules, or XAML attributes unknown to this converter will throw a NotImplementedException. Set the HtmlTextRangeConverterOptions.IgnoreUnknownProperties property to true to optionally ignore unknown XAML element properties, HTML element attributes, and CSS rules.

The same applies to unsupported HTML elements and WPF classes. HTML elements and WPF classes unknown to the converter throw a NotImplementedException. You can define custom mappings for HTML elements and WPF classes unknown to the converter by adding individual element mappings to the HtmlTextRangeConverterOptions.AdditionalElementMapping collection. Your custom mappings are applied only to elements unknown to the converter. The built-in mapping cannot be overridden.

Options

WPF Flow Document HTML Converter provides a rich set of conversion options. You can configure conversion details using the following HtmlXamlDocConverterOptions properties:

<dl> <dt>HeadingSizes</dt> <dd>

Collection of XAML font sizes used to recognize a Paragraph element for being interpreted as the corresponding heading level in the target format.

The default values are: [24, 20, 18, 16, 15, 14, 13].</dd>

<dt>MonospaceFontName</dt> <dd>

Font name used to recognize Paragraph, Run or Span elements as being interpreted as code elements in the target format.

The default font family name is "Courier New".</dd>

<dt>BlockQuoteLineThickness</dt> <dd>

Left side border thickness used for recognizing a block quote.

The default value is 3.</dd>

<dt>BlockQuoteLineColor</dt> <dd>

Left border Color used for displaying a block quote.

The default value is Colors.Silver.</dd>

<dt>HorizontalLineThickness</dt> <dd>

Top border thickness used for recognizing a horizontal rule.

The default value is 3.</dd>

<dt>HorizontalLineColor</dt> <dd>

Top border Color used for displaying a horizontal rule.

The default value is Colors.Silver.</dd>

<dt>CssFontSizeUnit</dt> <dd>

CSS unit used for converting XAML font size attribute to HTML.

The default value is "pt".</dd>

<dt>CssThicknessUnit</dt> <dd>

CSS unit used for converting XAML margin, padding, width and height attributes to HTML.

The default value is "px".</dd>

<dt>CssBorderWidthUnit</dt> <dd>

CSS unit used for converting XAML border width attribute to HTML.

The default value is "px".</dd>

<dt>AdditionalElementMapping</dt> <dd>

Allows to add user defined mappings from source document element to target document element names.

Use this property for specifying custom mappings between additional HTML and WPF flow document elements not covered by this implementation.

To declare a custom element mapping to be used by a conversion, specify the element name from your source document as the key for the Dictionary{string, ElementInfo} and create a new ElementInfo object declaring the target element name and flow type.</dd>

<dt>IgnoreUnknownProperties</dt> <dd>

If true, unknown XAML properties and CSS styles in the source document are ignored.

The default value is false. Unknown XAML properties and CSS styles will throw NotImplementedException.</dd>

<dt>Indent</dt> <dd>

If true, output is prettified, i.e., new-lines and indentation will be added to each element. Set to false to not add white-space between elements.

The default value is true.</dd>

<dt>AsDocumentFragment</dt> <dd>

If true, the converted HTML tree will be a HTML document fragment, containing the converted elements only. If false, a full HTML document will be generated, with the child tree embedded within the HTML <body> element.

The default value is false.</dd>

<dt>LintXmlSpaceAttribute</dt> <dd>

Determines whether redundant xml:space attributes will be removed from the generated HTML document.

When converting a XAML document to HTML, existing xml:space attributes are transpiled into CSS white-space rules. However, when serializing the created HTML document, xml:space attributes are required for the serializer to correctly format the resulting HTML. This is particularly true for elements rendered with xml:space="preserve".

The xml:space attribute is ignored by HTML processors, so it's plain redundant if left in the resulting HTML document. Removing it from the resulting HTML comes with a performance penalty and additional memory requirements. So, you may want to opt-out of this linting step in order to improve performance and reduce the memory footprint of the conversion process.

The default value is true.</dd> </dl>

Known Issues

The current implementation of the Microsoft TextRange class (.NET ⇐ v10.0) does not allow for navigating through its child content (See WPF issue #10095). So, internally WPF Flow Document HTML Converter saves the TextRange content to a XAML stream using TextRange.Save() and the resulting XAML is taken as source for conversion. The TextRange.Save() method, however, does not save BlockUIContainer content. Thus, conversion is restricted to be text-only because image content cannot be gathered.

Feedback, Sponsorship and Contact

You may reach me on axeldahmen.de or LinkedIn

Product Compatible and additional computed target framework versions.
.NET net9.0-windows7.0 is compatible.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.5 154 5/27/2025
1.0.4 209 5/17/2025 1.0.4 is deprecated.
1.0.3 286 5/14/2025 1.0.3 is deprecated.
1.0.2 380 5/12/2025 1.0.2 is deprecated.
1.0.1 283 5/9/2025 1.0.1 is deprecated.
1.0.0 201 5/8/2025 1.0.0 is deprecated.