简单的了解一下XML解析的集中方式,将学习笔记记录下来
- DOM解析XML
- SAX解析XML
- StAX解析XML
例如如下的一个XML文件(book.xml):
<?xml version="1.0" encoding="UTF-8"?>
<books>
<book year="2000">
<title>Snow Crash</title>
<author>Neal Stephenson</author>
<publisher>Spectra</publisher>
<isbn>0553380958</isbn>
<price>14.95</price>
</book>
<book year="2005">
<title>Burning Tower</title>
<author>Larry Niven</author>
<author>Jerry Pournelle</author>
<publisher>Pocket</publisher>
<isbn>0743416910</isbn>
<price>5.99</price>
</book>
<book year="1995">
<title>Zodiac</title>
<author>Neal Stephenson</author>
<publisher>Spectra</publisher>
<isbn>0553573862</isbn>
<price>7.62</price>
</book>
<!-- more books -->
</books>
DOM
DOM是基于树形结构的XML解析方式,它会将整个XML文档读入到内存并构建一个DOM树,基于这颗树形结构对各个节点(Node)进行操作。XML文档中的每个成分都是一个节点:整个文档是一个文档节点,每个XML标签对应一个元素节点,包含在 XML标签中的文本是一个文本节点,每一个XML属性是一个属性节点,注释属于注释节点。
DOM解析的方式最主要的好处是易于编程,可以根据需求在树形结构的各节点之间导航。例如导航到当前节点的父节点、兄弟节点、子节点等都是比较方便的,这样就可以轻易地获取到自己需要的数据,也可以很容易的添加和修改树中的元素。因为整个XML文档加载到内存中并构造成树形结构,当XML文档较大时,会造成较大的资源消耗
首先使用DOM解析book.xml:
package ssm.pojectTest.parseXML.DOM;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
* 使用DOM解析XML
* @author msi
* @date 2019年4月27日
*/
public class DOMTest {
public static void main(String [] args) {
// 1.创建DocumentBuilderFactory对象
DocumentBuilderFactory a = DocumentBuilderFactory.newInstance();
try {
// 2.创建DocumentBuilder对象
DocumentBuilder builder = a.newDocumentBuilder();
// 3.通过Document对象的parse方法返回一个Document对象
Document document = builder.parse("src/test/java/ssm/pojectTest/parseXML/book.xml");
// 4.通过Document对象的getElementsByTagName()返根节点的一个list集合
NodeList bookList = document.getElementsByTagName("book");
// book节点的个数(这里是3)
System.out.println("bookList.getLength():" + bookList.getLength());
for (int i = 0; i < bookList.getLength(); i++) {
// 循环遍历获取每一个book
Node book = bookList.item(i);
// 获取节点的所有属性(在这里就是book元素的所有属性)
NamedNodeMap map = book.getAttributes();
for (int j = 0; j < map.getLength(); j ++) {
Node node = map.item(j);
//通过Node对象的getNodeName()和getNodeValue()方法获取属性名和属性值
System.out.println(node.getNodeName() + ":" + node.getNodeValue() + "--" + node.getNodeType());
}
// 解析book节点的子节点(在这里就是获取当前循环中的book节点的子元素)
NodeList childList = book.getChildNodes();
//System.out.println("childList.getLength():" + childList.getLength());
for (int t = 0; t < childList.getLength(); t++) {
// 区分出text类型的node以及element类型的node
if (childList.item(t).getNodeType() == Node.ELEMENT_NODE) {
// getNodeNmae()用于得到子节点名,getTextContext()用于得到子节点的文本内容
System.out.println(childList.item(t).getNodeName()+"===" + childList.item(t).getTextContent());
}
}
}
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
SAX
SAX是基于事件模型的XML解析方式,它并不需要将整个XML文档加载到内存中,而只需将XML文档的一部分加载到内存中,即可开始解析,在处理过程中并不会在内存中记录XML中的数据,所以占用的资源比较小。当程序处理过程中满足条件时,也可以立即停止解析过程,这样就不必解析剩余的XML内容。
当SAX解析器解析到某类型节点时,会触发注册在该类型节点上的回调函数,开发人员可以根据自己感兴趣的事件注册相应的回调函数。一般情况下,开发人员只需继承SAX提供的DefaultHandler基类,重写相应事件的处理方法并进行注册即可。事件是由解析器产生并通过回调函数发送给应用程序的,这种模式我们也称为“推模式”。
SAX的缺点也非常明显,因为不存储XML的文档结构,所以需开发人员自己负责维护业务逻辑涉及的多层节点之间的关系,维护节点间的关系复杂度高,工作量也较大,另一方面,因为是流式处理,所以处理过程只能从XML文档开始向后单向进行,无法像DOM方式那样,自由导航到之前处理过的节点上重新处理,也无法支持Xpath。SAX没有提供撰写XML文档的功能
使用SAX解析XML:
一。首先需要一个继承了DefaultHandler的实现类,重写startDocument(),endDocument(),startElement(),endElement(),characters()。
例如:SaxHandler.java
package ssm.pojectTest.parseXML.SAX;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
*
* @author msi
* @date 2019年4月27日
*/
public class SaxHandler extends DefaultHandler{
@Override
public void startDocument() throws SAXException {
System.out.println("…………开始解析文档…………\n");
System.out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
super.startDocument();
}
@Override
public void endDocument() throws SAXException {
System.out.println("\n…………结束解析文档…………");
super.endDocument();
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
System.out.print("<" + qName);
if (attributes != null) {
for (int i = 0; i < attributes.getLength(); i ++) {
System.out.print(" " + attributes.getQName(i) + "=\"" + attributes.getValue(i) + "\"");
}
}
System.out.print( ">");
super.startElement(uri, localName, qName, attributes);
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
System.out.println("</" + qName + ">");
super.endElement(uri, localName, qName);
}
/*
* 此方法有三个参数
* ch是传回来的字符数组,其包含元素内容
* start和length分别是数组的开始位置和结束位置
*/
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
String content = new String(ch, start, length);
System.out.print(content);
super.characters(ch, start, length);
}
}
使用SAX解析XML:SAXTest.java
package ssm.pojectTest.parseXML.SAX;
import java.io.File;
import java.io.IOException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.SAXException;
public class SAXTest {
public static void main(String [] args) {
// 1.实例化SAXParserFactory对象
SAXParserFactory factory = SAXParserFactory.newInstance();
// 2.创建解析器
try {
SAXParser parser = factory.newSAXParser();
// 3. 获取需要解析的文档
File f = new File("src/test/java/ssm/pojectTest/parseXML/book.xml");
SaxHandler handler = new SaxHandler();
parser.parse(f,handler);
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
结束,目前就对这两个解析方式进行了简单查阅,还有StAX.以后有机会在介绍