使用poi实现word解析
word样式解析
poi进行样式解析时,如果是常用的样式是无法获取到它的样式信息的,并且通过poi工具读取时也存在有部分内容无法解析,这样在使用的时候体验就不是太好,后来我发现将docx文件通过压缩包的形式打开,docx的文件打开如图所示
打开“word”,里面有一个document.xml这个文件就包含了word的样式以及文本内容
通过分析此文件可以发现
w:p:表示属于文本内容
w:val: 表示文本的字体大小
w:ascil: 表示文本的字体格式
如果 w:p 中的文本为空则表示该段落没有文本内容,字体格式获取时为空则表示字体使用的是默认格式宋体(简),字体大小如果获取为空,表示字体使用的是默认字体大小24.
springBoot集成poi解析word文件
1.导入maven依赖
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.5</version>
</dependency>
2.编写操作word工具类PoiUtil
public static Map<String, FontDto> getType(MultipartFile file) {
HashMap<String, FontDto> fontMap = new HashMap<>(20);
try (ZipInputStream zipIs = new ZipInputStream(file.getInputStream())) {
// 读取 Word 文档
ZipEntry entry;
String contentXml = null;
// 寻找 content.xml 文件
while ((entry = zipIs.getNextEntry()) != null) {
if ("word/document.xml".equals(entry.getName())) {
// 找到了 content.xml
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = zipIs.read(buffer)) > 0) {
baos.write(buffer, 0, len);
}
contentXml = baos.toString("UTF-8");
baos.close();
break;
}
}
if (contentXml != null) {
// 解析 content.xml
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new ByteArrayInputStream(contentXml.getBytes(StandardCharsets.UTF_8)));
// 查找标题的字体信息(假设标题在第一个段落中)
NodeList textNodes = doc.getElementsByTagName("w:p");
for (int i = 0; i < textNodes.getLength(); i++) {
Element textNode = (Element) textNodes.item(i);
String text = textNode.getTextContent().trim();
if ("".equals(text)) {
continue;
}
// 获取格式信息
String fontFamily = null;
String fontSize = null;
// 获取包含格式信息的父节点
Element parentNode = (Element) textNode.getElementsByTagName("w:r").item(0);
if (parentNode != null) {
NodeList fontNodes = parentNode.getElementsByTagName("w:rPr");
if (fontNodes.getLength() > 0) {
Element fontNode = (Element) fontNodes.item(0);
Element fontFamilyNode = (Element) fontNode.getElementsByTagName("w:rFonts").item(0);
if (fontFamilyNode != null) {
fontFamily = fontFamilyNode.getAttribute("w:ascii");
if ("".equals(fontFamily)) {
fontFamily = fontFamilyNode.getAttribute("w:cs");
if ("".equals(fontFamily)) {
fontFamily = "汉仪书宋一简";
}
}
}
Element fontSizeNode = (Element) fontNode.getElementsByTagName("w:sz").item(0);
if (fontSizeNode != null) {
fontSize = fontSizeNode.getAttribute("w:val");
} else {
// 默认字体大小
fontSize = "24";
}
}
}
FontDto fontDto = new FontDto();
fontDto.setFont(fontFamily);
fontDto.setFontSize(fontSize);
fontMap.put(text, fontDto);
}
} else {
throw new RuntimeException("文件中不存在这样的数据");
}
} catch (Exception e) {
e.printStackTrace();
}
return fontMap;
}
public static Boolean checkBold(XWPFParagraph paragraph) {
List<XWPFRun> runs = paragraph.getRuns();
for (XWPFRun run : runs) {
if (run.isBold()) {
return true;
}
}
return false;
}
public static Boolean checkBold(XWPFTableCell cell) {
for (XWPFParagraph paragraph : cell.getParagraphs()) {
// 检查段落对齐方式
ParagraphAlignment alignment = paragraph.getAlignment();
boolean isCenterAligned = alignment == ParagraphAlignment.CENTER;
// 遍历段落中的所有文本运行,检查加粗属性
for (XWPFRun run : paragraph.getRuns()) {
return run.isBold();
}
}
return false;
}
public static Boolean checkCenter(XWPFTableCell cell) {
for (XWPFParagraph paragraph : cell.getParagraphs()) {
// 检查段落对齐方式
ParagraphAlignment alignment = paragraph.getAlignment();
if (alignment == ParagraphAlignment.CENTER) {
return true;
}
}
return false;
}
public static Boolean checkCenter(XWPFParagraph paragraph) {
ParagraphAlignment alignment = paragraph.getAlignment();
if (alignment == ParagraphAlignment.CENTER) {
return true;
}
return false;
}
fontDto类:
public class FontDto {
private String font;
private String fontSize;
public String getFont() {
return font;
}
public void setFont(String font) {
this.font = font;
}
public String getFontSize() {
return fontSize;
}
public void setFontSize(String fontSize) {
this.fontSize = fontSize;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
FontDto fontDto = (FontDto) o;
return Objects.equals(font, fontDto.font) &&
Objects.equals(fontSize, fontDto.fontSize);
}
@Override
public int hashCode() {
return Objects.hash(font, fontSize);
}
}
这里只展示了获取word中每个段落的样式,在不同的需求中基本都会解析获取样式信息。如果只解析文档文字部分内容,直接调用上述的方法即可。获取Map是为了再一次解析文件保存文本内容时能够直接获取到当前文本的样式信息。解析文本的信息依旧采用poi的方式进行解析。
3.调用解析方法
@PostMapping("/word")
public ApiResult<List<FontDto>> analyzeWord(@RequestPart("file")MultipartFile file){
return ApiResult.success(service.analyzeWord(file));
}
3.调用解析方法
@PostMapping("/word")
public ApiResult<List<FontDto>> analyzeWord(@RequestPart("file")MultipartFile file){
return ApiResult.success(service.analyzeWord(file));
}