一、整体思路
1.因为项目中打印pdf多为表格,所以将所有组件统一使用表格处理。对单元格的边框做处理,达到普通文本的目的
2.xml定义表格的格式及普通文本内容,使用{{变量名称}}来表示需要使用变量替换。
3.考虑到一个pdf中可能有多个数据源,所以使用map来传递参数。
二、实现
1.xml及dtd定义。
这里有一个问题没有解决,那就是dtd文件的位置。先附上代码,待会说问题
我用eclipse新建的java project,新建文件夹xml-config并加入build path,然后在xml-config下直接存储xml文件,NewFile.xml文件内容如下:
事务所基本信息
基本情况
名称
{{cpafName}}
所属行政区划
{{divisionProvince}}
组织形式
{{orgForm}}
执业许可批准日期
{{approDate}}
统一社会信用代码
{{regisCno}}
执业许可批准文号
{{rna}}
执业证书编号
{{cpafCno}}
注册资本(出资总额)(单位:万元)
{{totalInves}}
分所数量
{{cpafbNum}}
国际网络名称(如有)
{{internetName}}
经营场所
{{officeLocation}}
通讯地址
{{address}}
报备业务联系人
{{reporter}}
电子邮箱
{{email}}
报备业务联系电话
{{phone}}
测试横向页面
基本情况
名称
{{cpafName}}
所属行政区划
{{divisionProvince}}
组织形式
{{orgForm}}
执业许可批准日期
{{approDate}}
统一社会信用代码
{{regisCno}}
执业许可批准文号
{{rna}}
执业证书编号
{{cpafCno}}
注册资本(出资总额)(单位:万元)
{{totalInves}}
分所数量
{{cpafbNum}}
国际网络名称(如有)
{{internetName}}
经营场所
{{officeLocation}}
通讯地址
{{address}}
报备业务联系人
{{reporter}}
电子邮箱
{{email}}
报备业务联系电话
{{phone}}
dtd文件内容如下
dtd主要是对xml内容的约束与检查。问题是,不管是单独将dtd放在xml-config,还是工程根目录下,都会报错,说在另一个位置找不到dtd,但是在两个位置都放dtd,则可以运行。至今不知道为什么。
2.将xml中的内容翻译为bean
Tablepage
package com.ufgov.pdf.entity;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/**
* 对应xml中的tablepage标签
*
* @author lihh
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "tablepage")
@XmlType(propOrder = { "title", "tableList" })
public class Tablepage {
@XmlElement(name = "title")
private Title title;
@XmlElementWrapper(name = "tables")
@XmlElement(name = "table")
private List tableList;
public Title getTitle() {
return title;
}
public void setTitle(Title title) {
this.title = title;
}
public List getTableList() {
return tableList;
}
public void setTableList(List tableList) {
this.tableList = tableList;
}
}
Title
package com.ufgov.pdf.entity;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(propOrder = { "text" })
public class Title {
@XmlElement(name = "text", required = true)
private String text;
@XmlAttribute(name = "align")
private String align;
@XmlAttribute(name = "v-align")
private String vAlign;
@XmlAttribute(name = "font-family")
private String fontFamily;
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getAlign() {
return align;
}
public void setAlign(String align) {
this.align = align;
}
public String getvAlign() {
return vAlign;
}
public void setvAlign(String vAlign) {
this.vAlign = vAlign;
}
public String getFontFamily() {
return fontFamily;
}
public void setFontFamily(String fontFamily) {
this.fontFamily = fontFamily;
}
}
Table
package com.ufgov.pdf.entity;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlType;
/**
* 对应xml中的table标签
*
* @author lihh
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "table", propOrder = { "title", "trList" })
public class Table {
@XmlElement(name = "title")
private Title title;
@XmlElementWrapper(name = "trs")
@XmlElement(name = "tr")
private List trList;
@XmlAttribute(name = "cols")
private String cols;
@XmlAttribute(name = "font-family")
private String fontFamily;
@XmlAttribute(name = "entity")
private String entity;
@XmlAttribute(name = "rotate")
private String rotate;
public String getRotate() {
return rotate;
}
public void setRotate(String rotate) {
this.rotate = rotate;
}
public Title getTitle() {
return title;
}
public void setTitle(Title title) {
this.title = title;
}
public List getTrList() {
return trList;
}
public void setTrList(List trList) {
this.trList = trList;
}
public String getCols() {
return cols;
}
public void setCols(String cols) {
this.cols = cols;
}
public String getFontFamily() {
return fontFamily;
}
public void setFontFamily(String fontFamily) {
this.fontFamily = fontFamily;
}
public String getEntity() {
return entity;
}
public void setEntity(String entity) {
this.entity = entity;
}
}
Tr
package com.ufgov.pdf.entity;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "tr",propOrder= {"tdList"})
public class Tr {
@XmlElementWrapper(name = "tds")
@XmlElement(name = "td")
private List tdList;
public List getTdList() {
return tdList;
}
public void setTdList(List tdList) {
this.tdList = tdList;
}
}
Td
package com.ufgov.pdf.entity;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "td", propOrder = { "text" })
public class Td {
@XmlAttribute(name = "rowspan")
private String rowspan;
@XmlAttribute(name = "border-width")
private String borderWidth;
@XmlAttribute(name = "colspan")
private String colspan;
@XmlAttribute(name = "align")
private String align;
@XmlAttribute(name = "v-align")
private String vAlign;
@XmlElement(name = "text")
private String text;
public String getBorderWidth() {
return borderWidth;
}
public void setBorderWidth(String borderWidth) {
this.borderWidth = borderWidth;
}
public String getSText() {
return text;
}
public void setString(String text) {
this.text = text;
}
public String getRowspan() {
return rowspan == null ? "1" : rowspan;
}
public void setRowspan(String rowspan) {
this.rowspan = rowspan;
}
public String getColspan() {
return colspan == null ? "1" : colspan;
}
public void setColspan(String colspan) {
this.colspan = colspan;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getAlign() {
return align;
}
public void setAlign(String align) {
this.align = align;
}
public String getvAlign() {
return vAlign;
}
public void setvAlign(String vAlign) {
this.vAlign = vAlign;
};
}
上述实体需要用到XmlAccessorType等注解,不懂的话可以百度。
3.下边是工具类
a.xml转为bean
这个是从网上找的jaxb2的用法
package com.ufgov.pdf.util;
import java.io.StringReader;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
/**
* Jaxb2工具类
*/
public class JaxbUtil {
/**
* xml转换成JavaBean
*
* @param xml
* @param c
* @return
*/
@SuppressWarnings("unchecked")
public static T converyToJavaBean(String xml, Class c) {
T t = null;
try {
JAXBContext context = JAXBContext.newInstance(c);
Unmarshaller unmarshaller = context.createUnmarshaller();
t = (T) unmarshaller.unmarshal(new StringReader(xml));
} catch (Exception e) {
e.printStackTrace();
}
return t;
}
// /**
// * JavaBean转换成xml 默认编码UTF-8
// *
// * @param obj
// * @param writer
// * @return
// */
// public static String convertToXml(Object obj) {
// return convertToXml(obj, "UTF-8");
// }
// /**
// * JavaBean转换成xml
// *
// * @param obj
// * @param encoding
// * @return
// */
// public static String convertToXml(Object obj, String encoding) {
// String result = null;
// try {
// JAXBContext context = JAXBContext.newInstance(obj.getClass());
// Marshaller marshaller = context.createMarshaller();
// marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
// marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding);
//
// StringWriter writer = new StringWriter();
// marshaller.marshal(obj, writer);
// result = writer.toString();
// } catch (Exception e) {
// e.printStackTrace();
// }
//
// return result;
// }
}
b.数据库测试用类
package com.ufgov.pdf.util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
public class DBHelper {
/**
* 将下划线风格替换为驼峰风格
*
* @param inputString
* @return
*/
private static String underlineToCamelhump(String inputString) {
StringBuilder sb = new StringBuilder();
boolean nextUpperCase = false;
for (int i = 0; i < inputString.length(); i++) {
char c = inputString.charAt(i);
if (c == '_') {
if (sb.length() > 0) {
nextUpperCase = true;
}
} else {
if (nextUpperCase) {
sb.append(Character.toUpperCase(c));
nextUpperCase = false;
} else {
sb.append(Character.toLowerCase(c));
}
}
}
return sb.toString();
}
public static Map getData(String sql) throws ClassNotFoundException, SQLException {
Class.forName("oracle.jdbc.driver.OracleDriver");
String url = "jdbc:oracle:thin:@127.0.0.1:1521:orcl";
String user = "test";
String password = "1";
Connection conn = DriverManager.getConnection(url, user, password);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
ResultSetMetaData data = rs.getMetaData();
Map map = null;
while (rs.next()) {
map = new HashMap();
for (int i = 1; i <= data.getColumnCount(); i++) {// 数据库里从 1 开始
String c = data.getColumnName(i);
String v = rs.getString(c);
System.out.println(c + ":" + v + "\t");
map.put(underlineToCamelhump(c), v);
}
System.out.println("======================");
}
rs.close();
stmt.close();
conn.close();
return map;
}
public static void main(String[] args) throws ClassNotFoundException, SQLException {
String sql = "select * from cpa_cpaf_bir t where t.report_no ='CG201700042045'";
System.out.println(getData(sql));
}
}
c.核心转换类
package com.ufgov.pdf.util;
import java.io.File;
import java.io.FileOutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.itextpdf.text.Document;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import com.ufgov.pdf.entity.Table;
import com.ufgov.pdf.entity.Tablepage;
import com.ufgov.pdf.entity.Td;
import com.ufgov.pdf.entity.Title;
import com.ufgov.pdf.entity.Tr;
/**
* 到处pdf帮助类 Created by lihhz on 2017/10/16.
*/
public class PdfHelper {
/**
* xml与数据装配页面
* 核心方法,负责输出文档
*
* @param tablepage
* xml结构
* @param map
* 数据结构
* @throws Exception
*/
public static void convert(Tablepage tablepage, Map> map) throws Exception {
// TODO:这里要设置一个文件名称,暂时先写死
// Title title = tablepage.getTitle();
// String fileName = title.getText() + ".pdf";
String fileName = "测试文档.pdf";
BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
Font font = new Font(baseFont, 10, Font.NORMAL);
// TODO:这个地方如果拿到注会用的话,要改成使用response输出
File file = new File(fileName);
FileOutputStream out = new FileOutputStream(file);
// TODO:这个A4要不要做配置?
Rectangle rectPageSize = new Rectangle(PageSize.A4);
Document document = new Document(rectPageSize, -50, -50, 10, 20);
PdfWriter.getInstance(document, out);
document.open();
// PdfPTable table_title1 = new PdfPTable(1);
// setTitle(document, title, table_title1);
List tableList = tablepage.getTableList();
// TODO:这个地方可以做成静态数据,也可以不做,只是为了输出的时候更简单
Map posMap = new HashMap();
posMap.put("center", Element.ALIGN_CENTER);
posMap.put("left", Element.ALIGN_LEFT);
posMap.put("right", Element.ALIGN_RIGHT);
posMap.put("top", Element.ALIGN_TOP);
posMap.put("middle", Element.ALIGN_MIDDLE);
posMap.put("bottom", Element.ALIGN_BOTTOM);
int size = tableList.size();
if (tableList == null || size < 1) {
return;
}
for (Table table : tableList) {
String rotate = table.getRotate();
Rectangle rect = new Rectangle(PageSize.A4);
// 添加横向支持
if (rotate.equals("true")) {
document.setPageSize(rect.rotate());
}
document.newPage();
PdfPTable table1 = new PdfPTable(12);
// table1.addCell("测试一下");
// table1.getDefaultCell().setBorder(PdfPCell.NO_BORDER);
// table1.setLockedWidth(true);
Title t = table.getTitle();
PdfPTable tableTitle = new PdfPTable(1);
if (t != null && t.getText() != null) {
setTitle(document, t, tableTitle);
}
List trList = table.getTrList();
String entity = table.getEntity();
Map obj = map.get(entity);
if (null == obj) {
System.out.println("警告:出现空值!");
}
if (trList == null || trList.size() < 1) {
document.add(table1);
continue;
}
for (Tr tr : trList) {
List tdList = tr.getTdList();
if (tdList == null || tdList.size() < 1) {
continue;
}
for (Td td : tdList) {
String text = td.getText();
if (text.startsWith("{{") && text.endsWith("}}")) {
String key = text.replace("{{", "").replace("}}", "");
text = obj.containsKey(key) && obj.get(key) != null ? obj.get(key).toString() : "";
}
PdfPCell cell = new PdfPCell(new Paragraph(text, font));
String borderWidth = td.getBorderWidth();
float[] borderArr = getBorder(borderWidth);
if (borderArr != null) {
cell.setBorderWidthTop(borderArr[0]);
cell.setBorderWidthRight(borderArr[1]);
cell.setBorderWidthBottom(borderArr[2]);
cell.setBorderWidthLeft(borderArr[3]);
}
cell.setColspan(Integer.parseInt(td.getColspan()));
cell.setRowspan(Integer.parseInt(td.getRowspan()));
cell.setHorizontalAlignment(posMap.get(td.getAlign()));
cell.setVerticalAlignment(posMap.get(td.getvAlign()));
cell.setMinimumHeight(20f);
table1.addCell(cell);
}
}
document.add(table1);
}
document.close();
}
/**
* TODO:在这里设置边框。暂时没有什么好的方法
*/
private static float[] getBorder(String borderWidth) {
if (borderWidth == null) {
return null;
}
float[] borderArr = new float[4];
String[] borderWidths = borderWidth.split("\\s+");
// 校验边框
int borderNum = borderWidths.length;
switch (borderNum) {
case 1:
borderArr[0] = Float.parseFloat(borderWidths[0]);
borderArr[1] = borderArr[0];
borderArr[2] = borderArr[0];
borderArr[3] = borderArr[0];
break;
case 2:
borderArr[0] = Float.parseFloat(borderWidths[0]);
borderArr[1] = borderArr[0];
borderArr[2] = Float.parseFloat(borderWidths[1]);
borderArr[3] = borderArr[2];
break;
case 3:
borderArr[0] = Float.parseFloat(borderWidths[0]);
borderArr[1] = Float.parseFloat(borderWidths[1]);
borderArr[2] = Float.parseFloat(borderWidths[2]);
borderArr[3] = 0;
break;
case 4:
borderArr[0] = Float.parseFloat(borderWidths[0]);
borderArr[1] = Float.parseFloat(borderWidths[1]);
borderArr[2] = Float.parseFloat(borderWidths[2]);
borderArr[3] = Float.parseFloat(borderWidths[3]);
break;
default:
borderArr[0] = borderArr[1] = borderArr[2] = borderArr[3] = 1;
break;
}
return borderArr;
}
private static void setTitle(Document document, Title title, PdfPTable tableTitle) throws Exception {
PdfPCell cell = new PdfPCell(new Paragraph(title.getText(), new Font(
BaseFont.createFont(title.getFontFamily(), "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED), 17, Font.NORMAL)));
// TODO:这个地方要设置标题的位置,暂时先不写
cell.setHorizontalAlignment(Element.ALIGN_CENTER); // 设置单元格中文本位置(居中:ALIGN_CENTER;靠左:ALIGN_LEFT;靠右:ALIGN_RIGHT)
cell.setVerticalAlignment(Element.ALIGN_MIDDLE); // 文本垂直方向位置(靠上:ALIGN_TOP;居中:ALIGN_MIDDLE;靠下:ALIGN_BOTTOM;)
cell.setBorderWidth(0f); // 设置单元格边框,参数都为float
cell.setPaddingBottom(20f); // 设置单元格文本内边距
tableTitle.addCell(cell);
document.add(tableTitle);
}
}
其它测试类
package com.ufgov.pdf.util;
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.Locale;
/**
* 测试用的工具类,在cpams中已经存在,可以删除了
* @author lihh
*
*/
public class CanDel {
/**
*
* @param number
* 要转换的数字
* @param digit
* 保留小数点位数
* @return
* @author zhangdand at 2018年3月1日下午4:10:52
*/
public static String numberFormat(BigDecimal number, int digit) {
String result = "0";
// 小数点后边的数字(不包括.)
String digitStr = "";
NumberFormat usFormat = NumberFormat.getIntegerInstance(Locale.US);
if (number == null || number.compareTo(new BigDecimal(0)) == 0) {
if (digit > 0) {
for (int i = 0; i < digit; i++) {
digitStr += "0";
}
result += "." + digitStr;
}
} else {
// 保留两位小数
usFormat.setMaximumFractionDigits(digit);
result = usFormat.format(number);
if (result.indexOf(".") < 0 && digit > 0) {
for (int i = 0; i < digit; i++) {
digitStr += "0";
}
result += "." + digitStr;
} else if (result.indexOf(".") > 0) {
String[] tmpArry = result.split("\\.");
digitStr = tmpArry[1];
// 处理小数点结尾0不显示的情况
if (digitStr.length() < digit) {
int tmpN = digit - digitStr.length();
for (int i = 0; i < tmpN; i++) {
digitStr += "0";
}
result = tmpArry[0] + "." + digitStr;
}
}
}
return result;
}
}
4.实体基类
所有需要转pdf的实体继承基类,主要是toMap方法,不过在main方法中并没有用到
package com.ufgov.pdf.entity;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import com.ufgov.pdf.util.CanDel;
/**
* pdf bean基类. 将需要转换为Map的bean继承自此抽象类
* 如果所需要的类型在toMap方法中不存在,可以添加;
* 如果基类的toMap方法实在不能满足您的需求,您可以重写此方法
*
* @author lihh
*
*/
public abstract class BaseMapBean {
/**
* 转化为Map
* @return
*/
public Map toMap() {
Map map = new HashMap();
try {
// 内省是 Java 语言对 Bean 类属性、事件的一种缺省处理方法。例如类 PersonBean中有属性 name, 那我们可以通过
// getName,setName 来得到其值或者设置新的值。通过 getName/setName 来访问 name 属性,这就是默认的规则。 Java
// 中提供了一套 API 用来访问某个属性的 getter/setter 方法,通过这些 API 可以使你不需要了解这个规则(但你最好还是要搞清楚),这些
// API 存放于包 java.beans 中。注意:
// PersonBean中属性mN的getter/setter方法必须满足javaBean命名规范,即getmN,不能写作getMN,否则转换失败。
BeanInfo beanInfo = Introspector.getBeanInfo(this.getClass());
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor property : propertyDescriptors) {
String key = property.getName();
// 过滤class属性
if (!key.equals("class")) {
// 得到property对应的getter方法
Method getter = property.getReadMethod();
Object value = getter.invoke(this);
if (value != null) {
if (value instanceof BigDecimal) {
value = CanDel.numberFormat((BigDecimal) value, 2);
} else {
System.out.println(value.getClass().toString());
}
}
map.put(key, value);
}
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("transBean2Map Error " + e);
}
return map;
}
}
main测试方法
package com.ufgov.pdf.util;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import org.dom4j.Document;
import org.dom4j.io.SAXReader;
import com.ufgov.pdf.entity.Tablepage;
/**
* 导出PDF的Main方法
*
* @author lihh
*
*/
public class ExportPdfImpl {
/**
* 这个在注会中写成一个方法,该方法接受一个xml文件路径参数,一个map
* @param args
*/
public static void main(String[] args) {
SAXReader sax = new SAXReader();// 创建一个SAXReader对象
File xmlFile = new File("xml-config/NewFile.xml");// 根据指定的路径创建file对象
try {
// 获取document对象,如果文档无节点,则会抛出Exception提前结束
Document document = sax.read(xmlFile);
Tablepage tablepage = JaxbUtil.converyToJavaBean(document.asXML(), Tablepage.class);
Map> map = new HashMap>();
String sql = "select * from cpa_cpaf_bir t where t.report_no ='CG201700042045'";
map.put("cpafInfo", DBHelper.getData(sql));
PdfHelper.convert(tablepage, map);
} catch (Exception e) {
e.printStackTrace();
}
}
// public static void getRoot() {
// SAXReader sax = new SAXReader();// 创建一个SAXReader对象
// File xmlFile = new File("xml-config/NewFile.xml");// 根据指定的路径创建file对象
// try {
// // 获取document对象,如果文档无节点,则会抛出Exception提前结束
// Document document = sax.read(xmlFile);
// Element root = document.getRootElement();// 获取根节点
// Tablepage tablepage = new Tablepage();
// getNodes(root, tablepage);// 从根节点开始遍历所有节点
// } catch (DocumentException e) {
// e.printStackTrace();
// }
//
// }
//
// /**
// * 从指定节点开始,递归遍历所有子节点
// *
// * @author chenleixing
// */
// public static void getNodes(Element node, Tablepage tablepage) {
// System.out.println("--------------------");
// if (node.getName().equals("title")) {
// tablepage.setTitle(node.getText());
// } else if (node.getName().equals("table")) {
// Table table = new Table();
// }
// // 当前节点的名称、文本内容和属性
// System.out.println("当前节点名称:" + node.getName());// 当前节点名称
// System.out.println("当前节点的内容:" + node.getTextTrim());// 当前节点名称
// List listAttr = node.attributes();// 当前节点的所有属性的list
// for (Attribute attr : listAttr) {// 遍历当前节点的所有属性
// String name = attr.getName();// 属性名称
// String value = attr.getValue();// 属性的值
// System.out.println("属性名称:" + name + "属性值:" + value);
// }
//
// // 递归遍历当前节点所有的子节点
// List listElement = node.elements();// 所有一级子节点的list
// for (Element e : listElement) {// 遍历所有一级子节点
// // getNodes(e);// 递归
// }
// }
}
至此,整个项目结束
导出的pdf还有一个问题就是,在设置边框后,放大pdf,会看到设置的边框外侧和其它没有手动设置、正常的cell边框有细微的距离,这个不知道怎么解决
你可能感兴趣的:(java,xml,pdf)