xml方式導出word優缺點:
優點:
1、代碼量少,樣式、內容容易控制,打印不變形,符合office標准;
2、支持Linux平台,不要求安裝office;
3、可以實現固定格式文檔輸出;
4、支持添加圖片;
缺點:
1、需要提前設計好word模板,把需要替換的地方用特殊標記標出來;
2、若要在word中添加圖片,需要在設計模板時加入一張圖片進行占位,然后手動編輯xml模板文檔;
1、XmlWord類的使用(使用org.w3c.dom操作XML)
XmlWord類源碼:XmlWord.txt
示例代碼所用模板:2.xml
【注】:創建模板的office需2003及以上版本。
使用步驟:
1、創建一個需要導出word模板;
2、創建一個XmlWord對象;
3、若模板標記有多個,存儲至list中;存儲替換值;
4、生成word文檔;
[示例代碼]:
XmlWord test = new XmlWord();
//1、載入模板
Document doc = test.LoadXml("2.xml");
//2、設置標記,tagList中存放的標記要同模板中的標記一致;
List<String> tagList = new ArrayList<String>();
tagList.add("${test_name}");
tagList.add("${test_no}");
//3、設置填充標記的值,dataList中存放數據順序與tagList存放標記順序一致;
List<String> dataList = new ArrayList<String>();
dataList.add("----用例名");
dataList.add("----用例編號");
//4、將標記和標記值存入dataMap
test.setData(tagList, dataList);
//5、替換值
/*添加圖片*/
test.replacePic(doc.getDocumentElement(), "${img}", "8.jpg", imgStr);
test.replaceTagContext(doc.getDocumentElement());
//6、寫入文檔
test.doc2DocFile(doc, "xmlword.doc");
2、特殊說明
1、word模板制作:
使用office 2003及以上版本寫一個需要導出的word模板,然后編輯文檔的樣式,將需要動態填充的內容,使用特殊標記替換,如實例代碼中的標記(${test_name}),最后將編輯后的word文檔另存為為“Word 2003 XML 文檔(*.xml)”格式,將模板放置在工程下。
2、添加圖片:
如果需要在word中添加圖片,在第一步制作模板時,加入一張圖片占位,然后打開xml文檔,可以看到如下的一片base64編碼后的代碼:
<w:binData w:name="wordml://03001.png" xml:space="preserve">iVBO……CC</w:binData>
只要將base64的代碼替換成例如:${image},如下:
<w:binData w:name="wordml://03001.png" xml:space="preserve">${image}</w:binData>
這里要注意“>${image}<”這尖括號中間不能加任何其他的諸如空格,tab,換行等符號,否則導出的word將會出錯。
3、XmlWord類說明
Properties:
變量 |
說明 |
Map<String,String> dataMap |
用於當模板中有多個標記時存放標記值及替換數據。
|
Methods:
方法 |
參數 |
返回值 |
LoadXml(String filename):Document 載入一個xml文檔 |
filename:模板路徑 |
成功返回Document對象; 失敗返回null |
getImageStr(String imgFile):String 圖片轉碼 |
ImgFile:圖片全路徑名 |
返回圖片base64字符串 |
doc2DocFile(Document document,String filename):boolean 將Document對象保存為一個Doc文件 |
filename:保存的文件名 document:需要保存的Document對象 |
true:保存成功 false:保存失敗 |
replaceTagContext(Element element,String tag,String data):Element 替換標識內容:單個標記(僅用於替換文本) |
element:要填充內容的節點 tag:模板中標記 data:數據 |
返回替換后的節點 |
replaceTagContext(Element element):Element 替換標識內容:多個標記,調用此方法前,先調用setData方法(僅用於替換文本) |
element:要替換內容的節點 |
返回替換后的節點 |
replacePic(Object element,String tag,String imgName,String imgStr):Element 添加圖片,此方法僅適用於單張圖片的添加,多圖添加可參考該方法源碼 |
element:要替換內容的節點 tag:模板中圖片標記 imgName:圖片名稱,若word中有多張圖,圖片名必須唯一 imgStr:圖片轉碼后的base64字符串 |
返回替換后的節點 |
本類目前僅能支持文本、圖片分次替換,未實現文本同圖片的同時替換。
模板:
導出后效果:
XmlWord類代碼:
package com.hxh.test; 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.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import sun.misc.BASE64Encoder; public class XmlWord { private Map<String,String> dataMap = new HashMap<String,String>(); public Map<String, String> getDataMap() { return dataMap; } public void setDataMap(Map<String, String> dataMap) { this.dataMap = dataMap; } /** * 設置標識值 * @param tagList 標識 * @param dataList 數據 * @param dataMap */ public void setData(List<String> tagList,List<String> dataList){ Iterator<String> it1 = tagList.iterator(); Iterator<String> it2 = dataList.iterator(); while(it1.hasNext()){ this.dataMap.put(it1.next(), it2.next()); } } /** * 載入一個xml文檔 * @param filename 文件路徑 * @return 成功返回Document對象,失敗返回null */ public Document LoadXml(String filename){ Document doc = null; try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); doc = (Document) builder.parse(new File(filename)); } catch (Exception e) { System.out.println("載入xml文件時出錯"); e.printStackTrace(); } return doc; } /** * 圖片轉碼 * @return 返回圖片base64字符串 * @throws Exception */ public String getImageStr(String imgFile){ InputStream in = null; BASE64Encoder encoder = null; byte[] data = null; try { in = new FileInputStream(imgFile); } catch (FileNotFoundException e) { System.out.println("文件沒找到!"); e.printStackTrace(); } try { data = new byte[in.available()]; in.read(data); in.close(); } catch (IOException e) { e.printStackTrace(); } encoder = new BASE64Encoder(); return encoder.encode(data); } /** * doc2XmlFile * 將Document對象保存為一個xml文件 * @return true:保存成功 flase:失敗 * @param filename 保存的文件名 * @param document 需要保存的document對象 */ public boolean doc2XmlFile(Document document,String filename) { boolean flag = true; try{ TransformerFactory transFactory = TransformerFactory.newInstance(); Transformer transformer = transFactory.newTransformer(); DOMSource source=new DOMSource(); source.setNode(document); StreamResult result=new StreamResult(); FileOutputStream fileOutputStream = new FileOutputStream(filename); result.setOutputStream(fileOutputStream); transformer.transform(source, result); fileOutputStream.close(); }catch(Exception ex){ flag = false; ex.printStackTrace(); } return flag; } /** * 替換標識內容:單個文本標記 * @param element 要替換內容的節點 * @param tag 標識名稱 * @param data 替換參數 * @return 返回替換后的節點 * @throws Exception */ public Element replaceTagContext(Object element,String tag,String data){ Element xElement = null; xElement = (Element) element; NodeList tElements = xElement.getElementsByTagName("w:t");//w:t標簽組 for(int i=0; i<tElements.getLength(); i++){ Element tElement = (Element)tElements.item(i); if(tElement.getTextContent().equals(tag)){ tElement.setTextContent(data); } } return xElement; } /** * 替換標識內容:多個文本標記 * @param element 要替換內容的節點 * @return 返回替換后的節點 * @throws Exception */ public Element replaceTagContext(Element element){ Element xElement = element; NodeList tElements = xElement.getElementsByTagName("w:t");//w:t標簽組 Set<String> dataSet = this.dataMap.keySet(); Iterator<String> it = dataSet.iterator(); while(it.hasNext()){ String tag = it.next(); String data = dataMap.get(tag); for(int i=0; i<tElements.getLength(); i++){ Element tElement = (Element)tElements.item(i); if(tElement.getTextContent().equals(tag)){ tElement.setTextContent(data); } } } return xElement; } /** * 添加圖片 * @param element 需要替換內容的節點 * @param tag 標識名稱 * @param imgName 圖片名稱,若word中有多張圖,圖片名必須唯一 * @param imgStr 圖片轉碼后的base64字符串 * @return 返回替換后的節點 */ public Element replacePic(Element element,String tag,String imgName,String imgFile){ Element xElement = element; NodeList tElements = xElement.getElementsByTagName("w:binData");//w:t標簽組 pkg:binaryData String wName = "wordml://"+imgName; for(int i=0; i<tElements.getLength(); i++){ Element picElement = (Element)tElements.item(i); if(picElement.getTextContent().equals(tag)){ picElement.setTextContent(this.getImageStr(imgFile));/*圖片編碼*/ picElement.setAttribute("w:name",wName);//設置名字 Element imagedataElement = (Element) xElement.getElementsByTagName("v:imagedata").item(i); imagedataElement.setAttribute("src",wName); } } return xElement; } /** * 插入圖片 * @param parentElement 圖片添加至何處 * @param imgFile 圖片路徑 * @param isnewLine 是否換行 * @return 返回添加圖片節點后的節點 */ public Element addPic(Element parentElement,String imgFile,boolean isnewLine){ Document parent = parentElement.getOwnerDocument(); Element p = null; Element pict = null; Element binData = null; Element shape = null; Element imagedata = null; String src = "wordml://" + new Date().getTime(); if(isnewLine){ p = parent.createElement("w:p"); } pict = parent.createElement("w:pict"); binData = parent.createElement("w:binData"); binData.setAttribute("w:name", src); binData.setAttribute("xml:space", "preserve"); binData.setTextContent(this.getImageStr(imgFile)); shape = parent.createElement("v:shape"); imagedata = parent.createElement("v:imagedata"); imagedata.setAttribute("src", src); //構造圖片節點 shape.appendChild(imagedata); pict.appendChild(binData); pict.appendChild(shape); if(isnewLine){ p.appendChild(pict); parentElement.appendChild(p); }else{ parentElement.appendChild(pict); } return parentElement; } /** * 插入段落 * @param parentElement 待添加段落的節點 * @param data 待插入數據 * @return */ public Element addParagraph(Element parentElement,String data){ Document parent = parentElement.getOwnerDocument(); Element p = null; Element r = null; Element t = null; p = parent.createElement("w:p"); r = parent.createElement("w:r"); t = parent.createElement("w:t"); t.setTextContent(data); //構造圖片節點 r.appendChild(t); p.appendChild(r); parentElement.appendChild(p); return parentElement; } }