一、XML解析
1.1 XML概念
xml:即可扩展标记语言,是初期互联网前后台或多平台进行数据交互的通用语言格式,但随互联网发展,java更多的是进行前后台数据的交互,xml这种文本形式的数据格式,书写解析比较费劲所以已被json这种更轻量级的数据格式替换
优点:
xml与操作系统、编程语言的开发平台都无关;
实现不同系统之间的数据交互。
作用:
配置应用程序和网站;
数据交互;
Ajax基石。
在配置文件里边所有的配置文件都是以XMl的格式来编写的。
1.2 XML基础语法
xml语法分为两部分:
1、标题行
<?xml version="1.0" encoding="UTF-8"?>
由固定语法书写而成,用于标识当前文件为xml文件语法与相应版本以及相应的编码格式
2、数据块
以双标签的形式进行书写例如
<a> 数据</a>
注意:
(1)注意xml中可以使用标签进行层级嵌套,但是根标签只能存在一个
(2)标签名自定义但最好见名知意
(3)明确书写层级关系(对称->每个标签子标签数相同)
(4) xml标签名称严格区分大小写
<?xml version="1.0" encoding="Utf-8" ?>
<studetnts>
<student>
<name>张三</name>
<age>18</age>
<sex>男</sex>
</student>
<student>
<name>李四</name>
<age>28</age>
<sex>男</sex>
</student>
<student>
<name>小红</name>
<age>38</age>
<sex>女</sex>
</student>
<student>
<name>小美</name>
<age>18</age>
<sex>女</sex>
</student>
</studetnts>
1.3 XML解析方式
1.2.1 sax解析
(Simple API for XML)
处理方式类似于流处理,边读取边解析,采用的是事件回调的方式,书写好用于处理响应事件的方法,进行解析,当进行读取事触发响应事件执行对应方法
优点:
进行解析是无需加载全部文档,可以边读取边解析
基于事件回调进行响应的解析,只有触发相应事件时才会回调相应方法
可以解析数据量大于内存的数据
缺点:
需要自己维护响应事件的回调方法,随文档的复杂度难度递增
单向解析,不会进行反向查询,只能从头解析
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.util.ArrayList;
public class SaxParse {
public static void main(String[] args) throws Exception {
//1创建sax解析器工厂SAXParserFactory对象newInstance方法
SAXParserFactory SAXParserFatory=SAXParserFactory.newInstance();
//2使用工厂对象newSAXParser方法创建sax解析器对象
SAXParser saxParser = SAXParserFatory.newSAXParser();
//3创建自定义处理器类
class MySaxHandler extends DefaultHandler{
//startElement
//当读取到起始标签时回调的方法
//endElement
//当读取到结束标签时回调的方法
//characters
//当读取到文本标签时回调的方法
//在sax解析中是按照标签进行解析
//起始标签 结束标签 文本标签
String str="";
ArrayList<Student> list=new ArrayList<>();
Student student=null;
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
str=new String(ch,start,length);
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
// System.out.print("</"+qName+">");//qName-》触发当前回调的元素名
if(qName.equals("name")){
student=new Student();
student.setName(str);
// System.out.println(qName+":"+str);
}else if(qName.equals("age")){
student.setAge(Integer.valueOf(str));
// System.out.println(qName+":"+str);
}else if(qName.equals("sex")){
student.setSex(str);
// System.out.println(qName+":"+str);
list.add(student);
}
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
//System.out.print("<"+qName+">");//qName-》触发当前回调的元素名
}
}
//4创建自定义解析器处理器对象
MySaxHandler myHandler=new MySaxHandler();
//使用匿名内部类创建DefaultHandler实例对象
//5调用sax解析器对象传入处理器对象与数据地址进行解析
//传入解析数据地址与相应的处理器对象
saxParser.parse("F://ai/code/day1217/src/com/yunhe/xml/Students.xml",myHandler);
ArrayList<Student> allList=myHandler.list;
System.out.println(allList);
}
}
1.2.2 dom解析
(Document Object Model)
解析方式基于数据的节点层次结构进行解析,解析方式类可以理解为内嵌了处理器,在进行加载时使用已经提供的方式进行数据的解析,并以一定的层次结构进行保存,提供相应的方法可以直接进行数据的获取
优点:
底层以数据节点的形式进行存储数据,提供相应的方法快速获取
可以对某一标签直接进行访问
缺点:
需要加载整个文件,消耗内存,不能处理大于内存的数据
无论是否需要都会加载整个数据
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.InputStream;
import java.util.ArrayList;
public class DomParse {
public static void main(String[] args) throws Exception {
//dom解析基于文档对象document提供的方法进行获取
//1创建dom解析工厂DocumentBuilderFactory对象 使用newInstance方法
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
//2使用解析工厂对象newDocumentBuilder方法创建dom解析对象
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
//3调用解析parse方法将解析数据存储至相应dom对象中
InputStream resourceAsStream = DomParse.class.getClassLoader().getResourceAsStream("com/yunhe/xml/Students.xml");
Document dom = documentBuilder.parse(resourceAsStream);
//4调用dom对象API获取数据
//dom对象提供了很多对于节点操作以及获取的方法
//nodeList是一种存储方式类似于集合但不是集合的数据
NodeList students = dom.getElementsByTagName("student");
ArrayList<Student> list = new ArrayList<>();
for (int i = 0; i < students.getLength(); i++) {
Student student = new Student();
Node node = students.item(i);//相当于集合的get
NodeList childNodes = node.getChildNodes();//获取当前节点的所有子元素
for (int j = 0; j < childNodes.getLength(); j++) {
Node fieldNode = childNodes.item(j);
String qName = fieldNode.getNodeName();
// if(!fieldNode.getNodeName().equals("#text")){
// System.out.println(fieldNode.getNodeName()+":"+fieldNode.getTextContent());
// }
if(qName.equals("name")){
student.setName(fieldNode.getTextContent());
}else if(qName.equals("age")){
student.setAge(Integer.valueOf(fieldNode.getTextContent()));
}else if(qName.equals("sex")){
student.setSex(fieldNode.getTextContent());
}
}
list.add(student);
}
System.out.println(list);
}
}
1.2.3 jdom解析
(Java-based Document Object Model)
基于java规范开发的dom方式解析xml数据,主要是基于javaAPI与集合修改了原本的nodeList存储节点的形式,与dom原有的API。
JDOM文档声明其目的是“使用20%(或更少)的精力解决80%(或更多)
JDOM自身不包含解析器。它通常使用SAX2解析器来解析和验证输入XML文档(尽管它还可以将以前构造的DOM表示作为输入)。
优点:
将数据存储使用集合的形式存储
简化API的使用
缺点:
没有良好的灵活性
性能较差
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
public class JDomParse {
//jdom不能使用dom原有的解析
//使用的是sax2的解析
public static void main(String[] args) throws Exception {
//1创建sex解析器new SAXBuilder
SAXBuilder saxBuilder = new SAXBuilder();
//2使用sex解析解析数据build
InputStream resourceAsStream = DomParse.class.getClassLoader().getResourceAsStream("com/yunhe/xml/Students.xml");
Document dom = saxBuilder.build(resourceAsStream);
//3使用jdomAPI进行数据的获取
Element rootElement = dom.getRootElement();//获取代表根节点标签的元素对象
List<Element> studentList = rootElement.getChildren();
ArrayList<Student> list = new ArrayList<>();
for (Element student : studentList) {
Student s = new Student();
List<Element> filedList = student.getChildren();
for (Element filed : filedList) {
String qName = filed.getName();
if (qName.equals("name")) {
s.setName(filed.getValue());
} else if (qName.equals("age")) {
s.setAge(Integer.valueOf(filed.getValue()));
} else if (qName.equals("sex")) {
s.setSex(filed.getValue());
}
// System.out.println(filed.getName() + ":" + filed.getValue());
}
list.add(s);
}
System.out.println(list);
}
}
1.2.4 dom4j解析
DOM4J是一个非常非常优秀的Java XML API,具有性能优异、功能强大和极端易用使用的特点,同时它也是一个开放源代码的软件。如今你可以看到越来越多的Java软件都在使用DOM4J来读写XML,为解决jdom简化API导致的灵活性问题,dom4j在其基础上添加了大量的API功能代码
优点:
提高了大量的API应用于各种形式的使用
缺点:
API太过繁琐,如果只是进行简单的解析,不需要使用
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
public class Dom4JParse {
//不能直接使用dom解析器
//需要使用sex的解析器进行解析读取
public static void main(String[] args) throws Exception {
//创建sax解析器对象 new SAXReader
SAXReader saxReader=new SAXReader();
//解析响应的数据read
InputStream resourceAsStream = DomParse.class.getClassLoader().getResourceAsStream("com/yunhe/xml/Students.xml");
Document dom = saxReader.read(resourceAsStream);
//使用dom4j 提供的API进行获取
Element students = dom.getRootElement();//获取根节点元素对象
Iterator studentIterator = students.elementIterator();
ArrayList<Student> list = new ArrayList<>();
while(studentIterator.hasNext()){
Student s = new Student();
Element student = (Element) studentIterator.next();
Iterator fieldIterator = student.elementIterator();
while(fieldIterator.hasNext()){
Element field = (Element)fieldIterator.next();
//System.out.println(field.getName()+":"+field.getStringValue());
String qName = field.getName();
if (qName.equals("name")) {
s.setName(field.getStringValue());
} else if (qName.equals("age")) {
s.setAge(Integer.valueOf(field.getStringValue()));
} else if (qName.equals("sex")) {
s.setSex(field.getStringValue());
}
}
list.add(s);
}
System.out.println(list);
}
}