DocxportNet 1.2.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package DocxportNet --version 1.2.0
                    
NuGet\Install-Package DocxportNet -Version 1.2.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="DocxportNet" Version="1.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="DocxportNet" Version="1.2.0" />
                    
Directory.Packages.props
<PackageReference Include="DocxportNet" />
                    
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 DocxportNet --version 1.2.0
                    
#r "nuget: DocxportNet, 1.2.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 DocxportNet@1.2.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=DocxportNet&version=1.2.0
                    
Install as a Cake Addin
#tool nuget:?package=DocxportNet&version=1.2.0
                    
Install as a Cake Tool

NuGet Version Build & Tests

Docxport.Net

Docxport.Net is a .NET library for walking DOCX documents and exporting them to friendly formats. Today it focuses on Markdown (rich and plain), with full handling of:

  • Tracked changes (accept/reject/inline views)
  • Lists with proper markers and indentation
  • Tables (including merged cells / spans)
  • Comments and threaded replies
  • Headers and footers
  • Images/drawings
  • Bookmarks, hyperlinks, fields, and more

Support overview

Output formats

  • Markdown (rich + plain)
  • HTML (rich + plain)
  • Plain text

Document features

  • Tracked changes: accept/reject/inline/split modes
  • Comments: threads + replies
  • Lists: markers + indentation
  • Tables: cell spanning (row/col), borders/background/vertical-align (incl. tblStyle presets; theme colors/advanced border patterns are limited)
  • Headers/footers, bookmarks, hyperlinks, fields
  • Images/drawings (best-effort)

Why this exists

Most DOCX “save as text” pipelines lose important fidelity: strikethroughs and deletions disappear, list markers collapse to bullets or vanish (pandoc), comments/track changes are missing, images are dropped, and tools like LibreOffice/Interop require UI or platform-specific installs. Docxport.Net walks the OOXML directly, headlessly, and emits Markdown/HTML/plain text while preserving tracked changes, comments, list markers, images, headers/footers, and other semantics.

Quick start: DOCX → Markdown

Command line

# Option A: Install the CLI as a .NET tool (recommended)
dotnet tool install -g DocxportNet.Cli
docxport my-doc.docx -o my-doc.md --tracked=accept

# Option B: Download a self-contained binary from GitHub Releases
# (pick your OS/arch zip, extract it, then run):
./docxport my-doc.docx -o my-doc.md --tracked=accept

# From source (development):
git clone https://github.com/gaspardpetit/Docxport.Net.git
dotnet run --project DocxportNet.Cli -- my-doc.docx -o my-doc.md --tracked=accept

NuGet + code

Install: dotnet add package DocxportNet

using DocxportNet;
using DocxportNet.Visitors.Markdown;

string docxPath = "my-doc.docx";
var visitor = new DxpMarkdownVisitor(DxpMarkdownVisitorConfig.RICH);
string markdown = DxpExport.ExportToString(docxPath, visitor);

File.WriteAllText(Path.ChangeExtension(docxPath, ".md"), markdown);

Tracked changes

Visitors can emit different views of tracked changes:

  • Accept changes (default): DxpTrackedChangeMode.AcceptChanges
  • Reject changes: DxpTrackedChangeMode.RejectChanges
  • Inline markup (insert/delete): DxpTrackedChangeMode.InlineChanges
  • Split accept/reject panes: DxpTrackedChangeMode.SplitChanges

Pick the mode on the visitor config, e.g.:

var config = DxpMarkdownVisitorConfig.RICH with { TrackedChangeMode = DxpTrackedChangeMode.RejectChanges };
var rejectVisitor = new DxpMarkdownVisitor(config);
string rejected = DxpExport.ExportToString(docxPath, rejectVisitor);

Visitors and options

Markdown

  • Presets: DxpMarkdownVisitorConfig.CreateRichConfig() (styled) and CreatePlainConfig() (minimal).
  • Options cover images, inline styling, rich tables, comments formatting, custom properties, and tracked change mode.

HTML

  • Preset: DxpHtmlVisitorConfig.CreateRichConfig() (styled) and CreatePlainConfig() (minimal).
  • Options cover inline styles, colors/backgrounds, table borders, document colors, headers/footers, comments mode, custom properties, timeline, and tracked change mode.

Plain text

  • Presets: DxpPlainTextVisitorConfig.CreateAcceptConfig() and CreateRejectConfig() (choose tracked change handling).
  • Focused on readable text output with list markers, comments, and basic structure.

DxpExport has overloads for DOCX file paths, in-memory bytes, or an already-open WordprocessingDocument, and can return a string, a byte[], write straight to a file path, or just drive a visitor that collects data.

CLI

A ready-to-use console app lives in DocxportNet.Cli and is published as a .NET tool. Example:

dotnet tool install -g DocxportNet.Cli
docxport my.docx -o my.md --tracked=accept

Self-contained binaries for Windows/Linux/macOS are also published on GitHub Releases.

dotnet run --project DocxportNet.Cli -- my.docx -o my.md --tracked=accept
# or, using a self-contained binary:
./docxport my.docx --format=html --tracked=inline

Options: --format=markdown|html|text, --tracked=accept|reject|inline|split (text uses accept/reject), --plain (plain markdown), -o, --output=path (infers format from extension when --format is omitted).

Custom visitors

You can write your own DxpIVisitor to extract specific content. Example: collect all comments.

using DocxportNet.API;
using DocxportNet.Visitors;
using DocumentFormat.OpenXml.Wordprocessing;

public sealed class CommentCollector : DxpVisitor
{
	public List<(string Author, string Text)> Comments { get; } = new();

	public override void VisitComment(Comment c, DxpIDocumentContext d)
	{
		Comments.Add((c.Author?.Value ?? "Unknown", c.InnerText));
	}
}

var collector = new CommentCollector();
DxpExport.Export("my-doc.docx", collector);
foreach (var (author, text) in collector.Comments)
	Console.WriteLine($"{author}: {text}");

It also ships a small utility that translates legacy “symbol fonts” (Symbol, Zapf Dingbats, Webdings, Wingdings) into modern Unicode.

Field evaluation

Docxport.Net ships a standalone field evaluator for Word field codes. It can be used on its own or alongside the walker/exporter. For the exact language and field specifications, see docs/word-fields.md.

High‑level support includes:

  • Core built‑ins: DATE/TIME/CREATEDATE/SAVEDATE/PRINTDATE, SET/REF, DOCPROPERTY/DOCVARIABLE, MERGEFIELD, SEQ, IF/COMPARE/NEXTIF/SKIPIF, ASK
  • Formulas: arithmetic, comparisons, functions (SUM/AVERAGE/etc.), nested fields, table cell references (via a resolver)
  • Formatting switches: \* text transforms, \# numeric pictures, \@ date/time pictures
  • Locale‑aware formatting and list‑separator handling
  • Number‑to‑words languages: English, French, German, Spanish, Italian, Portuguese, Danish, Japanese, Thai, Chinese (Simplified)

Minimal setup (standalone):

using DocxportNet.Fields;

var eval = new DxpFieldEval();
eval.Context.SetBookmark("Total", "123.45");
eval.Context.SetDocumentPropertyValue("Title", new DxpFieldValue("My Doc"));

var date = await eval.EvalAsync(new DxpFieldInstruction("DATE \\@ \"yyyy-MM-dd\""));
var cond = await eval.EvalAsync(new DxpFieldInstruction("IF Total > 100 \"Big\" \"Small\""));
var formula = await eval.EvalAsync(new DxpFieldInstruction("= Total * 2 \\# \"$#,##0.00\""));
var title = await eval.EvalAsync(new DxpFieldInstruction("DOCPROPERTY Title \\* Upper"));

// date.Text    -> "2026-02-07" (uses default NowProvider)
// cond.Text    -> "Big"
// formula.Text -> "$246.90"
// title.Text   -> "MY DOC"

Minimal setup (with exporter + middleware):

using DocxportNet;
using DocxportNet.Fields;
using DocxportNet.Visitors.PlainText;

var visitor = new DxpPlainTextVisitor(DxpPlainTextVisitorConfig.CreateAcceptConfig());
// DxpExport wraps the visitor with field-eval middleware automatically.
string text = DxpExport.ExportToString("my-doc.docx", visitor);

Providing DOCVARIABLEs:

using DocxportNet.Fields;

var eval = new DxpFieldEval();
eval.Context.SetDocVariable("ClientName", "Contoso Ltd.");

var result = await eval.EvalAsync(new DxpFieldInstruction("DOCVARIABLE ClientName \\* Upper"));
// result.Text -> "CONTOSO LTD."

If you need dynamic resolution (DB/HTTP/etc.), register a resolver on the context instead of pre‑seeding values.

Gaps and contributions welcome

Area Current gap
List markers Word supports exotic textual markers (“forty-two” in various languages); current formatter covers numeric/roman/alpha and supports text‑number formats via the shared number‑to‑words registry, but not every Word numbering style.
Shapes/SmartArt Complex shapes/SmartArt/OLE rely on preview images if present; true vector or OLE rendering is not implemented.
Charts Charts are emitted via available previews or placeholders; data-driven re-rendering is not implemented.
Math/Fields Field evaluation exists, but complex math/field result rendering in exporters isn’t deeply covered by fixtures.
Tables (complex) Table styles are partially supported (borders/background/vertical align, incl. tblStyle presets), but theme color resolution and advanced border patterns are still limited; nested/edge-case tables beyond supplied samples may need additional handling.

Contributions that improve any of these areas are very welcome.

Supported symbol fonts

Symbols typically used in list markers are automatically converted to their unicode equivalent. Supported fonts include:

  • Symbol
  • Zapf Dingbats
  • Webdings
  • Wingdings
  • Wingdings 2
  • Wingdings 3

Symbol font to Unicode

Use DxpFontSymbols when you encounter text that was encoded with a symbol font and you want plain Unicode output.

// Convert a whole string using the font hint.
// 0x41 ('A') -> ✌, 0x42 ('B') -> 👌 in the Wingdings table.
string text = DxpFontSymbols.Substitute("Wingdings", "\u0041\u0042"); // => "✌👌"
// Convert a single character; falls back to the original if unmapped
string bullet = DxpFontSymbols.Substitute("Symbol", (char)0xB7); // → "•"

Unknown characters are returned unchanged. You can optionally supply a replacement character for non-printable glyphs:

// Replace non-printable/control entries with '?'
string safe = DxpFontSymbols.Substitute("Symbol", "\u0001\u00B7", '?'); // => "?•"

Reusing a converter

If you need to translate many strings from the same font or probe whether a font is supported, reuse a converter instance:

var converter = DxpFontSymbols.GetSymbolConverter("Webdings");
if (converter != null)
{
    string cat = converter.Substitute((char)0xF6, '?'); // 🐈
    string arrows = converter.Substitute((char)0x3C);   // ↔
}

Common mappings

  • Symbol bullet: DxpFontSymbols.Substitute("Symbol", (char)0xB7)
  • Webdings cat: DxpFontSymbols.Substitute("Webdings", (char)0xF6)🐈
  • Wingdings peace/ok: DxpFontSymbols.Substitute("Wingdings", "\u0041\u0042")✌👌
  • Wingdings 2 left point: DxpFontSymbols.Substitute("Wingdings 2", (char)0x42)👈
  • Wingdings 3 arrows: DxpFontSymbols.Substitute("Wingdings 3", "\u0030\u0031")⭽⭤
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos 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.2.2 210 3/3/2026
1.2.1 93 2/11/2026
1.2.0 132 2/7/2026
1.1.14 1,261 1/9/2026
1.1.13 105 1/9/2026
1.1.12 104 1/9/2026
1.1.11 104 1/9/2026
1.1.10 97 1/9/2026
1.1.9 101 1/9/2026
1.1.8 103 1/9/2026
1.1.7 110 1/8/2026
1.1.6 155 1/7/2026
1.1.5 99 1/7/2026
1.1.4 747 12/22/2025
1.1.3 181 12/22/2025
1.1.2 179 12/22/2025
1.1.1 176 12/22/2025
1.1.0 163 12/21/2025
1.0.1 287 12/19/2025
1.0.0 254 12/19/2025