Android之DOM生成XML文件
文章链接
知识点
- Document获取和设置文档属性;
- 创建节点并设置属性;
- 创建节点并且设置value;
- 转换生成XML;
- 新名词记录{Document:DOM的XML文档holder类;工厂模式;transformer:DOM实际转换生成XML类;}
概述
上一篇文章,讲解了如何利用SAX生成XML文件。
Android之pull生成XML及XmlSerializer详解
Android之SAX生成XML及TransformerHandler解析
下面来看一下如何使用DOM来生成XML文件。
DOM解析和生成XML都是利用树状结构来进行解析和生成,这是一个相反的过程。如果你了解了DOM的解析,那么理解生成也不是问题了。
XML文档Document
我们知道DOM是先将整个文档读入内存解析,就需要获取它的document对象,然后再根据整个文档的树结构,依次由“树根”–>“树梢”进行依次读取解析。同理,在生成XML的时候,也需要同样获取到“树根”,然后依次创建节点,加入到对应的位置,具体代码如下。
//工厂模式管理documentbuilder
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
//documentbuilder用于管理解析或者生产XML
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.newDocument();
由上面可以看到,DOM的实例管理和SAX/PULL是一样的,都是用了工厂模式,你要document对象可以,我给你创建。但是因为document对象是被DocumentBuilder管理,所以创建一个documentbuilder给你,documentbuilder的功能是解析或者生成XML,并且将结果放入到document对象中返回。而document对象则是对XML的树状结构进行保存和获取节点和节点数据等的操作,当然也具有创建节点的功能。
获取到document对象就可以进操作了。
创建XML文档说明
首先当然是对文档进行说明的一些设置了,例如版本,编码方式和命名空间等等。DOM比较好的就是都直接有对应的设置方法,不用获取到key然后再进行设置对应的值。
方法如下:
document.setPrefix();
document.setDocumentURI();
document.setXmlVersion();
document.setXmlStandalone();
//···
创建节点并设置属性
创建节点(元素)的方法比较都是相同的,需要传入节点的名称,不同的是要手动加入到需要节点并设置属性,代码如下所示:
//创建节点user
Element userElement = document.createElement("user");
//设置此节点id属性,结果为<user id = "1">
userElement.setAttribute("id", String.valueOf(userBean.getId()));
创建节点并且设置value
创建了节点和属性,接下来创建节点,并且添加节点下对应的数值,例如创建userName对象,并设置yaojt的值(< userName>yaojt),对应代码如下:
//创建userName节点
Element userNameElement = document.createElement("userName");
//给userName节点加入value "yaojt"
userNameElement.appendChild(document.createTextNode("yaojt");
//将userName的节点加入到user节点,作为user节点的子节点
userElement.appendChild(userNameElement);
上面的代码已经说清楚了,主要createTextNode()方法生成value,并且调用该(userName节点)节点的appendChild()方法加入到此节点下,作为此节点的value。该节点有从属于哪一个父节点(user节点),那么调用相对应的父节点的appendChild()加入子节点。
生成XML
上面的步骤中,我们利用document建立好了XML的层次结构,那只是在document对象里的,并没有进行实际的转换,并且进行输出。API提供了Transformer类进行转换的操作。而此类又是由工厂模式进行管理的。获取的方法如下:
//转换工厂类
TransformerFactory transformerFactory = TransformerFactory.newInstance();
//实际转换类
Transformer transformer = transformerFactory.newTransformer();
//设置输出文档属性说明
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
在转换类中,调用transform(Source xmlSource, Result outputTarget)方法就可以进行实际的转换操作了。我们看到需要两个参数,
参数1是输入需要转换的XML,Source类的作用是包含XML数据源的对象,实际上对于DOM,需要使用其子类DOMSource进行操作,DOMSource有3个构造方法,对于无参和1个参数构造方法,都是一样要设置Node对象(document类也是继承node类),2个参数的构造方法,第二个参数传入node相关联的base URI。
参数2是结果接收的Result对象。Result是一个接口类,实际中使用的是子类StreamResult,StreamResult也是一个间接管理输出的类,可以设置输出流,writer和文件等输出方式。这里利用了Writer接口类进行输出结果,实际使用的是PrintWriter子类,传入一个OutputStream对象,输出为本地的XML文件。
也可以使用StringWriter对象作为结果输出接受者。
具体的代码如下:
DOMSource domSource = new DOMSource(document);
PrintWriter printWriter = new PrintWriter(outputStream);
StreamResult streamResult = new StreamResult(printWriter);
transformer.transform(domSource, streamResult);
其实每一步都是遵循上面的步骤,只要按着结构,依次设置节点层次,整个文档就OK了。
最后给出全部的代码,如下:
/**
* DOM生成XML
*
* @param userBeanList 实体类集合
* @param outputStream 输出流
*/
public static void buildXmlByDom(List<UserBean> userBeanList, OutputStream outputStream) {
try {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.newDocument();
//创建根元素<users>
Element usersElement = document.createElement("users");
document.appendChild(usersElement);
for (UserBean userBean : userBeanList) {
//创建二级元素<user>
Element userElement = document.createElement("user");
//设置节点的属性<user id="1">的id属性,如有多个属性,则依次增加
userElement.setAttribute("id", String.valueOf(userBean.getId()));
Element userNameElement = document.createElement("userName");
userNameElement.appendChild(document.createTextNode(userBean.getUserName()));
userElement.appendChild(userNameElement);
Element passwordElement = document.createElement("password");
passwordElement.appendChild(document.createTextNode(userBean.getPassword()));
userElement.appendChild(passwordElement);
Element ageElement = document.createElement("age");
ageElement.appendChild(document.createTextNode(String.valueOf(userBean.getAge())));
userElement.appendChild(ageElement);
usersElement.appendChild(userElement);
}
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource domSource = new DOMSource(document);
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
PrintWriter printWriter = new PrintWriter(outputStream);
StreamResult streamResult = new StreamResult(printWriter);
transformer.transform(domSource, streamResult);
} catch (ParserConfigurationException | TransformerException e) {
e.printStackTrace();
}
}
实体类
private int id;
private String userName;
private String password;
private int age;
//setter和getter方法
调用上面的方法运行测试。
List<UserBean> userBeanList = XmlUtil.parseXmlByPull(inputStream);
try {
String outPutPath = file.getAbsolutePath() + "buildusersbydom.xml";
File outFile = new File(outPutPath);
if (outFile.exists()){
outFile.delete();
}
outFile.createNewFile();
CommonLog.logInfo("path:" + outFile.getAbsolutePath());
FileOutputStream fileOutputStream = new FileOutputStream(outFile);
XmlUtil.buildXmlByDom(userBeanList, fileOutputStream);
} catch (IOException e) {
e.printStackTrace();
}
关于parseXmlByPull()方法,请看这里的文章。
本例子是将生产的XML文件放在本地buildusersbydom.xml文件夹中了。下面给出一个输出的XML截图。
总结
利用DOM生成XML文档,首先需要创建一个完整的document树结构,比如根节点和子节点以及节点间的层次关系,依次appendChild()到对应的层级中。然后需要调用转换器Transformer,并且设置输出结果接受对象Source,一个DOM生成的XML文件就OK了。
以上就是所有内容,如有任何问题,请及时与我联系,谢谢!