DOM模式解析XML,是把整个XML文档当成一个对象来处理,会先把整个文档读入到内存里。是基于树的结构,通常需要加载整文档和构造DOM树,然后才能开始工作。
优点:
- 允许应用程序对数据和结构做出更改。
- 访问是双向的,可以在任何时候在树中上下导航,获取和操作任意部分的数据。
- 整个文档树在内存中,便于操作;支持删除、修改、重新排列等多种功能
缺点:
- 因为需要加载整个XML文档来构造层次结构,所以如果xml文件过大会消耗大量资源。
- 将整个文档调入内存(包括无用的节点),浪费时间和空间;使用场合:一旦解析了文档还需多次访问这些数据;硬件资源充足(内存、CPU)
下面看这样一个xml文件
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<address>
<person>
<name>张三</name>
<email>aaaaaa@163.com</email>
</person>
<person>
<name>李四</name>
<email>bbbbbb@163.com</email>
</person>
</address>
这个xml文件加载进来就如上面的树形图,每个标签都是一个节点,在这里要特别说明一下,其实每个标签的第一个节点都是text内容节点。比如<name>的text内容节点是“张三”,虽然对于<address>标签没有text内容,但是它依然要占据一个节点。
在解析XML前先了解一下以下这几个类(建议按表格顺序读,这也是解析xml的顺序):
类 | 作用 | 举例 |
DocumentBuilderFactory | 创建(DocumentBuilder(文件构建者)对象)的工厂类 | 创建工厂对象: DocumentBuilderFactory dbFactory= DocumentBuilderFactory.newInstance(); |
DocumentBuilder | 文件构建者(创建文件Document对象) | 用工厂对象创建DocumentBuilder对象: DocumentBuilder db=dbFactory.newDocumentBuilder(); |
Document | 文件对象(将Xml文件加载放置在此对象中)Document接口代表整个XML文档。 在概念上,它是文档树的根节点,并提供对文档数据的主访问 | 用DocumentBuilder对象创建Document, 将Xml文件加载放置Document对象中: Document document=db.parse("url.xml"); |
NodeList | 节点集合 |
Element这个对象其实就是xml标签元素:
NodeList | getElementByTagName(String name) | 以文件顺序返回该标签元素下所有名称为指定字符串的子孙节点 |
Document接口常用方法(Document可以看作是整个文档树,可以对文档树进行CRUD操作):
返回类型 | 方法 | 作用 |
Element | createElement(String tagName) | 创建指定名称的元素节点 |
Text | createTextNode(String tagName) | 创建指定名称的Text文本节点 |
NodeList | getElementByTagName(String name) | 以文件顺序返回节点下所有名称为指定字符串的子孙节点 |
NodeList接口方法:
返回类型 | 方法 |
int | getLength(),返回NodeList中的节点数 |
Node | item(int index),返回第index个节点 |
Node接口常用方法:
返回类型 | 方法 | 作用 |
Node | appendChilid(Node newChild) throws DOMException | 在当前节点下增加一个子节点 |
NodeList | getChildNodes() | 取得本节点下的全部子孙节点 |
Node | getFirstChild() | 取得该节点下的第一个子节点 |
Node | getLastChild() | 取得本节点下的最后一个子节点 |
String | getNodeValue() throws DOMException | 获取节点内容 |
Node | getNextSibling() | 与该节点相邻的下一节点 |
现在将上面的xml文件进行解析:
大致过程:
- 创建DocumentBuilderFactory工厂对象
- 用工厂对象创建DocumentBuilder对象
- 用DocumentBuilder对象将xml文件加载进内存,用Document对象接收
- 获取到所有person节点,返回NodeList
- 循环遍历NodeList里的person节点
- 用getElementByTagName();分别获取person标签节点里的name标签节点、email标签节点
- 用getFirstNode().getNodeValue();分别获取name标签节点、email标签节点的第一个子节点的内容
public class AnalyzeXML {
public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException {
DocumentBuilderFactory dbFactory= DocumentBuilderFactory.newInstance();//构造方法被protect修饰
DocumentBuilder db=dbFactory.newDocumentBuilder();//通过工厂创建DocumentBuilder对象
Document document=db.parse("src/XML/Date.xml");//将Xml文件放置此对象中
//获取所有person标签节点
NodeList node = document.getElementsByTagName("person");
//遍历NodeList node(person标签节点)
for(int i=0;i<node.getLength();i++){
Element person=(Element) node.item(i);//将每个person节点又转为元素节点(标签元素)
//将person标签下名称name的子节点全部获取
NodeList name = person.getElementsByTagName("name");
for (int j=0;j<name.getLength();j++) {
/**
* name.item(j):获取NodeList name节点集合中的第j个节点
* getFirstChild():获取该节点的第一个子节点
* getNodeValue():获取该节点的内容
* */
String s = name.item(j).getFirstChild().getNodeValue();
System.out.println("姓名:"+s);
}
//将person节点下叫email的子节点全部获取
NodeList email = person.getElementsByTagName("email");
for (int j=0;j<email.getLength();j++) {
String s = email.item(j).getFirstChild().getNodeValue();
System.out.println("邮箱:"+s);
}
System.out.println("---------------------------------");
}
}
}