Docx4j export FO игнорирует автономные пробелы

#xsl-fo #docx4j

#xsl-fo #docx4j

Вопрос:

Я использую docx4j-export-FO 11.3.2 для преобразования файла docx в xsl-fo, используя пример кода отсюда https://github.com/plutext/docx4j-export-FO/blob/master/src/samples/docx4j/org/docx4j/samples/ConvertOutPDFviaXSLFO.java. Всякий раз, когда есть автономный пробел, как <w:t xml:space="preserve"> </w:t> в word/document.xml внутри архива docx, затем он игнорируется и отсутствует в сгенерированном файле xsl-fo. Если пробелы совпадают <w:t> с символами, не содержащими пробелов, то они включаются. Пример проблемной ситуации в 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>
 

Это происходит при использовании XSLT exporter (Docx4J.FLAG_EXPORT_PREFER_XSL), при использовании visitor exporter (Docx4J.FLAG_EXPORT_PREFER_NONXSL) пробелы сохраняются, но удаляются все пустые строки из файла docx, поэтому меня это тоже не устраивает, так как мне нужно конвертировать xls-fo дальше в pdf.
Я попытался выполнить поиск в Интернете, но не смог найти именно эту проблему, означает ли это, что она должна работать таким образом, или есть какая-либо конфигурация или обходной путь, которые я мог бы использовать для решения этой проблемы?

Редактировать: ниже приведен пример того, как экспортер посетителей игнорирует пустые строки в документе WordML. WordML с пустой строкой между двумя непустыми строками:

 <?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, созданный посетителем-экспортером:

 <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, созданный экспортером XSLT:

 <?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>
 

Поэтому я считаю, что разница заключается в том, что white-space-treatment="preserve" она не генерируется экспортером посетителей.

Теперь у нас есть XSLT exporter, который игнорирует автономные пробелы, в то время как visitor exporter игнорирует пустые строки, и я думаю, что единственный способ решить эту проблему — изменить исходный код, для чего у меня недостаточно навыков.

Комментарии:

1. Когда вы говорите «удаляет все пустые строки из файла docx», не могли бы вы привести пример вашего ввода WordML?

2. Еще лучше, опубликуйте полученный файл XSL FO. Только таким образом мы можем помочь отладить то, что создается их экспортом XSL FO

3. @JasonPlutext извините за поздний ответ. если вам все еще интересно, я добавил пример, который вы просили.

4. «экспортер посетителей игнорирует пустые строки» с помощью FLAG_EXPORT_PREFER_NONXSL: не может воспроизвести, поскольку он создает пустой блок в FO, что приводит к пустой строке в результирующем PDF. Пожалуйста, откройте проблему на github, если вы можете создать тестовый пример. Спасибо

5. Другая проблема, которая теперь отслеживается по адресу github.com/plutext/docx4j/issues/496

Ответ №1:

Ваше приложение делает что-то неправильно, но, возможно, вы можете изменить XSLT, чтобы исправить это. Если вы можете увидеть файл XSL-FO, который FOP использует в качестве входных данных, вы можете получить лучшее представление о том, был ли текст удален или с ним было сделано что-то еще. Я ничего не знаю о Docx4J, поэтому я не знаю, есть ли опция конфигурации, которая исправит ситуацию для вас.

Каждое XML-приложение должно сохранять текстовые узлы, содержащие только пробелы, в элементах, которые имеют xml:space="preserve" . (См . https://www.w3.org/TR/REC-xml/#sec-white-space )

Приложение XSLT должно сохранять текстовые узлы, содержащие только пробелы, где:

Элемент-предок текстового узла имеет xml:space атрибут со значением preserve , и ни один более близкий элемент-предок не имеет xml:space значения по умолчанию.

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

Таким образом, текстовый узел, содержащий только пробелы, должен быть в исходном документе для вашего преобразования XSLT. Если у вас есть доступ к используемой таблице стилей, ознакомьтесь с xsl:template правилами для text() или w:t и посмотрите, сможете ли вы решить, что изменить.