如何在apache poi xwpf中确保ctdocument属性顺序

how to ensure ctdocument attribute sequence in apache poi xwpf

编辑[修复] - 见底部。

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 存档本身中手动修改此元素 "fixes" MSOffice 程序抛出的错误,它指定第 2 行第 0 列中的错误.

到目前为止我已经尝试过:

xwpfDocument.getDocument().getDomNode()

^ 已尝试以正确的顺序修改、删除和添加属性...不起作用,因为转换似乎发生在 XWPFDocument.write() 过程中的某处。

我也试过从 docx 存档中提取 document.xml 文件,对其进行修改并将其重新注入存档中……这似乎不起作用……CRC 问题…… .

有没有办法访问 OPCPackage 或部分或任何东西以允许直接调用此元素中的内置 "recalculateAttributesRelativeToNS"?

... 或者作为替代方案.. 我如何在存档内的文档 xml 文件中自动执行 dom 更改并仍然确保 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 示例),从而触发 ms Office 的 MS 架构 NS 失效例程。

属性正确。顺序错了。手动将 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;

此 class 中的所有内容都是独立的。

编辑 [修复]

修复方法是在此代码段中添加第二行。

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。

错误中第 2 行第 0 列的指向具有误导性。如果你看一下 /word/document.xml 那么根本就只有 2 行。第 1 行中的 XML 声明和第 2 行中的所有其他 XML。

您的问题是 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();
 }
}