一、需求场景
需要根据不同的Java对象,动态生成对应的XML文件。举例:现在要创建的XML文件如下:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Person>
<Name>小明</Name>
<Gender>男</Gender>
<Books>
<Item>
<Title>文学书</Title>
<Author>张三</Author>
</Item>
<Item>
<Title>历史书</Title>
<Author>李四</Author>
</Item>
</Books>
</Person>
二、需求实现
根据xml创建对应的Java类,结构与xml结构一致。如上,创建Java类:
@Data
public class Person {
private String name;
private String gender;
private List<Books> books;
}
动态生成Document节点代码:
/**
* 生成xml节点
*
* @param document XML文档
* @param method 调用方法
* @param rootElement 根节点
* @param clazz 当前节点类型
* @param curInstance 当前节点实例
*/
private static void generateElement(Document document, Method method, Element rootElement, Class<?> clazz, Object curInstance) {
try {
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
String name = field.getName();
// 转换首字母大写
char[] cs = name.toCharArray();
cs[0] -= 32;
String attribute = String.valueOf(cs);
//创建子节点
Element element = (Element) method.invoke(document, attribute);
Object obj = field.get(curInstance);
if (obj != null) {
if (obj instanceof List) {
// 列表-->递归创建节点
List list = (List) obj;
Type genericType = field.getGenericType();
// 如果是泛型参数的类型
if (genericType != null && genericType instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) genericType;
// 获取泛型Class对象
Class<?> actualTypeArgumentClazz = (Class<?>) pt.getActualTypeArguments()[0];
for (Object itemObj : list) {
Element item = (Element) method.invoke(document, "Item");
generateElement(document, method, item, actualTypeArgumentClazz, itemObj);
element.appendChild(item);
}
}
} else {
String content = obj.toString();
element.setTextContent(content);
}
}
rootElement.appendChild(element);
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
导出XML代码:
public static void exportXml(Object root) {
try {
DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = documentBuilder.newDocument();
// 创建根节点
Element personElement = document.createElement(root.getClass().getSimpleName());
Method createElementMethod = Document.class.getMethod("createElement", String.class);
generateElement(document, createElementMethod, personElement, root.getClass(), root);
// 将根节点(已经包含子节点)添加到dom树中
document.appendChild(personElement);
// 将dom树转换为XML文件
Transformer tf = TransformerFactory.newInstance().newTransformer();
// 设置XML文件自动换行
tf.setOutputProperty(OutputKeys.INDENT, "yes");
tf.transform(new DOMSource(document), new StreamResult(new File("E:\\test\\test.xml")));
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
测试代码:
public static void main(String[] args) {
Person person = new Person();
person.setName("小明");
person.setGender("男");
List<Books> bookList = new ArrayList<>();
Books books1 = new Books();
books1.setTitle("文学书");
books1.setAuthor("张三");
Books books2 = new Books();
books2.setTitle("历史书");
books2.setAuthor("李四");
bookList.add(books1);
bookList.add(books2);
person.setBooks(bookList);
exportXml(person);
}