Docx4j export FO ignores standalone whitespace

Viewed 151

I'm using docx4j-export-FO 11.3.2 to convert a docx file into xsl-fo using sample code from here https://github.com/plutext/docx4j-export-FO/blob/master/src/samples/docx4j/org/docx4j/samples/ConvertOutPDFviaXSLFO.java. Whenever there is a standalone whitespace like <w:t xml:space="preserve"> </w:t> in word/document.xml inside docx archive, then it is ignored and is missing in the generated xsl-fo file. If whitespace goes in the same <w:t> with non-whitespace characters, then it is included. Example of problematic situation in word/document.xml:

<w:r>
<w:rPr>
<w:rFonts w:ascii="Times New Roman" w:hAnsi="Times New Roman" w:cs="Times New Roman"/>
</w:rPr>
<w:t>Testing</w:t>
</w:r>
<w:r>
<w:rPr>
<w:rFonts w:ascii="Times New Roman" w:hAnsi="Times New Roman" w:cs="Times New Roman"/>
</w:rPr>
<w:t xml:space="preserve"> </w:t>
</w:r>
<w:r>
<w:rPr>
<w:rFonts w:ascii="Times New Roman" w:hAnsi="Times New Roman" w:cs="Times New Roman"/>
</w:rPr>
<w:t>whitespace</w:t>
</w:r>

This happens when using XSLT exporter (Docx4J.FLAG_EXPORT_PREFER_XSL), when using a visitor exporter (Docx4J.FLAG_EXPORT_PREFER_NONXSL) whitespace is preserved, but it removes all blank lines from docx file, so doesn't suit me either as I need to convert xls-fo further into pdf. I tried searching on the internet, but couldn't find exactly this issue, does it mean it's supposed to work this way or is there any config or workaround I could use to solve this problem?

Edit: the following is an example of visitor exporter ignoring blank lines in a WordML document. WordML with a blank line between two non-blank lines:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:document mc:Ignorable="w14 w15 w16se wp14" xmlns:cx="http://schemas.microsoft.com/office/drawing/2014/chartex" xmlns:cx1="http://schemas.microsoft.com/office/drawing/2015/9/8/chartex" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape">
    <w:body>
        <w:p w:rsidP="00550D75" w:rsidR="00065907" w:rsidRDefault="00550D75">
            <w:pPr>
                <w:pStyle w:val="a3"/>
            </w:pPr>
            <w:r>
                <w:t>Empty</w:t>
            </w:r>
        </w:p>
        <w:p w:rsidP="00550D75" w:rsidR="00550D75" w:rsidRDefault="00550D75">
            <w:pPr>
                <w:pStyle w:val="a3"/>
            </w:pPr>
        </w:p>
        <w:p w:rsidP="00550D75" w:rsidR="00550D75" w:rsidRDefault="00550D75" w:rsidRPr="00550D75">
            <w:pPr>
                <w:pStyle w:val="a3"/>
            </w:pPr>
            <w:r>
                <w:t>Line.</w:t>
            </w:r>
            <w:bookmarkStart w:id="0" w:name="_GoBack"/>
            <w:bookmarkEnd w:id="0"/>
        </w:p>
        <w:sectPr w:rsidR="00550D75" w:rsidRPr="00550D75">
            <w:pgSz w:h="15840" w:w="12240"/>
            <w:pgMar w:bottom="1134" w:footer="708" w:gutter="0" w:header="708" w:left="1701" w:right="850" w:top="1134"/>
            <w:cols w:space="708"/>
            <w:docGrid w:linePitch="360"/>
        </w:sectPr>
    </w:body>
</w:document>

Xsl-fo generated by visitor exporter:

<root xmlns="http://www.w3.org/1999/XSL/Format">
    <layout-master-set>
        <simple-page-master margin-bottom="12mm" margin-left="1.18in" margin-right="15mm" margin-top="12mm"
                            master-name="s1-simple" page-height="11in" page-width="8.5in">
            <region-body column-count="1" column-gap="12mm" margin-bottom="21.0pt" margin-left="0mm" margin-right="0mm"
                         margin-top="21.0pt"/>
            <region-before extent="0.0pt" region-name="xsl-region-before-simple"/>
            <region-after extent="0.0pt" region-name="xsl-region-after-simple"/>
        </simple-page-master>
        <page-sequence-master master-name="s1">
            <repeatable-page-master-alternatives>
                <conditional-page-master-reference master-reference="s1-simple"/>
            </repeatable-page-master-alternatives>
        </page-sequence-master>
    </layout-master-set>
    <page-sequence id="section_s1" master-reference="s1">
        <flow flow-name="xsl-region-body">
            <block break-before="auto" country="US" font-size="11.0pt" language="en" line-height="100%"
                   space-after="0in">
                <inline>
                    <inline font-family="Calibri">Empty</inline>
                </inline>
            </block>
            <block country="US" font-size="11.0pt" language="en" line-height="100%" space-after="0in"/>
            <block country="US" font-size="11.0pt" language="en" line-height="100%" space-after="0in">
                <inline>
                    <inline font-family="Calibri">Line.</inline>
                </inline>
            </block>
        </flow>
    </page-sequence>
</root>

Xsl-fo generated by XSLT exporter:

<?xml version="1.0" encoding="utf-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
    <layout-master-set xmlns="http://www.w3.org/1999/XSL/Format"
                       xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml"
                       xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml"
                       xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex"
                       xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing">
        <simple-page-master margin-bottom="12mm" margin-left="1.18in" margin-right="15mm" margin-top="12mm"
                            master-name="s1-simple" page-height="11in" page-width="8.5in">
            <region-body column-count="1" column-gap="12mm" margin-bottom="21.0pt" margin-left="0mm" margin-right="0mm"
                         margin-top="21.0pt"/>
            <region-before extent="0.0pt" region-name="xsl-region-before-simple"/>
            <region-after extent="0.0pt" region-name="xsl-region-after-simple"/>
        </simple-page-master>
        <page-sequence-master master-name="s1">
            <repeatable-page-master-alternatives>
                <conditional-page-master-reference master-reference="s1-simple"/>
            </repeatable-page-master-alternatives>
        </page-sequence-master>
    </layout-master-set>
    <fo:page-sequence force-page-count="no-force" id="section_s1" format="" master-reference="s1">
        <fo:flow flow-name="xsl-region-body">
            <fo:block break-before="auto" country="US" font-size="11.0pt" hyphenate="true" language="en"
                      line-height="100%" space-after="0in">
                <inline xmlns="http://www.w3.org/1999/XSL/Format" font-family="Calibri">Empty</inline>
            </fo:block>
            <fo:block country="US" font-size="11.0pt" hyphenate="true" language="en" line-height="100%"
                      space-after="0in" white-space-treatment="preserve"></fo:block>
            <fo:block country="US" font-size="11.0pt" hyphenate="true" language="en" line-height="100%"
                      space-after="0in">
                <inline xmlns="http://www.w3.org/1999/XSL/Format" font-family="Calibri">Line.</inline>
            </fo:block>
        </fo:flow>
    </fo:page-sequence>
</fo:root>

So I believe the difference is in that white-space-treatment="preserve" is not generated by visitor exporter.

Now we have XSLT exporter that ignores standalone whitespaces, while visitor exporter ignores blank lines and I think the only way to resolve this is to modify source code, which I don't have enough skills to accomplish.

1 Answers

Your application is doing something wrong, but maybe you can modify the XSLT to fix it. If you can see the XSL-FO file that FOP uses as input, you might get a better idea whether the text has been dropped or had something else done to it. I don't know anything about Docx4J, so I don't know if there's a configuration option that will fix things for you.

Every XML application should preserve white-space-only text nodes in elements that have xml:space="preserve". (See https://www.w3.org/TR/REC-xml/#sec-white-space)

An XSLT application should preserve white-space-only text nodes where:

An ancestor element of the text node has an xml:space attribute with a value of preserve, and no closer ancestor element has xml:space with a value of default.

(See https://www.w3.org/TR/1999/REC-xslt-19991116#strip)

So the white-space-only text node should be in the source document for your XSLT transformation. If you have access to the stylesheet that's being used, look at the xsl:template rules for text() or w:t and see if you can work out what to change.

Related