Android 创建与解析XML(二)---- DOM方式

时间:2022-08-02 20:33:13

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());
  }
  
 }

 

执行的结果图:

Android 创建与解析XML(二)---- DOM方式