起因
这几天在学习 JavaWeb 的内容,接触到 XML 的内容,XML 应该是不陌生的,但由于之前项目中用到的不是很多,有关 XML 解析逐渐也忘的差不多了,趁这个机会重新学一遍如何对 XML 进行解析,方便以后使用。
XML 简单介绍
XML(Extensible Markup Language)可扩展标记语言,是由 W3C 推出的新一代数据交换标准,XML 格式这里就不做介绍了。
XML 的具体用途
- 存储数据,这也是 XML 的最根本的用途
- 分离数据,使开发人员能集中精力组织数据
- 交换数据,可以再不同的系统之间交换数据
- 共享数据,XML 通过纯文本的方式来共享数据
XML 的常用解析方式
- DOM 解析
- SAX 解析
- JAXB 解析
- PULL 解析(Android)
本篇主要介绍以上 4 种解析方式
DOM解析
DOM(Document Object Mode) 基于对象的API,将 XML 全部加载到内存中,生成一个与XML稳定对应的 DOM 对象树,根据树的结构,以节点的形式来对文档进行操作。
要解析的 XML 数据
<?xml version="1.0" encoding="UTF-8"?>
<resume>
<person>
<name>张无忌</name>
<age>18</age>
<phone>000</phone>
</person>
</resume>
代码如下:
public class DOMParse {
public static void main(String[] args) {
File xmlFile = new File("D:\\resume.xml");
DocumentBuilder builder = null;
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
try {
builder = builderFactory.newDocumentBuilder();
Document document = builder.parse(xmlFile);
Element rootElement = document.getDocumentElement(); // 得到根元素
System.out.println("根元素:"+rootElement.getNodeName());
NodeList childNodes = rootElement.getChildNodes(); // 得到子元素
for (int i = 0; i < childNodes.getLength(); i++) {
Node item = childNodes.item(i);
if ("person".equals(item.getNodeName())) {
NodeList childNodes2 = item.getChildNodes();
for (int j = 0; j < childNodes2.getLength(); j++) {
Node item2 = childNodes2.item(j);
if ("name".equals(item2.getNodeName())) {
System.out.println("名字:"+item2.getTextContent());
}else if ("age".equals(item2.getNodeName())) {
System.out.println("年龄:"+item2.getTextContent());
}else if ("phone".equals(item2.getNodeName())) {
System.out.println("电话:"+item2.getTextContent());
}
}
}
}
} catch (Exception e) {
// XML 解析只负责解析正确的 XML 不能判断 XML 语法是否正确,如果 XML 文件不合法,会抛出异常
e.printStackTrace();
}
}
}
解析结果:
总结:
DOM 解析 XML 三步曲
// 1.获取 factory
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
// 2.获取 builder
DocumentBuilder builder = builderFactory.newDocumentBuilder();
// 3.解析为 Document 对象
Document document = builder.parse(xmlFile);
得到 Documnet 对象之后就可以通过 Document 的方法来遍历 XML
SAX解析
SAX 与 DOM 的底层实现不同,DOM 在解析的时候会把整个 XML 文件全部映射为 Document 里的树状结构,当遇到较大的 XML 文件时候,DOM 缺点就暴露出来了
SAX 就是针对这种情况出现的解决方案,SAX 解析器对 XML 文档解析会从 XML 文档开始的位置进行解析,根据已经定义好的事件处理器,来决定当前所解析的部分
我们同样还是解析上面的 XML 数据
public class SAXParseTest {
public static void main(String[] args) {
File xmlFile = new File("D:\\resume.xml");
SAXParserFactory factory = SAXParserFactory.newInstance();
try {
SAXParser parser = factory.newSAXParser();
parser.parse(xmlFile, new SAXHandler());
}catch(Exception e) {
e.printStackTrace();
}
}
static class SAXHandler extends DefaultHandler{
private String content;
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
content = new String(ch,start,length);
}
// 解析到元素的结束标签时触发
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if ("name".equals(qName)) {
System.out.println("名字:"+content);
}else if ("age".equals(qName)) {
System.out.println("年龄:"+content);
}else if ("phone".equals(qName)) {
System.out.println("电话:"+content);
}
}
}
}
解析结果
总结
SAX 解析 XML 三步曲
// 1.创建factory
SAXParserFactory factory = SAXParserFactory.newInstance();
// 2.获取 SAXParser
SAXParser parser = factory.newSAXParser();
// 3.开始解析
parser.parse(xmlFile,/*new SAXHandler() 自定义事件监听器*/);
自定义 事件监听器 需要继续 DefaultHandler 类,DefaultHandler 常用方法
void characters(char ch[],int start,int length)
void endDocument()
void endElement(String url,String localName,String qName)
void startDocument()
void startElement(String url,String localName,String qName,Attributes attributes)
JAXB解析
使用更简单快速的方式解析 XML,就需要使用 JAXB 了,JAXB 采用映射的方式允许 Java 将 Java 类映射为 XML 表示方式,JAXB 不但支持 XML,也可以方便对 JSON 数据进行处理,我们这里只讨论 XML 的方式。
JAXB 的工作原理如下
- XML 转换到 Java 对象的过程叫做 Unmarshal
- Java 对象转换到 XML 的过程叫做 Marshal
将 Java 对象转换成 XML 格式
@XmlRootElement
public class Resume {
private String name;
private String age;
private String phone;
// getter setter ...
}
通过标注 @XmlRootElement 用于标注 XML 的根元素
一旦类标注了根元素,那么这个类的所有属性,默认映射为根元素的子元素
public class JAXParse {
public static void main(String[] args) {
File xmlFile = new File("D:\\resume.xml");
try {
JAXBContext context = JAXBContext.newInstance(Resume.class);
Marshaller marshaller = context.createMarshaller();
Resume resume = new Resume();
resume.setName("张三丰");
resume.setAge("18");
resume.setPhone("999");
marshaller.marshal(resume, xmlFile);
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
将 Java 对象转化成 XML 三步曲
// 1.通过映射的类创建 JAXBContext 对象,
JAXBContext context = JAXBContext.newInstance(Object.class);
// 2.创建 Marshaller
Marshaller marshaller = context.createMarshaller();
// 3.将Java 对象转换到指定的输出位置
marshaller.marshal(new Object(), xmlFile);
将 XML 转换成 Java 对象
public class JAXParse {
public static void main(String[] args) {
File xmlFile = new File("D:\\resume.xml");
try {
JAXBContext context = JAXBContext.newInstance(Resume.class);
Unmarshaller u = context.createUnmarshaller();
Resume resume = (Resume)u.unmarshal(xmlFile);
System.out.println(resume.getName);
System.out.println(resume.getAge);
System.out.println(resume.getPhone);
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
将 XML 转换成 Java 对象 使用的 Unmarshaller
当然了 JAXB 还提供了其他复杂的映射标注,帮助我们构建更加复杂的 XML 结构的文本,我们可以参考具体的 API 文档
PULL解析(Android)
由于之前一直是做 Android 开发,Android 提供了另一种解析 XML 的方式,那就是 PULL 解析,这里也顺便介绍一下
未完待续….