SAM解析的特点
- 1.基于事件驱动
- 2.从上至下依次顺序读取,速度快
- 3.不能任意读取节点,灵活性差
- 4.解析时占用的内存小
- 5.SAX更适用于在性能要求更高的设备上使用(Android开发中,等移动开发)
DOM解析XML
- 1.基于树型结构,通过一次性把文档加载到内存中,所以会比较占用内存,可以随机访问更加灵活,更适合在Web开发中使用
JDOM解析XML
- 1.与DOM类似基于树型结构
- 2.与DOM区别
(1)第三方开源组件
(2)实现JAVA的Collection接口
(3)效率比DOM更快
DOM4J解析XML
- 1.基于树型结构,第三方组件
- 2.解析速度快,效率高,使用的JAVA中的迭代器实现数据读取,在Web框架中使用较多(Hibernate)
四种方法比较
- JDOM和DOM在性能测试时表现不佳,在测试10M文档时内存溢出。
- SAX表现好,这主要依赖于它特定的解析方式。一个SAX检测即将到来的XML流,但并没有载入到内存中(当然当XML流读入时,会有部分文档暂时隐藏在内存中)。
- DOM4J是这场测试的获胜者。目前许多开源项目中大量采用DOM4J,例如(Hibernate)也用DOM4J来读取XML配置文件
举例说明:
1.创建SAM、DOM、JDOM和DOM4J解析器工厂对象
package com.vince;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.xml.parsers.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Handler;
/**
* 四种方法比较
* JDOM和DOM在性能测试时表现不佳,在测试10M文档时内存溢出。
* SAX表现好,这主要依赖于它特定的解析方式。一个SAX检测即将到来的XML流,但并没有载入到内存中(当然当XML流读入时,会有部分文档暂时隐藏在内存中)。
*
* DOM4J是这场测试的获胜者。目前许多开源项目中大量采用DOM4J,例如(Hibernate)也用DOM4J来读取XML配置文件
*
*
*/
public class XMLDemo {
/**
*DOM4J解析XML
* 1.基于树型结构,第三方组件
* 2.解析速度快,效率高,使用的JAVA中的迭代器实现数据读取,在Web框架中使用较多(Hibernate)
*/
@Test
public void dom4jParseXML() throws DocumentException {
//1.创建DOM4J的解析对象
SAXReader reader=new SAXReader();
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("com/vince/Person.xml");
org.dom4j.Document doc = reader.read(is);
org.dom4j.Element rootElement = doc.getRootElement();
Iterator<org.dom4j.Element> iterator=rootElement.elementIterator();
ArrayList<Person> persons = new ArrayList<>();
Person p=null;
while(iterator.hasNext()){
p=new Person();
org.dom4j.Element e=iterator.next();
p.setPersonid(e.attributeValue("personid"));
Iterator<org.dom4j.Element> iterator1 = e.elementIterator();
while (iterator1.hasNext()){
org.dom4j.Element next = iterator1.next();
String tag = next.getName();
if("name".equals(tag)){
p.setName(next.getText());
}else if ("address".equals(tag)){
p.setAddress(next.getText());
}else if ("tel".equals(tag)){
p.setTel(next.getText());
}else if ("fax".equals(tag)){
p.setFax(next.getText());
}else if ("email".equals(tag)){
p.setEmail(next.getText());
}
}
persons.add(p);
}
System.out.println("结果:");
System.out.println(Arrays.toString(persons.toArray()));
}
/**
*JDOM解析XML
* 1.与DOM类似基于树型结构
* 2.与DOM区别
* (1)第三方开源组件
* (2)实现JAVA的Collection接口
* (3)效率比DOM更快
*/
@Test
public void jdomParseXML() throws JDOMException, IOException {
//创建JDOM解析器
SAXBuilder builder=new SAXBuilder();
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("com/vince/Person.xml");
org.jdom2.Document build = builder.build(is);
Element rootElement = build.getRootElement();
List<Person> list=new ArrayList<>();
Person person=null;
List<Element> children = rootElement.getChildren();
for (Element element:children){
person=new Person();
String personid = element.getAttributeValue("personid");
person.setPersonid(personid);
List<Element> children1 = element.getChildren();
for (Element e:children1){
String tag = e.getName();
if("name".equals(tag)){
person.setName(e.getText());
}else if ("address".equals(tag)){
person.setAddress(e.getText());
}else if ("tel".equals(tag)){
person.setTel(e.getText());
}else if ("fax".equals(tag)){
person.setFax(e.getText());
}else if ("email".equals(tag)){
person.setEmail(e.getText());
}
}
list.add(person);
}
System.out.println("结果:");
System.out.println(Arrays.toString(list.toArray()));
}
/**
*DOM解析XML
* 1.基于树型结构,通过一次性吧文档加载到内存中,所以会比较占用内存,可以随机访问更加灵活,更适合在Web开发中使用
*
*/
@Test
public void domParseXML() throws ParserConfigurationException, IOException, SAXException {
//1.创建一个DOM解析器工厂对象
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
//2.通过工厂对象创建DOM解析器
DocumentBuilder documentBuilder=factory.newDocumentBuilder();
//3.解析文档
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("com/vince/Person.xml");
Document doc=documentBuilder.parse(is);
//4.从内存中读取数据
//获取节点名称为person的所有节点
NodeList personNodeList = doc.getElementsByTagName("person");
ArrayList<Person> persons = new ArrayList<>();
Person p;
int length=personNodeList.getLength();
//此循环会迭代两次
for (int i=0;i<length;i++){
Node personNode = personNodeList.item(i);
p=new Person();
String personid = personNode.getAttributes().getNamedItem("personid").getNodeValue();
p.setPersonid(personid);
//获取当前结点的所有的子节点
NodeList childNodes = personNode.getChildNodes();
for (int j=0;j<childNodes.getLength();j++){
Node item = childNodes.item(j);
String nodeName = item.getNodeName();
if("name".equals(nodeName)){
p.setName(item.getFirstChild().getNodeValue());
}else if("address".equals(nodeName)){
p.setAddress(item.getFirstChild().getNodeValue());
}else if("tel".equals(nodeName)){
p.setTel(item.getFirstChild().getNodeValue());
}else if("fax".equals(nodeName)){
p.setFax(item.getFirstChild().getNodeValue());
}else if("email".equals(nodeName)){
p.setEmail(item.getFirstChild().getNodeValue());
}
}
persons.add(p);
}
System.out.println("结果:");
System.out.println(Arrays.toString(persons.toArray()));
}
@Test
public void saxParseXML() throws ParserConfigurationException, SAXException, IOException {
//1.创建一个SAX解析器工厂对象
SAXParserFactory saxParserFactory=SAXParserFactory.newInstance();
//2.通过工厂对象创建SAX解析器
SAXParser saxParser=saxParserFactory.newSAXParser();
//3.创建一个数据处理器(自己编写)
PersonHandler personHandler = new PersonHandler();
//4.开始解析
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("com/vince/Person.xml");
saxParser.parse(is, personHandler);
List<Person> persons = personHandler.getPersons();
for(Person p:persons){
System.out.println(p);
}
}
}
2.创建Person类
package com.vince;
public class Person {
private String personid;
private String name;
private String address;
private String tel;
private String fax;
private String email;
public String getPersonid() {
return personid;
}
public void setPersonid(String personid) {
this.personid = personid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getTel() {
return tel;
}
public void setTel(String tel) {
this.tel = tel;
}
public String getFax() {
return fax;
}
public void setFax(String fax) {
this.fax = fax;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "Person{" +
"personid='" + personid + '\'' +
", name='" + name + '\'' +
", address='" + address + '\'' +
", tel='" + tel + '\'' +
", fax='" + fax + '\'' +
", email='" + email + '\'' +
'}';
}
}
3.创建SAM的PersonHandler控制器
package com.vince;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import java.util.ArrayList;
import java.util.List;
/**
* SAM解析的特点
* 1.基于事件驱动
* 2.从上至下依次顺序读取,速度快
* 3.不能任意读取节点,灵活性差
* 4.解析时占用的内存小
* 5.SAX更适用于在性能要求更高的设备上使用(Android开发中,等移动开发)
*/
public class PersonHandler extends DefaultHandler {
private List<Person> persons;
private Person p;//当前正在解析的Person
private String tag;//用于几率当前正在解析的标签名
public List<Person> getPersons() {
return persons;
}
//开始解析文档时调用
@Override
public void startDocument() throws SAXException {
super.startDocument();
persons=new ArrayList<>();
System.out.println("开始解析文档");
}
//在XML文档解析结束时当用
@Override
public void endDocument() throws SAXException {
super.endDocument();
System.out.println("解析文档结束。");
}
//解析开始元素时调用(标签)
/**
*
* @param uri
* @param localName 不带前缀的标签名
* @param qName 带前缀的标签名
* @param attributes 当前标签的属性集合
* @throws SAXException
*/
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
if("person".equals(qName)){
p=new Person();
String personid = attributes.getValue("personid");
p.setPersonid(personid);
}
tag=qName;
//System.out.println("startElement--"+qName); 测试
}
//解析结束元素时调用(标签)
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
if("person".equals(qName)){
persons.add(p);
}
tag=null;
//System.out.println("endElement--"+qName);测试
}
//解析文本内容时调用
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
super.characters(ch, start, length);
if (tag != null) {
if ("name".equals(tag)) {
p.setName(new String(ch,start,length));
}else if ("address".equals(tag)){
p.setAddress(new String(ch,start,length));
}else if("tel".equals(tag)){
p.setTel(new String(ch,start,length));
}else if("fax".equals(tag)){
p.setFax(new String(ch,start,length));
}else if("email".equals(tag)){
p.setEmail(new String(ch,start,length));
}
//System.out.println(ch);测试
}
}
}
4.使用xml文档
<?xml version="1.0" encoding="UTF-8"?>
<people>
<person personid="E01">
<name>Tony Blair</name>
<address>10 Downing Street,London,UK</address>
<tel>(061) 987654</tel>
<fax>(061) 987654</fax>
<email>blair@ererywhere.com</email>
</person>
<person personid="E02">
<name>Bili Clinton</name>
<address>White House,USA</address>
<tel>(001) 6400 987654</tel>
<fax>(001) 6400 987654</fax>
<email>bili@ererywhere.com</email>
</person>
</people>