Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is There An Open Source XSLT To Convert a WPF FlowDocument to WordML?

I want to use a WPF RichTextBox which allows users to edit and format text. This formatted text will eventually work its way into a Word document along with some of our other custom XML data.

I've found several examples going from WordML to a FlowDocument but nothing that takes the RichTextBox FlowDocument to WordML.

Rather than re-invent the wheel, is there an open source XSLT file I can use to convert a WPF FlowDocument into WordML?

I'm not looking for a 100% solution (e.g. tables, figures, drawings, etc.). At this point, I'm just interested in preserving font formatting, paragraphs, bullet lists, etc.

Edit:

I need to avoid Word Interop or expensive 3rd party tools (e.g. Apose) if possible. I'm looking for an elegant way to translate some basic FlowDocument XML formatted content to OpenXML, preferrably via XSLT. Since I'm not interested in items such as embedded pictures, I believe it's probably doable given the fact that I've found examples going the other direction (i.e. OpenXML/WordML to XAML Flowdocument)

like image 732
bporter Avatar asked Jan 22 '13 21:01

bporter


2 Answers

There are a couple of solutions I found in my searching. The easiest way would probably be to convert to an .rtf format which supports all of the required XSLT stuff. This is explained VERY well here.

Another solution I found online is where someone goes to PDF, but first converts to .DOCX. You can find his solution here. If you just want the part that converts to .DOCX, you would want to edit out his code so that the .DOCX is not replaced with the .PDF.

Depending on the details of how your project works, you may find this interesting.

I hope this helps you. Currently there are not direct ways to do this with a single API. You need to convert to some format like .XPS, .RTF, etc, and then from their use another API to convert to WordMl.

Happy coding!

like image 92
FrostyFire Avatar answered Nov 15 '22 20:11

FrostyFire


JABFreeware has touched on a method that I have used; taking the FlowDocument content and creating an rtf then build a new Word document and save. However, you may not want to touch libraries like Microsoft.Office.Interop.Word.

There are some examples out there of other methods too. For example, you might want to look at the following open source FlowDocument editor here. It is old, but still informative and converts FlowDocuments to docx. This brings up looking into the OpenXml SDK from Microsoft's site (not enough rep for more links, but Google will get you there).

Also, you might find this useful as a reference. It is a Word add-on that you can get the source code to that will allow you to convert Word documents to FlowDocuments. It's backwards from the original request, but reversing the process is a possibility.

Hope some of this helps.

EDIT:

If you really want to cheat and the documents that you will be creating are really basic, you can. However, I know this to work only with docx.

  1. Create a simple word document with some formatting first (as a docx).
  2. Extract the contents and keep everything but the /word/document.xml file.
  3. Open the /word/document.xml file and use that as a template for your XSLT. I made a simple one here:

FlowDocument XML

<?xml version="1.0" encoding="utf-8"?>
<FlowDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
  <Paragraph>
    <Run FontWeight="Bold" Foreground="#FF0000">Testing</Run>
  </Paragraph>
  <Paragraph>
    <Run FontWeight="Bold" Foreground="#0000FF">Testing2</Run>
  </Paragraph>
</FlowDocument>

XSLT (only partially done for demo purposes)

<?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">
<xsl:template match="/x:FlowDocument">
    <?mso-application progid="Word.Document"?>
    <w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
       <w:body>
          <w:sect>
        <w:p>
                <xsl:for-each select="x:Paragraph">
            <w:pPr>
                <w:jc w:val="center" />
                <w:spacing w:after="0" w:line="240" w:lineRule="auto"/>
            </w:pPr>
            <w:r>
                <w:rPr>
                    <w:rFonts w:ascii="Segoe UI" w:hAnsi="Segoe UI" w:cs="Segoe UI" />
                    <w:sz w:val="18" />
                    <w:b w:val="on" />
                    <w:i w:val="off" />
                    <w:color>
                        <xsl:attribute name="w:val"><xsl:value-of select="x:Run/@Foreground"/></xsl:attribute>
                    </w:color>
                </w:rPr>
                <w:t><xsl:value-of select="x:Run" /></w:t>
            </w:r>
    </xsl:for-each>
        </w:p>
      </w:sect>
    </w:body>
  </w:document>
</xsl:template>
</xsl:stylesheet>
  1. Use and XmlDocument and XamlWriter to create the xml to transform.
  2. Save your transformation result as a new 'document.xml' and put it in the /word directory and package everything as an archive with a .docx extension.

The biggest headache is that FlowDocuments will probably be RGBA but WordML works with RBG in the color attribute.

So, there is a way to get everything with one xslt, but it is also headache. IMHO, the code from the OpenXmlWriter application would be a much cleaner solution. Or possibly a combination of both...

like image 37
Vynos Avatar answered Nov 15 '22 20:11

Vynos