如何在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();
}
}
编辑[修复] - 见底部。
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();
}
}