xmlworker是一個基於iText的xml生成pdf工具。使用xmlworker是很是簡單的,思路也很清晰。獲取模板->拼裝模板->生成pdf。可是在過程當中仍是有一些小問題須要注意下。<p/>css
首先中文的問題,xmlworker默認是不支持中文的,須要修改源代碼從新打包才能支持亞洲字體(修改詳情)。<br/> 也能夠下載我已經編好的包: 修改com.itextpdf.tool.xml.css.apply.ChunkCssApplier.java 中的 public Chunk apply(final Chunk c, final Tag t) :<br/>html
Font f = applyFontStyles(t); // for chinese charater display @www.micmiu.com if (null != HTMLUtils.bfCN && HTMLUtils.isChinese(c.getContent())) { f = new Font(HTMLUtils.bfCN, f.getSize(), f.getStyle(), f.getColor()); } float size = f.getSize(); ......
<p/> 在com.itextpdf.tool.xml.html.HTMLUtils.java 中 增長下面用於中文字符判斷的方法:java
public static BaseFont bfCN = null; static { try { bfCN = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); } catch (Exception e) { } } // add by Michael more see:http://www.micmiu.com private static final boolean isChinese(char c) { Character.UnicodeBlock ub = Character.UnicodeBlock.of(c); if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) { return true; } return false; } // add by Michael more see:http://www.micmiu.com public static final boolean isChinese(String strName) { char[] ch = strName.toCharArray(); for (int i = 0; i < ch.length; i++) { char c = ch[i]; if (isChinese(c)) { return true; } } return false; }
其次,在寫html模板的時候,由於xmlworker支持的CSS樣式極少,因此模板內容要儘可能簡單。對於DOCTYPE和html標籤的約束頁比較嚴格。我使用的是<br/> `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">app
<html xmlns="http://www.w3.org/1999/xhtml">`。<br/> 對於一個標籤中含有中文、數字或英文的時候,極可能會出現字體變形。這是由於xmlworker在渲染PDF的時候是以html的標籤爲單位的。只要把中文和英文分隔在不一樣的標籤就能夠了。 最後貼上代碼做爲參考:<br/>maven
<!-- lang: java --> import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; import java.io.Writer; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import com.itextpdf.text.Document; import com.itextpdf.text.DocumentException; import com.itextpdf.text.pdf.PdfWriter; import com.itextpdf.tool.xml.XMLWorkerHelper; import freemarker.template.Configuration; import freemarker.template.DefaultObjectWrapper; import freemarker.template.Template; import freemarker.template.TemplateException; public class PDFOperation { public static void main(String[] args) throws Exception { // 獲取html內容 String html = getHtml(); // 生成pdf createPdf(html); } public static void createPdf(String html)throws DocumentException, IOException { String file = "E:/detail.pdf"; Document doc = new Document(); PdfWriter writer = PdfWriter.getInstance(doc, new FileOutputStream(file)); doc.open(); XMLWorkerHelper.getInstance().parseXHtml(writer, doc,new StringReader(html)); doc.close(); } public static String getHtml() throws IOException, TemplateException{ Configuration cfg = new Configuration(); cfg.setDirectoryForTemplateLoading(new File("E:/templatedir/")); cfg.setObjectWrapper(new DefaultObjectWrapper()); Template t = cfg.getTemplate("test.ftl"); Writer out = new StringWriter(); Map<String,Object> map = new HashMap<String,Object>(); Map<String,Object> req = new HashMap<String,Object>(); req.put("title","XXX"); req.put("ctime", "2014.05.06"); req.put("province", "北京"); List<Map<String,Object>> files = new ArrayList<Map<String,Object>>(); Map<String,Object> file1 = new HashMap<String,Object>(); Map<String,Object> file2 = new HashMap<String,Object>(); file1.put("url", "http://xxx"); file1.put("name", "FreeMarker_Manual_zh_CN.pdf"); file1.put("ext","pdf"); file2.put("url", "http://xxx"); file2.put("name", "OReilly.Redis.Cookbook.2011.pdf"); file2.put("ext","pdf"); files.add(file1); files.add(file2); map.put("files", files); map.put("map",map); t.process(map, out); out.flush(); return out.toString(); } }
ftl模板:工具
<!-- lang: html --> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title></title> </head> <body> <div style="padding:24px;color:#3a3b3b;background-color:#f4f4f4;line-height:28px;"> <h1 style="color:#98989a;font-weight:bold;font-size:24px;text-align:left;">DO NOT COPY</h1> <div style="background-color:#fff;padding:16px 24px;width:100%;"> <h1>${map.title}</h1> <h5 style="color:#848484;font-weight:normal;"><span>${map.ctime}</span></h5> </div> <div style="height:24px;"> </div> <div style="background-color:#fff;padding:16px 24px;width:100%;"> <h2>說明</h2> <div style="height:1px;background-color:#dbdbdb;width:100%;"> </div> <div style="height:16px;width:100%;"> </div> <ul style="list-style-type:none;margin:0px;padding:0px;padding-left:24px;"> <li><span style="color:#848484">地區</span> ${map.province?default('')}</li> </ul> <#if files ?exists > <h3>附件</h3> <div style="background-color:#eee;width:100%;padding:12px;padding-left:24px;">文件</div> <ul style="list-style-type:none;margin:0px;padding:0px;padding-left:24px;padding-right:24px;"> <#list files as f> <li style="margin:0px;padding:12px 0;"><a href="${f.url}"><span>${f.name}</span>.<span>${f.ext}</span></a></li> </#list> </ul> </#if> </div> <h1 style="color:#98989a;font-weight:bold;font-size:24px;text-align:right;">DO NOT COPY</h1> </div> </body> </html>
<p/> ##如下是可能提供幫助的資料: [支持的樣式表][5]<br/> [HTML生成PDF在線測試][6]<br/> [itextpdf in action中的源碼樣例][7]<br/> [編譯好的xmlworker-cn.jar][8],若是使用maven並有私庫,須要部署到私庫。version=5.5.0,groupId=com.itextpdf.tool,artifactId=xmlworker-cn<br/>測試