Java解析XML文件共有四种方式:
1.DOM
2.SAX
3.DOM4j
4.JDOM
其中前两种方式是JAVA语言默认支持的,后两者为第三方jar包提供支持。
<!--样例文件book.xml-->
<?xml version="1.0" encoding="UTF-8" ?>
<bookList>
<book id = "1">
<name>冰与火之歌</name>
<author>乔治马丁</author>
<price>56</price>
</book>
<book id = "2">
<name>Java编程思想</name>
<author>SomeOne</author>
<price>52</price>
</book>
</bookList>
1.DOM解析,将整个文件解析后作为一个Document整体对象做处理。
/**
* Created by Mr.Wang on 2019/2/20.
*/
public class DOMParseTest {
public static void main(String[] args) {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); //1.获取DocumentBuilderFactory工厂对象
try{
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); //2.创建DocumentBuilder对象
Document document = documentBuilder.parse("I:\\practice\\book.xml"); //3.获取文件对象
NodeList bookLists = document.getElementsByTagName("book"); //根据节点名称获取子节点
System.out.println("共有:" + bookLists.getLength() + "个book节点");
for (int i = 0 ; i<bookLists.getLength() ; i++) { //遍历每一个节点
Node book = bookLists.item(i);
NamedNodeMap attrMap = book.getAttributes(); //获取节点的属性
System.out.println("节点" + i + "有" + attrMap.getLength() + "个属性");
for (int j = 0; j < attrMap.getLength(); j++) {
Node attr = attrMap.item(j);
System.out.println("节点" + i + "的属性" + j + ":" + attr.getNodeName() + "--" + attr.getNodeValue());
}
NodeList childNodes = book.getChildNodes(); //获取子节点
System.out.println("节点" + i + "有" + childNodes.getLength() + "个子节点");
for (int k = 0; k < childNodes.getLength() ; k++) {
Node child = childNodes.item(k);
if(child.getNodeType() == Node.ELEMENT_NODE){
String childNodeName = child.getNodeName(); //子节点名称
String childNodeValue = child.getTextContent(); //节点内容
System.out.println("节点" + i + "的子节点" + k + ":" + childNodeName + "--" + childNodeValue);
}
}
}
}catch(Exception e){
System.out.println(e);
}
}
}
2.SAX解析,是遍历文件的同时,根据标签首/尾将标签内容解析出来。需要自定义ParseHandler类,重写方法。
其中常用的几个方法:
startDocument() , endDocument() 开始/结束 解析文档的方法
startElement() , endElement() 开始/结束 结束标签的方法
character() 获取标签值的方法
/**
* Created by Mr.Wang on 2019/2/20.
*/
public class SAXParseTest {
public static void main(String[] args){
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); //1.获取SAXParserFactory工厂
try{
SAXParser saxParser = saxParserFactory.newSAXParser(); //2.获取解析器
SAXParseHandler handler = new SAXParseHandler(); //3.创建自定义处理器对象 解析处理工作都在该对象中处理
saxParser.parse("I:\\practice\\book.xml",handler); //4.解析文件
}catch (Exception e){
System.out.println(e);
}
}
}
class SAXParseHandler extends DefaultHandler{
/**
* 开始解析文件
* @throws SAXException
*/
@Override
public void startDocument() throws SAXException {
System.out.println("开始解析文件...");
super.startDocument();
}
/**
* 解析文件结束
* @throws SAXException
*/
@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(qName.equals("book")){
System.out.println("==========开始遍历book节点========");
System.out.println("book节点下共有" + attributes.getLength() + "个属性");
for (int i = 0; i < attributes.getLength(); i++) {
System.out.println("属性:" + i + ":" + attributes.getQName(i) + "-" + attributes.getValue(i));
}
}
if(!qName.equals("book") && !qName.equals("bookList")){
System.out.println("子节点:" + qName);
}
}
/**
* 结束解析元素
* @param uri
* @param localName
* @param qName
* @throws SAXException
*/
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
if(qName.equals("book")){
System.out.println("==========结束遍历book节点========");
}
}
/**
* 获取节点值
* @param ch
* @param start
* @param length
* @throws SAXException
*/
public void characters (char ch[], int start, int length) throws SAXException
{
super.characters(ch,start,length);
String value = new String(ch, start, length);
if(!"".equals(value.trim())){
System.out.println(value);
}
}
}
3.JDOM 同DOM解析方式一样,将整个xml文件解析完后,针对Document这个对象进行处理。
package com.wang.com.XMLparse;
import org.jdom2.Attribute;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
/**
* Created by Mr.Wang on 2019/2/26.
*/
public class JDOMParseDemo {
public static void main(String[] args) {
try {
SAXBuilder saxBuilder = new SAXBuilder(); //1.创建SAXBuilder,需引入jdom2第三方jar包
InputStream inputStream = new FileInputStream("I:\\practice\\book.xml");
InputStreamReader reader = new InputStreamReader(inputStream,"UTF-8"); //指定编码
Document document = saxBuilder.build(reader); //2.获取Document对象 可根据文件直接创建,也可通过输入流创建
Element rootElement = document.getRootElement(); //获取根节点
List<Element> childElements = rootElement.getChildren(); //获取根节点的子节点
for (Element child : childElements) { //遍历子节点
System.out.println("=====开始遍历book节点=====");
List<Attribute> attributeList = child.getAttributes(); //获取属性列表
for (int i = 0; i < attributeList.size(); i++) {
System.out.println("属性" + i + ":" + attributeList.get(i).getName() + "-" + attributeList.get(i).getValue());
}
List<Element> childNodes = child.getChildren();
for (Element childNode : childNodes) {
System.out.println("节点" + childNode.getName() + ":" + childNode.getValue() );
}
System.out.println("=====结束遍历book节点=====");
}
} catch (JDOMException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
4.DOM4J解析XML文件也是将文件作为一个Document对象进行处理
package com.wang.com.XMLparse;
import com.sun.xml.internal.bind.v2.runtime.output.NamespaceContextImpl;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.util.Iterator;
import java.util.List;
/**
* Created by Mr.Wang on 2019/2/26.
*/
public class DOM4JDemo {
public static void main(String[] args) {
try {
SAXReader saxReader = new SAXReader(); //1.创建SAXReader对象
Document document = saxReader.read("I:\\practice\\book.xml"); //2.获取Document对象
Element rootElement = document.getRootElement(); //获取根节点
Iterator iterator = rootElement.elementIterator(); //获取子节点的Iterator
while(iterator.hasNext()){
Element element = (Element) iterator.next();
List<Attribute> attributes = element.attributes(); //获取节点的属性
for (Attribute attribute : attributes) {
System.out.println("属性" + attribute.getName() + ":" +attribute.getValue());
}
Iterator childIterator = element.elementIterator();
while(childIterator.hasNext()){
Element childElement = (Element)childIterator.next();
System.out.println("子节点" + childElement.getName() + ":" +childElement.getText());
}
}
} catch (DocumentException e) {
e.printStackTrace();
}
}
}
几种解析方式的优缺点比较:
1.DOM:
优点:1.形成整个文件的树形结构,便于理解与编程
2.结构清楚,便于修改与保存
缺点:一次性将整个文件写入内存中,如果文件过大,会造成空间不足
2.SAX
优点:1.实时解析文件,不会造成内存浪费
缺点:结构不清晰,不便于理解与编程;很难同时处理多处相同标签
3.JDOM和DOM4J之间的比较:DOM4J在JDOM的基础上发展,效率更快。且相较于DOM方式,不会造成内存溢出。
推荐使用DOM4J