DOM解析器:
DOM是基于树形结构的的节点或信息片段的集合,允许开发人员使用DOM API遍历XML树、检索所需数据。分析该结构通常需要加载整个文档和构造树形结构,然后才可以检索和更新节点信息。Android完全支持DOM 解析。利用DOM中的对象,可以对XML文档进行读取、搜索、修改、添加和删除等操作。
DOM工作原理:
使用DOM对XML文件进行操作时,首先要解析文件,将文件分为独立的元素、属性和注释等,然后以节点树的形式在内存中对XML文件进行表示,就可以通过节点树访问文档的内容,并根据需要修改文档——这就是DOM的工作原理。
DOM解析器优点:
1、可以对XML文档进行读取、搜索、修改、添加和删除等操作
2、由于DOM在内存中以树形结构存放,因此检索和更新效率会更高
DOM解析器缺点:
1、但是对于特别大的文档,解析和加载整个文档将会很耗资源
常用的DoM接口和类:
Document:该接口定义分析并创建DOM文档的一系列方法,它是文档树的根,是操作DOM的基础。
Element:该接口继承Node接口,提供了获取、修改XML元素名字和属性的方法。
Node:该接口提供处理并获取节点和子节点值的方法。
NodeList:提供获得节点个数和当前节点的方法。这样就可以迭代地访问各个节点。
DOMParser:该类是Apache的Xerces中的DOM解析器类,可直接解析XML文件。
DOM操作步骤:
1、首先利用DocumentBuilderFactory创建一个DocumentBuilderFactory实例
2、然后利用DocumentBuilderFactory创建DocumentBuilder
3、然后加载XML文档(Document),
4、然后获取文档的根结点(Element),
5、然后获取根结点中所有子节点的列表(NodeList),
6、然后使用再获取子节点列表中的需要读取的结点。
注意:这里的books.xml、Book.java和自定义解析器接口BookParser.java与上篇 Android 创建与解析XML(一)---- SAX方式 中的是一样的
DOM解析器代码:
DomBookParser.java
package com.sym.xml;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import android.util.Log;
public class DomBookParser implements BookParser {
@Override
public List<Book> parser(InputStream is) throws Exception {
List<Book> books = new ArrayList<Book>();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();//取得DocumentBuilderFactory实例
DocumentBuilder builder = factory.newDocumentBuilder();//从factory获取DocumentBuilder实例
Document doc = builder.parse(is);//解析输入流,得到Document实例
Element rootElement = doc.getDocumentElement();
NodeList items = rootElement.getElementsByTagName("book");
Log.e("NodeList.getLength", "----"+items.getLength());
for(int i=0; i<items.getLength(); i++){
Book book = new Book();
Node item = items.item(i);
NodeList properties = item.getChildNodes();
Log.e("properties.getLength", "----"+properties.getLength());
for(int j=0; j<properties.getLength(); j++){
Node property = properties.item(j);
String nodeName = property.getNodeName();
Log.e("nodeName", "----"+nodeName);
if(nodeName.equals("id")){
book.setId(Integer.parseInt(property.getFirstChild().getNodeValue()));
}else if(nodeName.equals("name")){
book.setName(property.getFirstChild().getNodeValue());
}else if(nodeName.equals("price")){
Log.e("price----", ""+property.getFirstChild().getNodeValue());
book.setPrice(Float.parseFloat(property.getFirstChild().getNodeValue()));
}
}
books.add(book);
}
return books;
}
@Override
public String serialize(List<Book> books) throws Exception {
TransformerFactory transFactory = TransformerFactory.newInstance();//取得TransformerFactory实例
Transformer transformer = transFactory.newTransformer();//从transformer中获得Transformer实例
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");//设置输出采用的编码方式
transformer.setOutputProperty(OutputKeys.INDENT, "yes");//是否自动添加额外是空白
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");//是否忽略XML声明
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.newDocument();//由builder创建新文档
Element rootElement = doc.createElement("books");
for(Book book : books){
Element bookElement = doc.createElement("book");
bookElement.setAttribute("id", book.getId() + "");
Element nameElement = doc.createElement("name");
Node nodeName = doc.createTextNode(book.getName());
nameElement.appendChild(nodeName);
bookElement.appendChild(nameElement);
Log.e("book.getName()", "----"+book.getName());
Element priceElement = doc.createElement("price");
Node nodePrice = doc.createTextNode(book.getPrice()+"");
priceElement.appendChild(nodePrice);
bookElement.appendChild(priceElement);
Log.e("book.getPrice()", "----"+book.getPrice());
rootElement.appendChild(bookElement);
}
doc.appendChild(rootElement);
StringWriter writer = new StringWriter();
DOMSource source = new DOMSource(doc.getDocumentElement());//表明文档来源是doc
Result result = new StreamResult(writer);//表明目标结果为writer
transformer.transform(source, result);//开始转换
Log.e("source----", "" + writer.toString());
return writer.toString();
}
}
布局文件的XML代码与上篇一样
MainActivity.java只要修改一个地方---在read方法中将实例化的是DomBookParser对象就可以了。
public void read(View v){
try {
InputStream is = getAssets().open("books.xml");
// parser = new SaxBookParser();//创建SaxBookParser实例
parser = new DomBookParser();
// parser = new PullBookParser();
books = parser.parser(is);//解析输入流
StringBuffer sb = new StringBuffer();
sb.append("解析XML结果:" + "\n");
for(Book book : books){
sb.append(book.toString() + "\n");
Log.i(TAG, book.toString());
}
readxml.setText(sb.toString());
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
}
执行的结果图: