引言
思路word中的docx是 Office Open XML 标准的文档格式,所以可以通过apache 的poi解析,docx的文档组件在poi中的结构是这样的
word文档 的组件 | poi中的对象 |
---|---|
word文件 | XWPFDocument |
段落 | XWPFParagraph |
表格 | XWPFTable |
自动编号 | XWPFParagraph.getNumFmt() |
段落中的小单元,可以是一个图片或文字或公式 | 文本是XWPFRun,图片是XWPFPicture,公式是CTOMath |
第一步处理自动编号和XWPFRun与CTOMath的顺序问题
public static String parseDocxContentToHTML(InputStream input, ImageParse imageParser) throws IOException {
if (input == null) {
throw new RuntimeException("请输入要转的docx的文件");
}
StringBuilder content = new StringBuilder();
Map<BigInteger, IWordNumber> wordNumberMap = new HashMap<BigInteger, IWordNumber>();
XWPFDocument docx = new XWPFDocument(input);
// 拿到所有的段落的表格,这两个属于同级无素
List<IBodyElement> elements = docx.getBodyElements();
for (IBodyElement body : elements) {
if (body.getElementType().equals(BodyElementType.PARAGRAPH)) {
handleParagraph(content, body, wordNumberMap, imageParser);
} else if (body.getElementType().equals(BodyElementType.TABLE)) {
handleTable(content, body, wordNumberMap, imageParser);
}
}
return content.toString();
}
第二步,分别处理段和表格
private static void handleParagraph(StringBuilder content, IBodyElement body, Map<BigInteger, IWordNumber> wordNumberMap, ImageParse imageParser) {
XWPFParagraph p = (XWPFParagraph) body;
if (p.isEmpty() || p.isWordWrap() || p.isPageBreak()) {
return;
}
String tagName = "p";
content.append("<" + tagName + ">");
// 自动编号
handleWordNumber(content, wordNumberMap, p);
/*XWPFParagraph 有两个方法可以分别提出XWPFRun和CTOMath,但是不知道位置
ParagraphChildOrderManager这个类是专门解决这个问题的
*/
ParagraphChildOrderManager runOrMaths = new ParagraphChildOrderManager(p);
List<Object> childList = runOrMaths.getChildList();
for (Object child : childList) {
if (child instanceof XWPFRun) {
handleParagraphRun(content, (XWPFRun) child, imageParser);
} else if (child instanceof CTOMath) {
handleParagraphOMath(content, (CTOMath) child, imageParser);
}
}
content.append("</" + tagName + ">");
}
//可以把公式和XWPFRun按顺序遍历,用到了以CTP开头的底层方式,中间也参观了别的人实现,自己改造
public class ParagraphChildOrderManager {
public static int TYPE_RUN = 1;
public static int TYPE_OMATH = 2;
List<Integer> typeList = new ArrayList<>();
XWPFParagraph p;
public ParagraphChildOrderManager(XWPFParagraph paragraph) {
this.p = paragraph;
List<CTOMathPara> oMathParaList = paragraph.getCTP().getOMathParaList();
//using a cursor to go through the paragraph from top to down
XmlCursor xmlcursor = paragraph.getCTP().newCursor();
while (xmlcursor.hasNextToken()) {
XmlCursor.TokenType tokenType = xmlcursor.toNextToken();
if (tokenType.isStart()) {
if (xmlcursor.getName().getPrefix().equalsIgnoreCase("w") && xmlcursor.getName().getLocalPart().equalsIgnoreCase("r")) {
typeList.add(TYPE_RUN);
} else if (xmlcursor.getName().getLocalPart().equalsIgnoreCase("oMath")) {
typeList.add(TYPE_OMATH);
}
} else if (tokenType.isEnd()) {
xmlcursor.push();
xmlcursor.toParent();
if (xmlcursor.getName().getLocalPart().equalsIgnoreCase("p")) {
break;
}
xmlcursor.pop();
}
}
}
public List<Object> getChildList() {
List<Object> runsOrMathList = new ArrayList<>();
List<XWPFRun> runs = p.getRuns();
List<CTOMath> oMathList = p.getCTP().getOMathList();
int totalRuns = runs.size() + oMathList.size();
if (typeList.size() != totalRuns) {
throw new RuntimeException(" word 文件解析公式有问题,请与管理员联系");
}
Queue<XWPFRun> runsQueue = new LinkedList<>(runs);
Queue<CTOMath> mathQueue = new LinkedList<>(oMathList);
for (int i = 0; i < typeList.size(); i++) {
Integer type = typeList.get(i);
if (type.equals(TYPE_RUN) && runs.size() > 0) {
runsOrMathList.add(runsQueue.poll());
} else if (type.equals(TYPE_OMATH) && mathQueue.size() > 0) {
runsOrMathList.add(mathQueue.poll());
}
}
return runsOrMathList;
}
}
// 处理自动编号的代码如下
private static void handleWordNumber(StringBuilder sb, Map<BigInteger, IWordNumber> wordNumberMap, XWPFParagraph p) {
String prefix = null;
if (wordNumberMap != null && p.getNumID() != null && p.getNumFmt() != null) {
IWordNumber wn = wordNumberMap.get(p.getNumID());
if (wn != null) {
prefix = wn.nextNum();
} else {
IWordNumber newWordNumber = WordNumberFactory.getWordNumber(p.getNumFmt(), p.getNumLevelText());
if (newWordNumber != null) {
wordNumberMap.put(p.getNumID(), newWordNumber);
prefix = newWordNumber.nextNum();
}
}
}
if (StringUtils.isNotBlank(prefix)) {
sb.append(prefix);
}
}
// 这里贴了数字和自动编号的实现,虽的类似,我就不贴了
public class WordNumberFactory {
public static IWordNumber getWordNumber(String numFmt, String numLevelText) {
if ("decimal".equals(numFmt)) {
return new DecimalNumber(numLevelText);
} else if ("upperLetter".equals(numFmt)) {
return new UpperLetterNumber(numLevelText);
} else if ("japaneseCounting".equals(numFmt)) {
return new JapaneseCountingNumber(numLevelText);
}
return null;
}
}
public class DecimalNumber extends BaseNumber implements IWordNumber {
int number = 0;
public DecimalNumber(String splitChar) {
super(splitChar);
}
@Override
public String nextNum() {
number++;
return number + this.splitChar;
}
}
public class UpperLetterNumber extends BaseNumber implements IWordNumber {
char number = 'A';
public UpperLetterNumber(String splitChar) {
super(splitChar);
}
@Override
public String nextNum() {
String value = number + this.splitChar;
number++;
return value;
}
}
public class JapaneseCountingNumber extends BaseNumber implements IWordNumber {
String[] baseWord = {"十", "一", "二", "三", "四", "五", "六", "七", "八", "九"};
String dot = "、";
int count = 0;
public JapaneseCountingNumber(String splitChar) {
super(splitChar);
}
@Override
public String nextNum() {
count++;
int unit = 0;
if (count > 99) {
throw new RuntimeException("仅支持100以下的自动编码");
}
if (count > 19) {
int ten = count / 10;
unit = count % 10;
if (unit == 0) {
return baseWord[ten] + "十" + dot;
} else {
return baseWord[ten] + "十" + baseWord[unit] + dot;
}
}
if (count > 10) {
unit = count % 10;
return "十" + baseWord[unit] + dot;
}
unit = count % 10;
return baseWord[unit] + dot;
}
}
public class BaseNumber {
BigInteger numberId;
String fmt;
String splitChar = ".";
public BaseNumber(String splitChar) {
if (splitChar.startsWith("%1")) {
this.splitChar = splitChar.replace("%1", "");
}
}
@Override
public boolean equals(Object obj) {
if (obj == null || this.getClass() != obj.getClass()) return false;
BaseNumber bn = (BaseNumber) obj;
if (bn.numberId == null || this.numberId == null) return false;
if (bn.numberId == this.numberId) {
return true;
}
return false;
}
@Override
public int hashCode() {
return numberId == null ? 0 : numberId.hashCode();
}
}
public interface IWordNumber {
public String nextNum();
}
// 结束处理自动编号
### 处理XWPFRun
private static void handleParagraphRun(StringBuilder content, XWPFRun run, ImageParse imageParser) {
//char[] runChars = run.toString().toCharArray();
// 有内嵌的图片
List<XWPFPicture> pics = run.getEmbeddedPictures();
if (pics != null && pics.size() > 0) {
handleParagraphRunsImage(content, pics, imageParser);
} else if (isMath(run)) {// 处理wps的公式图片
handleParagraphRunsImageMath(content, run, imageParser);
} else { //处理文本
handleParagraphRunsWithText(content, run);
}
}
// 处理图片
private static void handleParagraphRunsImage(StringBuilder content, List<XWPFPicture> pics, ImageParse imageParser) {
for (XWPFPicture pic : pics) {
String desc = pic.getDescription();
String path = imageParser.parse(pic.getPictureData().getData(),
pic.getPictureData().getFileName());
log.debug("pic.getPictureData().getFileName()===" + pic.getPictureData().getFileName());
CTPicture ctPicture = pic.getCTPicture();
Node domNode = ctPicture.getDomNode();
Node extNode = getChildChainNode(domNode, "pic:spPr", "a:ext");
NamedNodeMap attributes = extNode.getAttributes();
if (attributes != null && attributes.getNamedItem("cx") != null) {
int width = WordMyUnits.emuToPx(new Double(attributes.getNamedItem("cx").getNodeValue()));
int height = WordMyUnits.emuToPx(new Double(attributes.getNamedItem("cy").getNodeValue()));
content.append(String.format("<img src=\"%s\" width=\"%d\" height=\"%d\" />", path, width, height));
} else {
content.append(String.format("<img src=\"%s\" />", path));
}
}
}
// 处理wps的内嵌的图片公式,里面有wmf to svg的工具类
private static boolean isMath(XWPFRun run) {
Node runNode = run.getCTR().getDomNode();
Node objectNode = getChildNode(runNode, "w:object");
if (objectNode == null) {
return false;
}
Node shapeNode = getChildNode(objectNode, "v:shape");
if (shapeNode == null) {
return false;
}
Node imageNode = getChildNode(shapeNode, "v:imagedata");
if (imageNode == null) {
return false;
}
Node binNode = getChildNode(objectNode, "o:OLEObject");
if (binNode == null) {
return false;
}
return true;
}
private static void handleParagraphRunsImageMath(StringBuilder content, XWPFRun run, ImageParse imageParser) {
Node runNode = run.getCTR().getDomNode();
XWPFDocument runDocument = run.getDocument();
Node objectNode = getChildNode(runNode, "w:object");
if (objectNode == null) {
return;
}
Node shapeNode = getChildNode(objectNode, "v:shape");
if (shapeNode == null) {
return;
}
Node imageNode = getChildNode(shapeNode, "v:imagedata");
if (imageNode == null) {
return;
}
Node binNode = getChildNode(objectNode, "o:OLEObject");
if (binNode == null) {
return;
}
NamedNodeMap shapeAttrs = shapeNode.getAttributes();
// 图片在Word中显示的宽高
String style = shapeAttrs.getNamedItem("style").getNodeValue();
NamedNodeMap imageAttrs = imageNode.getAttributes();
// 图片在Word中的ID
String imageRid = imageAttrs.getNamedItem("r:id").getNodeValue();
// 获取图片信息
PackagePart imgPart = runDocument.getPartById(imageRid);
// word/media/image4.wmf
String fullName = imgPart.getPartName().getName();
log.debug("pic.Match.fullName==" + fullName);
String extName = imgPart.getPartName().getExtension();
Pattern p = Pattern.compile("\\w+\\." + extName);
Matcher matcher = p.matcher(fullName);
if (matcher.find()) {
fullName = matcher.group(0);
}
log.debug("pic.Match.name==" + fullName);
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
WmfUtils.toSvg(imgPart.getInputStream(), out);
fullName = fullName.replace(extName, "svg");
String path = imageParser.parse(new ByteArrayInputStream(out.toByteArray()), fullName);
content.append("<img src=\"" + path + "\" style=\"" + style + "\"/>");
} catch (IOException e) {
e.printStackTrace();
}
}
// 处理文本的html样式
private static void handleParagraphRunsWithText(StringBuilder content, XWPFRun run) {
String c = run.toString();
c = escapeHtmlTag(c);
if (c == null || c.length() == 0) {
return;
}
if (run.getSubscript() != null) {
VerticalAlign va = run.getSubscript();
if (va.equals(VerticalAlign.SUBSCRIPT)) {
c = "<sub>" + c + "</sub>";
} else if (va.equals(VerticalAlign.SUPERSCRIPT)) {
c = "<sup>" + c + "</sup>";
}
}
if (run.isBold()) {
c = "<b>" + c + "</b>";
} else if (run.isItalic()) {
c = "<i>" + c + "</i>";
} else if (run.isStrikeThrough()) {
c = "<strike>" + c + "</strike>";
}
if (run.getUnderline() != null && run.getUnderline() != UnderlinePatterns.NONE) {
c = "<span style='text-decoration: underline;'>" + c + "</span>";
}
if (run.getColor() != null) {
c = "<span style='color:#" + run.getColor().toLowerCase() + ";'>" + c + "</span>";
}
content.append(c);
}
private static String escapeHtmlTag(String text) {
text = text.replace("&", "&");
text = text.replace("<", "<");
text = text.replace(">", ">");
return text;
}
段处理完,该公式了 CTOMath,该公式是微软自己的公式
private static void handleParagraphOMath(StringBuilder content, CTOMath child, ImageParse imageParser) {
String s = OmmlUtils.convertOmathToPng(child, imageParser);
content.append(s);
}
// omml先转成node,再转成string ,再转成mathML的string,再用第三工具生成图片
public class OmmlUtils {
/**
* 直接转node有等号会出问题,先转成xml的string,再转成mathML的字符串
*
* @param node
* @return
* @throws IOException
* @throws TransformerException
*/
private static String getMathMLFromNode(Node node) throws IOException, TransformerException {
final String xslFile = "/OMML2MML.XSL";
StreamSource streamSource = new StreamSource(OmmlUtils.class.getResourceAsStream(xslFile));
String s = W3cNodeUtil.node2XmlStr(node);
// encoding utf-16
String mathML = W3cNodeUtil.xml2Xml(s, streamSource);
mathML = mathML.replaceAll("xmlns:m=\"http://schemas.openxmlformats.org/officeDocument/2006/math\"", "");
mathML = mathML.replaceAll("xmlns:mml", "xmlns");
mathML = mathML.replaceAll("mml:", "");
return mathML;
}
public static String convertOmathToPng(XmlObject xmlObject, ImageParse imageParser) {
Document document = null;
try {
String mathMLStr = getMathMLFromNode(xmlObject.getDomNode());
document = W3cNodeUtil.xmlStr2Node(mathMLStr, "utf-16");
return documentToImageHTML(document, imageParser);
} catch (IOException e) {
e.printStackTrace();
} catch (TransformerException e) {
e.printStackTrace();
}
return null;
}
private static String documentToImageHTML(Document document, ImageParse imageParser) {
try {
Converter mathMLConvert = Converter.getInstance();
LayoutContextImpl localLayoutContextImpl = new LayoutContextImpl(LayoutContextImpl.getDefaultLayoutContext());
localLayoutContextImpl.setParameter(Parameter.MATHSIZE, 18);
ByteArrayOutputStream os = new ByteArrayOutputStream();
mathMLConvert.convert(document, os, "image/png", localLayoutContextImpl);
String pngName = imageParser.parse(os.toByteArray(), ".png");
os.close();
return "<img src=\"" + pngName + "\" align=\"absmiddle\"/>";
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
public class W3cNodeUtil {
public static String node2XmlStr(Node node) {
Transformer transformer = null;
if (node == null) {
throw new IllegalArgumentException("node 不能为空..");
}
try {
transformer = TransformerFactory.newInstance().newTransformer();
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
if (transformer != null) {
try {
StringWriter sw = new StringWriter();
transformer.transform(new DOMSource(node), new StreamResult(sw));
return sw.toString();
} catch (TransformerException te) {
throw new RuntimeException(te.getMessage());
}
}
return null;
}
public static String xml2Xml(String xml, Source XSLSource) {
Transformer transformer = null;
if (xml == null) {
throw new IllegalArgumentException("node 不能为空..");
}
try {
if (XSLSource == null) {
transformer = TransformerFactory.newInstance().newTransformer();
} else {
transformer = TransformerFactory.newInstance().newTransformer(XSLSource);
}
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
if (transformer != null) {
try {
Source source = new StreamSource(new StringReader(xml));
StringWriter sw = new StringWriter();
transformer.transform(source, new StreamResult(sw));
return sw.toString();
} catch (TransformerException te) {
throw new RuntimeException(te.getMessage());
}
}
return null;
}
public static Document xmlStr2Node(String xmlString, String encoding) {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
Document doc = null;
try {
InputStream is = new ByteArrayInputStream(xmlString.getBytes(encoding));
doc = dbf.newDocumentBuilder().parse(is);
is.close();
} catch (Exception e) {
e.printStackTrace();
}
return doc;
}
private static Node getChildNode(Node node, String nodeName) {
if (!node.hasChildNodes()) {
return null;
}
NodeList childNodes = node.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node childNode = childNodes.item(i);
if (nodeName.equals(childNode.getNodeName())) {
return childNode;
}
childNode = getChildNode(childNode, nodeName);
if (childNode != null) {
return childNode;
}
}
return null;
}
public static Node getChildChainNode(Node node, String... nodeName) {
Node childNode = node;
for (int i = 0; i < nodeName.length; i++) {
String tmp = nodeName[i];
childNode = getChildNode(childNode, tmp);
if (childNode == null) {
return null;
}
}
return childNode;
}
}
public class WordMyUnits {
public static final int EMU_PER_PX = 9525;
public static final int emuToPx(double emu) {
return (int) (emu/9525);
}
}
处理表格,表格就容易多了,
// 处理table
private static String handleTable(StringBuilder content, IBodyElement body, Map<BigInteger, IWordNumber> wordNumberMap, ImageParse imageParser) {
XWPFTable table = (XWPFTable) body;
List<XWPFTableRow> rows = table.getRows();
content.append("<table class=\"paper-table\">");
for (XWPFTableRow row : rows) {
content.append("<tr>");
List<XWPFTableCell> cells = row.getTableCells();
for (XWPFTableCell cell : cells) {
content.append("<td>");
List<XWPFParagraph> paragraphs = cell.getParagraphs();
for (XWPFParagraph paragraph : paragraphs) {
handleParagraph(content, paragraph, wordNumberMap, imageParser);
}
content.append("</td>\n");
}
content.append("</tr>\n");
}
content.append("</table>\n");
return null;
}
// 还有一个保存图片到硬盘上的类
public class ImageParse {
int number = 0;
private String targetDir;
private String baseUrl;
public ImageParse(String targetDir, String baseUrl) {
super();
this.targetDir = targetDir;
this.baseUrl = baseUrl;
}
public String parse(byte[] data, String extName) {
return parse(new ByteArrayInputStream(data), extName);
}
public String parse(InputStream in, String extName) {
if (extName.lastIndexOf(".") > -1) {
extName = extName.substring(extName.lastIndexOf(".") + 1);
}
String filename = "image_" + (number++) + "." + extName;
File target = new File(targetDir);
if (!target.exists()) {
target.mkdirs();
}
try {
IOUtils.copy(in, new FileOutputStream(new File(target, filename)));
} catch (IOException e) {
e.printStackTrace();
}
return baseUrl + filename;
}
}
public class WmfUtils {
public static void main(String[] args) {
String result = convert("D:\\06training\\docx\\image1.wmf");
System.out.println(result);
}
@Deprecated
public static String convert2(String path) throws TranscoderException,
IOException {
String wmfPath = path;
File wmf = new File(wmfPath);
FileInputStream wmfStream = new FileInputStream(wmf);
ByteArrayOutputStream imageOut = new ByteArrayOutputStream();
int noOfByteRead = 0;
while ((noOfByteRead = wmfStream.read()) != -1) {
imageOut.write(noOfByteRead);
}
imageOut.flush();
wmfStream.close();
// wmf 转换为svg
WMFTranscoder transcoder = new WMFTranscoder();
// TranscodingHints hints = new TranscodingHints();
// hints.put(WMFTranscoder.KEY_HEIGHT, 1000f);
// hints.put(WMFTranscoder.KEY_WIDTH, 1500f);
// transcoder.setTranscodingHints(hints);
TranscoderInput input = new TranscoderInput(new ByteArrayInputStream(
imageOut.toByteArray()));
ByteArrayOutputStream svg = new ByteArrayOutputStream();
TranscoderOutput output = new TranscoderOutput(svg);
transcoder.transcode(input, output);
String svgFile = FileExtNameUtils.replace(wmfPath, "wmf", "svg");
FileOutputStream fileOut = new FileOutputStream(svgFile);
fileOut.write(svg.toByteArray());
fileOut.flush();
fileOut.close();
svg.close();
// svg -> jpg
ImageTranscoder it = new JPEGTranscoder();
it.addTranscodingHint(JPEGTranscoder.KEY_QUALITY, 0.5);
ByteArrayOutputStream jpg = new ByteArrayOutputStream();
it.transcode(new TranscoderInput(new ByteArrayInputStream(svg
.toByteArray())), new TranscoderOutput(jpg));
String jpgFile = FileExtNameUtils.replace(wmfPath, "wmf", "jpg");
FileOutputStream jpgOut = new FileOutputStream(jpgFile);
jpgOut.write(jpg.toByteArray());
jpgOut.flush();
jpgOut.close();
jpg.close();
// Filor.deleteFile(svgFile);// 删除掉中间文件
return jpgFile;
}
public static String convert(String path) {
try {
String svgFile = FileExtNameUtils.replace(path, "wmf", "svg");
wmfToSvg(path, svgFile);
String jpgFile = FileExtNameUtils.replace(path, "wmf", "png");
svgToJpg(svgFile, jpgFile);
return jpgFile;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 将svg转化为JPG
*
* @param src
* @param dest
*/
public static String svgToJpg(String src, String dest) {
FileOutputStream jpgOut = null;
FileInputStream svgStream = null;
ByteArrayOutputStream svgOut = null;
ByteArrayInputStream svgInputStream = null;
ByteArrayOutputStream jpg = null;
try {
// 获取到svg文件
File svg = new File(src);
svgStream = new FileInputStream(svg);
svgOut = new ByteArrayOutputStream();
// 获取到svg的stream
int noOfByteRead = 0;
while ((noOfByteRead = svgStream.read()) != -1) {
svgOut.write(noOfByteRead);
}
JPEGTranscoder it = new JPEGTranscoder();
it.addTranscodingHint(JPEGTranscoder.KEY_QUALITY, (float) 1);
it.addTranscodingHint(ImageTranscoder.KEY_WIDTH, 200f);
jpg = new ByteArrayOutputStream();
svgInputStream = new ByteArrayInputStream(svgOut.toByteArray());
it.transcode(new TranscoderInput(svgInputStream),
new TranscoderOutput(jpg));
jpgOut = new FileOutputStream(dest);
jpgOut.write(jpg.toByteArray());
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (svgInputStream != null) {
svgInputStream.close();
}
if (jpg != null) {
jpg.close();
}
if (svgStream != null) {
svgStream.close();
}
if (svgOut != null) {
svgOut.close();
}
if (jpgOut != null) {
jpgOut.flush();
jpgOut.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return dest;
}
public static void toSvg(InputStream in, OutputStream out) {
try {
WmfParser parser = new WmfParser();
final SvgGdi gdi = new SvgGdi(false);
parser.parse(in, gdi);
Document doc = gdi.getDocument();
//OutputStream out = new FileOutputStream(dest);
//if (dest.endsWith(".svgz")) {
// out = new GZIPOutputStream(out);
// }
output(doc, out);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 将wmf转换为svg
*
* @param src
* @param dest
*/
public static void wmfToSvg(String src, String dest) {
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(src);
out = new FileOutputStream(dest);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
toSvg(in, out);
}
private static void output(Document doc, OutputStream out) throws Exception {
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer();
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC,
"-//W3C//DTD SVG 1.0//EN");
transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM,
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd");
transformer.transform(new DOMSource(doc), new StreamResult(out));
out.flush();
out.close();
}
}
public class FileExtNameUtils {
public static String replace(String wmfPath, String wmf, String jpg) {
int index = wmfPath.lastIndexOf("wmf");
if (index > -1) {
return wmfPath.substring(0, index) + jpg + wmfPath.substring(index + 3);
}
return wmfPath;
}
}
用到的jar包
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>ooxml-schemas</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>net.arnx</groupId>
<artifactId>wmf2svg</artifactId>
<version>0.9.8</version>
</dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-codec</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>net.sourceforge.jeuclid</groupId>
<artifactId>jeuclid-core</artifactId>
<version>3.1.9</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
中间也参观了好多网站,就不一一列出来了,当时找的也是晕头转向的,最后整理也是相当费时间