Knowledgebase (2597)
Children categories
Converting between Word documents and OpenXML is one of the most frequent needs in document processing: exporting a Word document to XML lifts the body content out of the binary package structure, which makes cross-system exchange, bulk extraction and archiving much easier, while turning XML back into a Word document lets you generate a standard document directly from structured data you already have. Spire.Doc for JavaScript performs the conversion in both directions in the browser via WebAssembly, using a virtual file system (VFS) to manage fonts and files — no backend server required. OpenXML flat files come in two formats: WordML for Word 2003 and WordXml (Flat OPC) for Word 2007 and later, so the one you save as depends on the target Word version.
This article covers three core features:
For installation and project setup, refer to Integrating Spire.Doc for JavaScript in a React Project. The examples below assume Spire.Doc is installed and the WebAssembly module is initialized.
Word to OpenXML (WordML)
Converting a Word document to OpenXML involves three steps: first, load the font files and the target Word document into the WASM virtual file system via FetchFileToVFS; then instantiate a Document, load the file and call SaveToFile with FileFormat.WordML to save the document as a Word 2003 XML flat file; finally, read the generated XML file from VFS, wrap it as a Blob and trigger a browser download.
function App() {
const WordToWordML = async () => {
const docModule = window.wasmModule?.spiredoc;
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load the sample file into VFS
let inputFileName = 'WordToWordXML.docx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/static/data/`);
// Create a document instance
const doc = new docModule.Document();
// Load the document from the virtual file system
doc.LoadFromFile(inputFileName);
// Define the output file name and save it as a Word 2003 OpenXML file
const outputFileName = 'WordToWordXML-result.xml';
doc.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.WordML });
// Release resources
doc.Dispose();
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Convert Word To WordML</h1>
<button onClick={WordToWordML}>Generate</button>
</div>
);
}
export default App;
With FileFormat.WordML passed to SaveToFile, the Word document is converted into a Word 2003 XML flat file

Word to OpenXML (WordXml)
The flat file format of Word 2007 and later is called WordXml (Flat OPC): it packs the individual parts of the docx package — body, styles, relationships and so on — into a single XML file whose root element is <pkg:package>, and Word can open it directly just the same. The conversion flow is identical to WordML; only the save format differs. It again involves three steps: first, load the font files and the target Word document into the WASM virtual file system via FetchFileToVFS; then instantiate a Document, load the file and call SaveToFile with FileFormat.WordXml to save the document as a Word 2007 XML file; finally, read the generated XML file from VFS, wrap it as a Blob and trigger a browser download.
function App() {
const WordToWordXml = async () => {
const docModule = window.wasmModule?.spiredoc;
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load the sample file into VFS
let inputFileName = 'WordToWordXML.docx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/static/data/`);
// Create a document instance
const doc = new docModule.Document();
// Load the document from the virtual file system
doc.LoadFromFile(inputFileName);
// Define the output file name and save it as a Word 2007 OpenXML file
const outputFileName = 'WordToWordXML-result-2007.xml';
doc.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.WordXml });
// Release resources
doc.Dispose();
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Convert Word To WordXml</h1>
<button onClick={WordToWordXml}>Generate</button>
</div>
);
}
export default App;
With FileFormat.WordXml passed to SaveToFile, the parts of the Word document are merged into a single Word 2007 Flat OPC XML file

OpenXML to Word
Converting OpenXML to Word involves three steps: first, load the font files and the target XML file into the WASM virtual file system via FetchFileToVFS; then instantiate a Document and load the XML file directly with LoadFromFile — Spire.Doc recognizes the WordML and WordXml formats from the file contents automatically — and call SaveToFile to save it as a Docx2013 Word document; finally, read the generated .docx file from VFS, wrap it as a Blob and trigger a browser download.
function App() {
const XMLToWord = async () => {
const docModule = window.wasmModule?.spiredoc;
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load the sample file into VFS
let inputFileName = 'XMLToWord.xml';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/static/data/`);
// Create a document instance
const doc = new docModule.Document();
// Load the OpenXML file from the virtual file system
doc.LoadFromFile(inputFileName);
// Define the output file name and save it as a Word document
const outputFileName = 'XMLToWord-result.docx';
doc.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.Docx2013 });
// Release resources
doc.Dispose();
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Convert XML To Word</h1>
<button onClick={XMLToWord}>Generate</button>
</div>
);
}
export default App;
After the OpenXML file is loaded with LoadFromFile and saved as a Word document, the paragraphs, lists and tables it contains are restored in full

FAQ
The generated XML reports a format error when opened in Word
Cause: The save format does not match the target Word version. FileFormat.WordML maps to the Word 2003 XML format and FileFormat.WordXml to the Word 2007 and later Flat OPC format; the two have different structures, so opening a file saved in the newer format with an older version of Word fails.
Solution: Pick the enum value that matches the target Word version, and name the output file .xml:
// Word 2003 and earlier
doc.SaveToFile({ fileName: 'out.xml', fileFormat: wasmModule.FileFormat.WordML });
// Word 2007 and later
doc.SaveToFile({ fileName: 'out.xml', fileFormat: wasmModule.FileFormat.WordXml });
Loading the XML fails, or the converted document comes out empty
Cause: OpenXML to Word requires the input to be a complete WordprocessingML flat file; an ordinary custom data XML cannot be recognized by LoadFromFile.
Solution: Make sure the input XML was exported by Word or Spire.Doc — the root element of the WordML format is <w:wordDocument> and that of the WordXml format is <pkg:package>:
const doc = new wasmModule.Document();
doc.LoadFromFile('XMLToWord.xml');
Get a Free License
Spire.Doc for JavaScript offers a 30-day full-featured free trial license with no functional limitations. Apply here to evaluate before purchasing.
Plain text (TXT) is the lightest text carrier there is, commonly used for log export, data exchange and content archiving, while Word takes care of layout and formal delivery. Converting between the two in the browser is a common document-processing need: TXT to Word turns collected plain text into a well-formed document, and Word to TXT extracts body text that a program can keep processing. Spire.Doc for JavaScript performs the conversion in both directions in the browser via WebAssembly, using a virtual file system (VFS) to manage fonts and files — no backend server required.
It should be said up front that TXT is a plain-text format which carries no layout information of its own, so both directions only hold at the level of text: the styles, table structure and images on the Word side never reach the TXT file, and a Word document produced from TXT contains nothing but body paragraphs. Being clear about that boundary before you use the API keeps your expectations of the result realistic.
This article covers two core features:
For installation and project setup, refer to Integrating Spire.Doc for JavaScript in a React Project. The examples below assume Spire.Doc is installed and the WebAssembly module is initialized.
Convert TXT to Word
Converting TXT to Word involves three steps: first, load the font files and the target TXT file into the WASM virtual file system via FetchFileToVFS; then instantiate a Document and load the file with LoadFromFile — no fileFormat is passed here, so Spire.Doc identifies it as plain text from the file extension; finally, call SaveToFile to save the result as docx, read the generated file from VFS, wrap it as a Blob and trigger a browser download.
function App() {
const TxtToWord = async () => {
const docModule = window.wasmModule?.spiredoc;
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load the sample file into VFS
let inputFileName = "TxtToWord.txt";
await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}/static/data/`);
// Create a document instance
const doc = new docModule.Document();
// Load the document from the virtual file system
doc.LoadFromFile(inputFileName);
// Define the output file name
const outputFileName = "TxtToWord-result.docx";
// Save the document in the specified format
doc.SaveToFile({fileName: outputFileName, fileFormat: docModule.FileFormat.Docx2013});
// Release resources
doc.Dispose();
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Convert TXT To Word</h1>
<button onClick={TxtToWord}>Generate</button>
</div>
);
}
export default App;
Because TXT carries no style information, the result is decided entirely by the default layout rules of Spire.Doc, and there are two things to keep in mind: every line break in the file is turned into a paragraph in Word, while blank lines are kept as empty paragraphs, so a file that ends with a line break gains an extra empty paragraph at the end; and every paragraph in the output uses the default Normal style, so headings, numbering and bullet levels are not created automatically — the 1., - and similar characters written in the TXT are kept as ordinary characters only.
After a TXT file is loaded with LoadFromFile and saved as a Word document, the text is restored to paragraphs line by line, all in the Normal style

Convert Word to TXT
Converting Word to TXT follows the same three steps as the other direction: load the font files and the target Word document into the virtual file system via FetchFileToVFS, then instantiate a Document and load the document with LoadFromFile. The difference is that FileFormat.Txt is specified when saving, so Spire.Doc extracts the document content by plain-text rules; finally, read the generated txt file from VFS, wrap it as a text/plain Blob and trigger a browser download.
function App() {
const WordToTxt = async () => {
const docModule = window.wasmModule?.spiredoc;
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load the sample file into VFS
let inputFileName = "WordToTxt.docx";
await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}/static/data/`);
// Create a document instance
const doc = new docModule.Document();
// Load the document from the virtual file system
doc.LoadFromFile(inputFileName);
// Define the output file name
const outputFileName = "WordToTxt-result.txt";
// Save the document as plain text
doc.SaveToFile({fileName: outputFileName, fileFormat: docModule.FileFormat.Txt});
// Release resources
doc.Dispose();
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Convert Word To TXT</h1>
<button onClick={WordToTxt}>Generate</button>
</div>
);
}
export default App;
The FileFormat.Txt export follows a "text only" rule. Taking a Word document that contains a heading, a bullet list, a numbered list, a table and an image as the example, the exported result can be summed up as follows:
- The font, font size, colour and bold formatting of headings, body text and list items are all dropped, and everything is reduced to ordinary text lines;
- Bullet list items are written with a
*prefix and numbered items with a1.prefix, and the list level information is lost along with them; - The table is expanded cell by cell into separate lines, so the correspondence between rows and columns no longer holds;
- Images are not exported, and the paragraph that held one becomes an empty line.
In addition, the exported txt is UTF-8 encoded with a BOM and uses CRLF line breaks, so wrapping the Blob with the text/plain type is all that is needed.
With FileFormat.Txt passed to SaveToFile, the styles, tables and images of the Word document are not preserved and only the text content is written out in order

FAQ
Table columns shift and list markers turn into asterisks after converting Word to TXT
Cause: TXT has no concept of rows, columns or list structure, and FileFormat.Txt only extracts text: the table is written out line by line in cell order, bullets are replaced with * and numbering with the number text. This is a limitation of the format itself rather than a conversion failure.
Solution: If all the downstream consumer needs is readable text, restore the structure on the reading side using the rules above; if the table and list layout has to be preserved, use a format that can carry structure instead, such as HTML or OpenXML.
The converted Word document has no heading or list styles
Cause: TXT carries no style information, so when LoadFromFile loads plain text it can only write each line as a paragraph with the default Normal style — the 1., - and similar characters in the TXT are ordinary characters and are not parsed as headings or lists.
Solution: Set the styles of the paragraphs you care about again after the conversion; if setting them paragraph by paragraph is not acceptable, complete this step with an input format that already carries structure (such as HTML) instead.
Loading a TXT file reports that the file type cannot be detected
Cause: When LoadFromFile is called without fileFormat, the format is judged from the file extension. When the extension of the input file is not .txt (for example .log, .dat, or no extension at all), Spire.Doc cannot identify it and throws an exception such as Cannot detect current file type.
Solution: Specify the plain-text format explicitly:
doc.LoadFromFile({ fileName: inputFileName, fileFormat: wasmModule.FileFormat.Txt });
Get a Free License
Spire.Doc for JavaScript offers a 30-day full-featured free trial license with no functional limitations. Apply here to evaluate before purchasing.
HTML is the most universal carrier for presenting content on the web and for editing rich text, while Word remains the standard format for delivering and archiving documents. Converting between the two comes up frequently in scenarios such as report export, content archiving, and storing rich text in a database. Spire.Doc for JavaScript performs this conversion directly in the browser via WebAssembly, using a virtual file system (VFS) to manage input and output files — no backend server required.
This article covers two core features:
For installation and project setup, refer to Integrating Spire.Doc for JavaScript in a React Project. The examples below assume Spire.Doc is installed and the WebAssembly module is initialized.
HTML File to Word
Converting an HTML file to Word breaks down into three stages: first, load the font file and the target HTML file into the WASM virtual file system via FetchFileToVFS; then instantiate a Document and call LoadFromFile with FileFormat.Html, so that Spire.Doc parses the tags, lists, and table structures in the file; finally, call SaveToFile to save the result as a docx, read the generated file from VFS, wrap it in a Blob, and trigger a browser download.
function App() {
const htmlFileToWord = async () => {
const docModule = window.wasmModule?.spiredoc;
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
const inputFileName = 'HtmlFileToWord.html';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);
// Create a Document instance and load the file in HTML format
const doc = new docModule.Document();
doc.LoadFromFile({
fileName: inputFileName,
fileFormat: docModule.FileFormat.Html,
validationType: docModule.XHTMLValidationType.None,
});
// Define the output file name and save it as Word
const outputFileName = 'HtmlFileToWord-result.docx';
doc.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.Docx });
// Release resources
doc.Dispose();
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Convert an HTML File to a Word Document</h1>
<button onClick={htmlFileToWord}>Generate</button>
</div>
);
}
export default App;
The Word document generated by converting an HTML file via LoadFromFile

HTML String to Word
In real projects the HTML waiting to be converted usually does not live on disk. It is the submitted result of a rich text editor, a fragment returned by a backend API, or a string assembled from a front-end template. Input like this does not need to be loaded from a file — appending the string to a paragraph is enough, and the rest of the flow matches HTML file to Word.
function App() {
const htmlStringToWord = async () => {
const docModule = window.wasmModule?.spiredoc;
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load the font into VFS
await window.spire.FetchFileToVFS("ARIALUNI.TTF","/Library/Fonts/",`${process.env.PUBLIC_URL}static/font/`);
// Define the HTML string to be converted
let HTML = "<html><head><meta charset=\"utf-8\" /><style type=\"text/css\">body{font-family:'Arial Unicode MS';font-size:11pt;}h2{font-family:'Arial Unicode MS';font-size:16pt;color:#1F4E79;}p,li,td,th{font-family:'Arial Unicode MS';font-size:11pt;}</style></head><body>";
HTML += "<h2 align=\"center\">Sichuan Province at a Glance</h2><p><b>Overview:</b></p> ";
HTML += "<ul type=\"disc\"><li><span style='color:#548235;'>Capital Chengdu, abbreviated as \"Chuan\" or \"Shu\"</span></li><li>Located in southwestern China, on the upper reaches of the Yangtze River</li><li><span style='color:#C00000'>The Western Sichuan Plateau and the Sichuan Basin differ greatly in climate, so trips need to be prepared region by region</span></li></ul><p><b>Signature Attractions:</b></p>";
HTML += "<ul type=\"square\"><li>Jiuzhaigou Valley</li><li>Mount Emei — Leshan Giant Buddha</li><li>Dujiangyan — Mount Qingcheng</li></ul>";
HTML += "<table border=\"1\" width=\"90%\" cellspacing=\"0\" cellpadding=\"6\"><tr><th>Sichuan Province Fact Sheet</th></tr><tr><td>Covers about 486,000 square kilometers, the fifth largest area in the country</td></tr><tr><td>Has a resident population of about 83 million and is home to many ethnic groups</td></tr>";
HTML += "<tr><td>Known since ancient times as the \"Land of Abundance\" and an important ecological barrier on the upper Yangtze</td></tr><tr><td>The main habitat of the giant panda, with the largest wild population in the country</td></tr></table></body></html>";
// Create a document and add a section and a paragraph
const doc = new docModule.Document();
const section = doc.AddSection();
const paragraph = section.AddParagraph();
// Append the HTML string to the paragraph
paragraph.AppendHTML(HTML);
// Define the output file name and save it as Word
const outputFileName = 'HtmlStringToWord-result.docx';
doc.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.Docx2013 });
// Release resources
doc.Dispose();
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Write an HTML String into a Word Document</h1>
<button onClick={htmlStringToWord}>Generate</button>
</div>
);
}
export default App;
The Word document generated by converting an HTML string via AppendHTML

FAQ
Converted Word text displays as boxes or garbled characters
Cause: The font files required for rendering are missing from the WASM virtual file system. LoadFromFile matches fonts for the text while it parses the HTML, and content written by AppendHTML also needs glyphs looked up by font name — if the matching font is not present in VFS, non-ASCII characters such as Chinese will display as boxes or garbled text.
Solution: Load the font file into VFS via FetchFileToVFS before converting:
await window.spire.FetchFileToVFS(
'ARIALUNI.TTF', '/Library/Fonts/', '/'
);
A validation-related exception is thrown when loading an HTML file
Cause: XHTMLValidationType is set too strictly. Real-world HTML files usually contain unclosed tags, inconsistently cased attributes, or non-standard markup, so they do not conform to the XHTML specification — strict validation throws during the parsing stage.
Solution: For HTML from uncontrolled sources, turn validation off with XHTMLValidationType.None:
wordDocument.LoadFromFile({
fileName: inputFileName,
fileFormat: docModule.FileFormat.Html,
validationType: docModule.XHTMLValidationType.None,
});
Get a Free License
Spire.Doc for JavaScript offers a 30-day full-featured free trial license with no functional limitations. Apply here to evaluate before purchasing.