XWPFDocument.getStyle 获取 org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyles 但不是文档部分 /word/styles.xml。因此,在写出XWPFDocument 时,不会提交此CTStyles 中的更改。
XWPFDocument.getStyles 获取扩展 POIXMLDocumentPart 的 XWPFStyles 并覆盖 commit 方法。因此,在写出XWPFDocument 时,将提交此XWPFStyles 中的更改。
不幸的是,没有一种方法可以从 XWPFStyles 中获取所有单一样式。有一个字段private CTStyles ctStyles,它也在protected void commit() 中提交,但不能公开访问。所以我用反射来得到它。
根据您之前的问题,我知道您在解析 *.docx 文件时遇到问题,该文件的字体大小错误地设置为双精度 <w:sz w:val="24.0"/>,这绝对是错误的,并导致 size.getVal() 抛出 org.apache.xmlbeans.impl.values.XmlValueOutOfRangeException: Invalid integer value: 24.0。
ctstyle.getRPr().getSz() 工作时不会崩溃,也有<w:sz w:val="24.0"/>。在这里你可以得到真正的平均尺寸。为此,请直接解析CTHpsMeasure size 的XML,然后将从那里截断的值设置为BigInteger。 BigDecimal为此提供了一种方法。
您还应该得到并更正ctstyle.getRPr().getSzCs(),这是使用的“复杂脚本”字体的大小,也可能是错误的。
以下对我有用,之后所有具有字体大小的样式都设置了整数字体大小。例如<w:sz w:val="24.0"/><w:szCs w:val="24.0"/> 是<w:sz w:val="24"/><w:szCs w:val="24"/>then。注意这里的测量单位是半点 24 半点 = 12 pt。
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyle;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyles;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHpsMeasure;
import java.math.BigInteger;
import java.math.BigDecimal;
import java.lang.reflect.Field;
public class WordChangeStyles {
public static void main(String[] args) throws Exception {
XWPFDocument document = new XWPFDocument(new FileInputStream("WordUsingStyles.docx"));
XWPFStyles styles = document.getStyles(); //XWPFStyles extends POIXMLDocumentPart and overwrites commit method
Field _ctStyles = XWPFStyles.class.getDeclaredField("ctStyles");
_ctStyles.setAccessible(true);
CTStyles ctStyles = (CTStyles)_ctStyles.get(styles);
CTHpsMeasure size;
String sz;
for (CTStyle ctstyle : ctStyles.getStyleList()) {
if (ctstyle.isSetRPr()) {
if (ctstyle.getRPr().isSetSz()) {
size = ctstyle.getRPr().getSz();
if (size != null) {
sz = size.selectAttribute("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "val").newCursor().getTextValue();
System.out.println(sz); //here you could get the real meant size out of
size.setVal(new BigDecimal(sz).toBigInteger()); //sets the sz got from size truncated to BigInteger
ctstyle.getRPr().setSz(size); //after that the font size should be integer
System.out.println(ctstyle.getRPr().getSz().getVal());
}
size = ctstyle.getRPr().getSzCs();
if (size != null) {
sz = size.selectAttribute("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "val").newCursor().getTextValue();
System.out.println(sz); //here you could get the real meant size out of
size.setVal(new BigDecimal(sz).toBigInteger()); //sets the sz got from size truncated to BigInteger
ctstyle.getRPr().setSzCs(size); //after that the font size should be integer
System.out.println(ctstyle.getRPr().getSzCs().getVal());
}
}
}
}
document.write(new FileOutputStream("WordUsingStyles.docx")); //while writing out XWPFStyles will be committed
document.close();
}
}