java通過xml配置屬性用iText包生成pdf檔案
總共步驟為:1、提供一個需要替換引數傳入類;2、解析xml檔案,替換xml檔案中的特定引數(寫死格式);3、解析xml檔案中的pdf檔案佈局(包括表、段落、文字、換行等);
4、生成pdf檔案。
第一步:引數可以用map存放,根據相應的key可以取到對應的值,如果值為List,則可用來替換表格中的引數,根據List大小擴充套件表格的行數。
第二步:解析xml檔案,可以直接用dom4j進行解析標準格式的xml檔案。此次先用檔案流進行解析吧,方便將拿到的引數進行字串替換操作。解析程式碼如下:
/** * 逐行讀取傳入的檔案內容 * @param filepath 檔案絕對路徑和檔名 * @return 存放檔案全部內容的String * @throws Exception */ public static String readFile(String filepath) throws Exception { InputStreamReader read = null; BufferedReader bufferedReader = null; FileInputStream fileInput = null; try { fileInput = new FileInputStream(filepath); read = new InputStreamReader(fileInput, "GBK");//讀取檔案流內容 bufferedReader = new BufferedReader(read); String lineTxt = null; StringBuffer buffer = new StringBuffer(); while ((lineTxt = bufferedReader.readLine()) != null) { buffer.append(lineTxt + "\r\n"); } String str1 = buffer.toString(); return str1; }
<span style="white-space:pre"> </span>finally {
if (bufferedReader != null)
bufferedReader.close();
if (read != null)
read.close();
if(fileInput != null)
fileInput.close();
}
}
將檔案內容按節點進行拆分為檔案頭與檔案體,檔案頭存放字型配置檔案頭、檔案頁的資訊,檔案體存放具體需要展示的pdf內容。用第一步set進的物件中的map內容,替換返回的Str中的內容。
示例一種根據特定的xml格式設定的表示式替換方法,程式碼如下:
2016/05/05 就寫到這了。/** * 找到始終的表示式,並進行替換。 表示式的格式為: ${status.index -----} * @param str * @param statusName * @param index * @return * @throws Exception */ private String findExpressAndReplace(String str, String statusName, int index) throws Exception { if ((statusName == null) || (statusName.trim().equals(""))) return str; StringBuffer sb = new StringBuffer(); // Pattern pattern = Pattern.compile("\\$\\{[\\w\\W]*?" + statusName + "\\.index[\\w\\W]*?\\}"); Pattern pattern = Pattern.compile("\\$\\{" + statusName + "\\.index[\\w\\W]*?\\}"); Matcher m = pattern.matcher(str); while (m.find()) { String sValue = m.group(0); sValue = sValue.substring(2, sValue.length() - 1); sValue = sValue.replace(statusName + ".index", index+""); sValue = runJsExpression(sValue); m.appendReplacement(sb, sValue); } m.appendTail(sb); return sb.toString(); } private String runJsExpression(String expression) throws Exception { ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("JavaScript"); System.out.println("表示式計算結果為:"+engine.eval(expression).toString()); return engine.eval(expression).toString(); }
2016/05/06 開寫:
熟練運用正則表示式能節省很多程式碼。正則表示式一般包括兩種引擎,一種傳統NFA,一種DFA。java語言使用的是NFA引擎,使用表示式去匹配內容,當遇到第一個符合條件的值時,接收第一個匹配項。而DFA引擎則是用內容去匹配表示式。若需要匹配所有內容則需要用到Pattern與Matcher,用Matcher.find()讀取匹配的下一個字元序列。
第三步:使用jdom解析xml檔案,用模型物件儲存各個pdf物件的值。
此步驟需要有面向物件程式設計思想,首先需要一個DocModel存放包含全域性引數的全域性物件GlobalModel,以及包含內容引數的內容體物件BodyModel。
其次BodyModel向下可以包含pdf的各個組建物件,包括單行(p)、換頁(np)、圖片(img)、表格(table)、直線(line)、換行(br)。各個元組的內容append到BodyModel物件中。
第四步:建立各個物件元組的具體內容,加入到Document,生成pdf檔案。
主要呼叫iText包裡的方法set配置引數,生成pdf內容。程式碼如下:
/**
* 根據model物件的內容,開始寫入pdf檔案
* @param model 存放檔案內容檔案物件
* @param os 檔案輸出流
* @throws Exception
*/
public void create(DocModel model, OutputStream os) throws Exception {
this.docModel = model;
PageModel pageModel = this.docModel.getGlobalModel().getPage();
Document document = null;
try {
if ((pageModel.getMarginLeft() < 0) && (pageModel.getMarginRight() < 0) && (pageModel.getMarginTop() < 0) && (pageModel.getMarginBottom() < 0))
document = new Document(PageSize.A4); //如果page引數設定不完整,則預設使用A4大小
else {
document = new Document(PageSize.A4, pageModel.getMarginLeft(),
pageModel.getMarginRight(), pageModel.getMarginTop(),
pageModel.getMarginBottom());
}
this.pdfWriter = PdfWriter.getInstance(document, os);
document.setFooter(createHeaderFooter());
document.open();
createContent(document, this.docModel.getBodyModel().getCells());
} catch (Exception e) {
e.printStackTrace();
throw e;
} finally {
if (document != null)
document.close();
if (this.pdfWriter != null)
this.pdfWriter.close();
}
}
/**
* 新增各元組例項物件到Document中
* @param document
* @param cells
* @throws Exception
*/
private void createContent(Document document, List<CellModel> cells) throws Exception {
for (CellModel cell : cells)
if ((cell instanceof PModel)) //CellModel為所有模型均須實現的公共介面,可以用 instanceof 判斷具體內容具體是被哪個介面實現類例項化的
document.add((Element) new PCreator(this.docModel.getGlobalModel(), this.pdfWriter).create(cell));
else if ((cell instanceof LineModel))
{
new LineCreator(this.docModel.getGlobalModel(), this.pdfWriter,document, 10.0F).create(cell);
}
else if ((cell instanceof ImgModel))
document.add((Element) new ImgCreator(this.docModel.getGlobalModel(), this.pdfWriter).create(cell));
else if ((cell instanceof TableModel))
document.add((Element) new TableCreator(this.docModel.getGlobalModel(), this.pdfWriter, document).create(cell));
else if ((cell instanceof BrModel))
document.add((Element) new BrCreator(this.docModel.getGlobalModel(), this.pdfWriter).create(cell));
else if ((cell instanceof NpModel))
document.newPage();
}
到此處為止,pdf檔案已經生成完成。
後續需要好好研究一下正則表示式的使用,已經拓展面向物件程式設計思想。