как обеспечить последовательность атрибутов ctdocument в apache poi xwpf

EDIT[FIX] - см. внизу.

MS Office создает этот элемент во всех документах с некоторым базовым знанием того, что ограничения NS должны соблюдаться до определенной степени...

Пример документа MS:

<w:document
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: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"
mc:Ignorable="w14 w15 wp14">
    <!--whatever-->
</w:document>

Пример вывода POI

<w:document
mc:Ignorable="w14 w15 wp14"
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: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">
    <!--whatever-->
</w:document>

Обратите внимание, что элемент MC:IGNORABLE смещен... Изменение этого элемента вручную внутри самого архива docx «исправляет» ошибку, вызванную программой MSOffice, которая указывает на ошибку в строке 2, столбце 0.

До сих пор я пробовал:

xwpfDocument.getDocument().getDomNode()

^ пробовали изменять, удалять и добавлять атрибуты в правильном порядке... не работает, поскольку сдвиг, кажется, происходит где-то в процедуре XWPFDocument.write().

Я также пытался извлечь файл document.xml из архива docx, изменить его и вставить обратно в архив... и это, похоже, не работает... Проблемы с CRC...

Есть ли способ получить доступ к OPCPackage или его части или чему-либо, чтобы разрешить прямой вызов встроенного «recalculateAttributesRelativeToNS» в этом элементе?

... или в качестве альтернативы .. как мне автоматизировать изменения dom в файле xml документа внутри архива и при этом обеспечить совместимость с ms?

[РЕДАКТИРОВАТЬ: "XY"]

Такое поведение проявляется в следующем сценарии:

fis = new FileInputStream(new File(path));
XWPFPicture picture = imageRun.addPicture(fis, XWPFDocument.PICTURE_TYPE_PNG, path, Units.toEMU(450), Units.toEMU(290));

Документ открывается нормально. проблема отсутствует.

Добавление этой строки (я знаю, что это технически неправильно, однако об ошибке не следует сообщать в строке 2 — столбец 0, так как об этом следует сообщать дальше по xml) все портит.

picture.getCTPicture().getSpPr().addNewEffectLst().addNewOuterShdw().setBlurRad(10000);

С добавлением этой строки атрибуты w:document переходят в состояние 2 (пример poi), тем самым запуская процедуру аннулирования схемы NS MS Office.

Атрибуты правильные. Порядок неправильный. Перемещение вручную атрибута mc:ignorable в конец списка атрибутов решает проблему, и документ загружается без проблем.

Это, скорее всего, связано с тем, что (в правильной реализации) атрибут xmlns:mc предшествует атрибуту mc:ignorable в списке атрибутов, тогда как в выводе poi это не так (mc:Ignorable является первым элементом в списке). ).

отсюда... вопрос.

дополнительно... список импорта:

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.poi.POIXMLProperties;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFPicture;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDocument1;

все в этом классе самодостаточно.

РЕДАКТИРОВАТЬ [ИСПРАВИТЬ]

Исправление заключается в добавлении второй строки в этот фрагмент.

picture.getCTPicture().getSpPr().addNewEffectLst().addNewInnerShdw().setBlurRad(Units.toEMU(3));
picture.getCTPicture().getSpPr().getEffectLst().getInnerShdw().addNewPrstClr().setVal(org.openxmlformats.schemas.drawingml.x2006.main.STPresetColorVal.BLACK);

Еще раз спасибо, @AxelRichter.


person EverNight    schedule 13.11.2018    source источник
comment
Я считаю, что это проблема XY. Я и тысячи других пользователей apache poi создали *.docx файлов с помощью apache poi без этой проблемы. Так что я подозреваю, что проблема где-то за пределами apache poi. Пожалуйста, предоставьте самый простой *.docx исходный файл и самый простой apache poi код, который приводит к повреждению этого файла. И, пожалуйста, опишите свое окружение. Какая apache poi версия используется? Какая Java версия используется? Какие дополнительные Java библиотеки, особенно для создания XML, задействованы?   -  person Axel Richter    schedule 14.11.2018
comment
Вопрос @AxelRichter дополнен дополнительными подробностями.   -  person EverNight    schedule 14.11.2018
comment
ПОИ версии 3.17; JDK 1.8.102   -  person EverNight    schedule 14.11.2018


Ответы (1)


Указание на столбец 0 строки 2 в ошибке вводит в заблуждение. Если вы посмотрите на /word/document.xml, то там всего 2 строки. Объявление XML в строке 1 и весь остальной XML в строке 2.

Ваша проблема в том, что определение схемы CT_OuterShadowEffect:

<xsd:complexType name="CT_OuterShadowEffect">
 <xsd:sequence>
  <xsd:group ref="EG_ColorChoice" minOccurs="1" maxOccurs="1"/>
 </xsd:sequence>
 <xsd:attribute name="blurRad" type="ST_PositiveCoordinate" use="optional" default="0"/>
 <xsd:attribute name="dist" type="ST_PositiveCoordinate" use="optional" default="0"/>
 <xsd:attribute name="dir" type="ST_PositiveFixedAngle" use="optional" default="0"/>
 <xsd:attribute name="sx" type="ST_Percentage" use="optional" default="100%"/>
 <xsd:attribute name="sy" type="ST_Percentage" use="optional" default="100%"/>
 <xsd:attribute name="kx" type="ST_FixedAngle" use="optional" default="0"/>
 <xsd:attribute name="ky" type="ST_FixedAngle" use="optional" default="0"/>
 <xsd:attribute name="algn" type="ST_RectAlignment" use="optional" default="b"/>
 <xsd:attribute name="rotWithShape" type="xsd:boolean" use="optional" default="true"/>
</xsd:complexType>

Как видите, EG_ColorChoice должно встречаться 1 раз. Другими словами: должна быть настройка цвета для CTOuterShadowEffect.

Следующий код работает для меня:

import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;

import org.apache.poi.xwpf.usermodel.*;

import org.apache.poi.util.Units;

public class WordInsertPicturesWithShadow {

 public static void main(String[] args) throws Exception {

  XWPFDocument document = new XWPFDocument(new FileInputStream("source.docx"));
  XWPFParagraph paragraph = document.createParagraph();
  XWPFRun run = paragraph.createRun();

  run.setText("The picture: ");

  InputStream in = new FileInputStream("samplePict.jpeg");
  XWPFPicture picture = run.addPicture(in, Document.PICTURE_TYPE_JPEG, "samplePict.jpeg", Units.toEMU(100), Units.toEMU(100));
  in.close();  

  picture.getCTPicture().getSpPr().addNewEffectLst().addNewOuterShdw().setBlurRad(50000);
  //picture.getCTPicture().getSpPr().getEffectLst().getOuterShdw().setDist(100000);
  //picture.getCTPicture().getSpPr().getEffectLst().getOuterShdw().setDir(2700000);
  //picture.getCTPicture().getSpPr().getEffectLst().getOuterShdw().setAlgn(
  // org.openxmlformats.schemas.drawingml.x2006.main.STRectAlignment.TL);
  //picture.getCTPicture().getSpPr().getEffectLst().getOuterShdw().setRotWithShape(false);
  picture.getCTPicture().getSpPr().getEffectLst().getOuterShdw().addNewPrstClr().setVal(
   org.openxmlformats.schemas.drawingml.x2006.main.STPresetColorVal.BLACK);

  run.setText(" text after the picture.");

  paragraph = document.createParagraph();

  FileOutputStream out = new FileOutputStream("result.docx");
  document.write(out);
  out.close();
  document.close();
 }
}
person Axel Richter    schedule 14.11.2018
comment
Спасибо, @AxelRichter. ... как ни странно, документ открывается после ручного вмешательства, что заставило меня поверить, что это была основная проблема. Я даже не удосужился реализовать недостающий цвет. - person EverNight; 14.11.2018
comment
@EverNight: Ну, это может быть проблема с использованием инструментов, которые хотят быть умнее, чем хорошая проблема. Кажется, инструмент, который вы используете для редактирования XML, проверяет XML на соответствие схеме, если она существует. И кажется, что у него есть *.xsd для пространства имен http://schemas.openxmlformats.org/drawingml/2006/main. Таким образом, он удаляет код XML <a:outerShdw blurRad="10000"/>, потому что это нарушает схему. Так что любое редактирование приведет к исправлению. - person Axel Richter; 15.11.2018
comment
Я думаю, что вопрос ввел в заблуждение ... либо это, либо я не вижу ход ваших мыслей. Однако по соображениям целостности я должен уточнить, что я начал редактировать файл document.xml, чтобы исправить ошибку, вызванную добавлением объекта OuterShdw, который в этом состоянии нарушил схему, как вы указали, поскольку я добавил только эффект размытия без цвета. Исправление заключалось в том, чтобы добавить цвет. вопрос обновлен с исправлением. - person EverNight; 15.11.2018