java解析读取xml文件的几种方式
dom平台无关,官方解析方式,一次性加载,方便解析,代码容易编写,当文件过大,容易造成内存溢出* sax基于事件驱动的解析方式,加载时进行验证判断,内存耗费小,不易编码,很难同时访问一个xml中的多处不同数据* jdom和dom4j是基于sax扩展* jdom仅使用具体类而不使用接口,api中大量使用了collections类* dom4j是jdom的一种智能分支,具有性能优异,灵活性好,功能强大
·
一、为什么使用xml文件
-
便于不同应用程序之间通信。
-
便于不同平台之间通信。
-
便于不同平台之间数据共享。
二、读取xml的方式
xml测试文件内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<studentInfo>
<student id="1">
<name>小明</name>
<age>28</age>
<birthday>19920114</birthday>
<home>河南</home>
</student>
<student id="2">
<name>小刚</name>
<age>29</age>
<birthday>19911114</birthday>
<home>湖北</home>
</student>
<student id="3">
<name>小红</name>
<age>28</age>
<birthday>19920115</birthday>
<home>湖南</home>
</student>
</studentInfo>
2.1 dom方式读取
dom方式读取xml文件具体源代码如下:
package basic;
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;
publicclass ReadXmlDomService {
public static void main(String[] args){
System.out.println("readXmlByDom start:");
readXmlByDom();
System.out.println("readXmlByDom end.");
}
//dom方式
private static void readXmlByDom(){
try {
// 创建解析器工厂
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder db = factory.newDocumentBuilder();
// 创建一个Document对象
Document doc = db.parse("/Users/liuxiaoming/Desktop/test.xml");
NodeList studentList = doc.getElementsByTagName("student");
// 获取节点个数
System.out.println("一共有" + studentList.getLength() + "同学");
// 遍历每个student节点
for (int i = 0; i < studentList.getLength(); i++) {
System.out.println("*******************************");
// 索引从零开始
org.w3c.dom.Node student = studentList.item(i);
// 获取student节点所有属性集合
org.w3c.dom.NamedNodeMap attrs = student.getAttributes();
System.out.println("第" + (i + 1) + "个同学共有" + attrs.getLength() + "属性");
// 遍历student属性,不知道节点属性和属性名情况
for (int j = 0; j < attrs.getLength(); j++) {
// 获取某一个属性
org.w3c.dom.Node attr = attrs.item(j);
System.out.print("属性名:" + attr.getNodeName());
System.out.println(" --- 属性值:" + attr.getNodeValue());
}
// 若已经知道student节点有且只有1个ID属性,可用以下方式
// org.w3c.dom.Element e = (org.w3c.dom.Element)
// bookList.item(i);
// System.out.println("Element属性值:"+e.getAttribute("id"));
NodeList childNodes = student.getChildNodes();
for (int k = 0; k < childNodes.getLength(); k++) {
// 区分,去掉空格和换行符
if (childNodes.item(k).getNodeType() == Node.ELEMENT_NODE) {
// 获取element类型的节点和节点值
System.out.print("节点名:" + childNodes.item(k).getNodeName());
System.out.print(" --- 节点值:" + childNodes.item(k).getFirstChild().getNodeValue());
System.out.println(" --- 节点值:"+childNodes.item(k).getTextContent());
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果:
readXmlByDom start:
一共有3同学
*******************************
第1个同学共有1属性
属性名:id --- 属性值:1
节点名:name --- 节点值:小明 --- 节点值:小明
节点名:age --- 节点值:28 --- 节点值:28
节点名:birthday --- 节点值:19920114 --- 节点值:19920114
节点名:home --- 节点值:河南 --- 节点值:河南
*******************************
第2个同学共有1属性
属性名:id --- 属性值:2
节点名:name --- 节点值:小刚 --- 节点值:小刚
节点名:age --- 节点值:29 --- 节点值:29
节点名:birthday --- 节点值:19911114 --- 节点值:19911114
节点名:home --- 节点值:湖北 --- 节点值:湖北
*******************************
第3个同学共有1属性
属性名:id --- 属性值:3
节点名:name --- 节点值:小红 --- 节点值:小红
节点名:age --- 节点值:28 --- 节点值:28
节点名:birthday --- 节点值:19920115 --- 节点值:19920115
节点名:home --- 节点值:湖南 --- 节点值:湖南
readXmlByDom end.
2.2 dom4j方式
dom4j方式需要引入dom4j依赖包
maven依赖项:
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
java源码如下:
package basic;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.File;
import java.util.Iterator;
import java.util.List;
publicclass ReadXmlDom4jService {
public static void main(String[] args){
System.out.println("readXmlByDom4j start:");
readXmlByDom4j();
System.out.println("readXmlByDom4j end.");
}
//dom4j方式
private static void readXmlByDom4j(){
try {
// 创建SAXReader对象
SAXReader reader = new SAXReader();
// 加载xml文件
Document dc= reader.read(new File("/Users/liuxiaoming/Desktop/test.xml"));
// 获取根节点
Element e = dc.getRootElement();
// 获取迭代器
Iterator it = e.elementIterator();
// 遍历迭代器,获取根节点信息
while(it.hasNext()){
Element studentInfo = (Element) it.next();
List<Attribute> atts= studentInfo.attributes();
// 获取student属性名和属性值
for (Attribute att : atts) {
System.out.println("节点名:"+att.getName()+"节点值:"+att.getValue());
}
Iterator itt = studentInfo.elementIterator();
while(itt.hasNext()){
Element b = (Element) itt.next();
System.out.println("属性名:"+b.getName()+"属性值:"+b.getText());
}
}
} catch (Exception e) {
// TODO: handle exception
}
}
}
运行结果:
readXmlByDom4j start:
节点名:id节点值:1
属性名:name属性值:小明
属性名:age属性值:28
属性名:birthday属性值:19920114
属性名:home属性值:河南
节点名:id节点值:2
属性名:name属性值:小刚
属性名:age属性值:29
属性名:birthday属性值:19911114
属性名:home属性值:湖北
节点名:id节点值:3
属性名:name属性值:小红
属性名:age属性值:28
属性名:birthday属性值:19920115
属性名:home属性值:湖南
readXmlByDom4j end.
2.3 jdom方式
使用jdom方式需要引入相关maven依赖
<dependency>
<groupId>org.jdom</groupId>
<artifactId>jdom</artifactId>
<version>1.1</version>
</dependency>
jdom方式导入源码如下:
package basic;
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
publicclass ReadXmlJdomService {
public static void main(String[] args){
System.out.println("readXmlByJdom start:");
readXmlByJdom();
System.out.println("readXmlByJdom end.");
}
//jdom方式
private static void readXmlByJdom(){
List<Student> bList = new ArrayList<Student>();
try {
// 创建一个SAXBuilder对象
SAXBuilder builder = new SAXBuilder();
// 创建一个输入流
InputStream in = new FileInputStream("/Users/liuxiaoming/Desktop/test.xml");
// 处理乱码情况
InputStreamReader isr = new InputStreamReader(in, "UTF-8");
// 通过build方法,将输入流加载到SAXBuilder中
Document doc = builder.build(isr);
// 通过Document对象获取根节点
Element foo= doc.getRootElement();
// 获取根节点下子节点名
List<Element> allChildren = foo.getChildren();
// 进行解析
for (Element student : allChildren) {
Student b = new Student();
System.out.println("开始解析第"+(allChildren.indexOf(student)+1)+"个同学");
// 解析student属性集合
List<Attribute> attrList = student.getAttributes();
// 遍历(针对不清楚节点下属性名)
for (Attribute attr : attrList) {
System.out.println("属性名:"+attr.getName() +" -- 属性值:"+attr.getValue());
if("id".equals(attr.getName())){
b.setId(attr.getValue());
}
}
// 清楚知道属性名获取属性值
String v = student.getAttributeValue("id");
System.out.println("清楚知道属性名"+v);
// 对student节点子节点的节点名和节点值进行遍历
List<Element> studentChiles = student.getChildren();
for (Element element : studentChiles) {
System.out.println("属性名:"+element.getName() +" -- 属性值:"+element.getValue());
if("name".equals(element.getName())){
b.setName(element.getValue());
}elseif("age".equals(element.getName())){
b.setAge(element.getValue());
}elseif("home".equals(element.getName())){
b.setHome(element.getValue());
}elseif("birthday".equals(element.getName())){
b.setBirthday(element.getValue());
}elseif("id".equals(element.getName())){
b.setId(element.getValue());
}
}
System.out.println("结束解析第"+(allChildren.indexOf(student)+1)+"个同学");
bList.add(b);
b = null;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果:
readXmlByJdom start:
开始解析第1个同学
属性名:id -- 属性值:1
清楚知道属性名1
属性名:name -- 属性值:小明
属性名:age -- 属性值:28
属性名:birthday -- 属性值:19920114
属性名:home -- 属性值:河南
结束解析第1个同学
开始解析第2个同学
属性名:id -- 属性值:2
清楚知道属性名2
属性名:name -- 属性值:小刚
属性名:age -- 属性值:29
属性名:birthday -- 属性值:19911114
属性名:home -- 属性值:湖北
结束解析第2个同学
开始解析第3个同学
属性名:id -- 属性值:3
清楚知道属性名3
属性名:name -- 属性值:小红
属性名:age -- 属性值:28
属性名:birthday -- 属性值:19920115
属性名:home -- 属性值:湖南
结束解析第3个同学
readXmlByJdom end.
2.4 Sax方式
Sax方式解析xml文件源码如下:
package basic;
import java.util.ArrayList;
import java.util.List;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
publicclass SAXParserHandler extends DefaultHandler {
int studentIndex = 0;
String str = null;
Student student = null;
private List<Student> stuList = new ArrayList<Student>();
public List<Student> getStuList() {
return stuList;
}
/**
* 用来遍历xml文件的开始标签
*/
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
// 调用DefaultHandler的startElement方法
super.startElement(uri, localName, qName, attributes);
// 开始解析student元素属性
if(qName.equals("student")){
studentIndex++;
// 创建一个student对象
student = new Student();
System.out.println("****开始第"+ studentIndex +"个同学内容****");
// 已知student元素下属性名称,根据属性名称获取属性值s
String value = attributes.getValue("id");
System.out.println("student的属性值是:"+value);
int num = attributes.getLength();
for(int i=0;i<num;i++){
System.out.print("student元素的第"+(i+1)+"个属性名是:"+attributes.getQName(i));
System.out.println(" -- 属性值是:"+attributes.getValue(i));
if(attributes.getQName(i).equals("id")){
student.setId(attributes.getQName(i));
}
}
}elseif(!qName.equals("student") && !qName.equals("studentInfo")){
System.out.print("节点名是:"+qName);
}
}
/**
* 用来遍历xml文件的结束标签
*/
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
// 调用DefaultHandler的endElement方法
super.endElement(uri, localName, qName);
// 判断是否针对一本书已经遍历结束
if(qName.equals("student")){
stuList.add(student);
student = null;
System.out.println("****结束第"+ studentIndex +"个同学内容****");
}elseif(qName.equals("name")){
student.setName(str);
}elseif(qName.equals("id")){
student.setId(str);
}elseif(qName.equals("age")){
student.setAge(str);
}elseif(qName.equals("birthday")){
student.setBirthday(str);
}elseif(qName.equals("home")){
student.setHome(str);
}
}
/**
* 用来标志解析开始
*/
@Override
public void startDocument() throws SAXException {
// 调用DefaultHandler的startDocument方法
super.startDocument();
System.out.println("解析开始");
}
/**
* 用来标志解析结束
*/
@Override
public void endDocument() throws SAXException {
// 调用DefaultHandler的endDocument方法
super.endDocument();
System.out.println("解析结束");
}
/**
* 用来标志解析结束
*/
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
// 调用DefaultHandler的characters方法
super.characters(ch, start, length);
str = new String(ch, start, length);
if(!str.trim().equals("")){
System.out.println(" -- 节点值是:"+str);
}
}
}
package basic;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
publicclass ReadXmlSaxService {
public static void main(String[] args){
System.out.println("readXmlByJdom start:");
readXmlBySax();
System.out.println("readXmlByJdom end.");
}
private static void readXmlBySax(){
try {
// 创建工厂
SAXParserFactory sf=SAXParserFactory.newInstance();
// 获取SAXParser实例
SAXParser sp = sf.newSAXParser();
// 创建一个解析对象
SAXParserHandler handler = new SAXParserHandler();
sp.parse("/Users/liuxiaoming/Desktop/test.xml", handler);
for(Student student : handler.getStuList()){
System.out.println(student.getId());
System.out.println(student.getName());
System.out.println(student.getAge());
System.out.println(student.getBirthday());
System.out.println(student.getHome());
System.out.println("*****************");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果:
readXmlByJdom start:
解析开始
****开始第1个同学内容****
student的属性值是:1
student元素的第1个属性名是:id -- 属性值是:1
节点名是:name -- 节点值是:小明
节点名是:age -- 节点值是:28
节点名是:birthday -- 节点值是:19920114
节点名是:home -- 节点值是:河南
****结束第1个同学内容****
****开始第2个同学内容****
student的属性值是:2
student元素的第1个属性名是:id -- 属性值是:2
节点名是:name -- 节点值是:小刚
节点名是:age -- 节点值是:29
节点名是:birthday -- 节点值是:19911114
节点名是:home -- 节点值是:湖北
****结束第2个同学内容****
****开始第3个同学内容****
student的属性值是:3
student元素的第1个属性名是:id -- 属性值是:3
节点名是:name -- 节点值是:小红
节点名是:age -- 节点值是:28
节点名是:birthday -- 节点值是:19920115
节点名是:home -- 节点值是:湖南
****结束第3个同学内容****
解析结束
id
小明
28
19920114
河南
*****************
id
小刚
29
19911114
湖北
*****************
id
小红
28
19920115
湖南
*****************
readXmlByJdom end.
三、总结对比
* dom平台无关,官方解析方式,一次性加载,方便解析,代码容易编写,当文件过大,容易造成内存溢出
* sax基于事件驱动的解析方式,加载时进行验证判断,内存耗费小,不易编码,很难同时访问一个xml中的多处不同数据
*
* jdom和dom4j是基于sax扩展
*
* jdom仅使用具体类而不使用接口,api中大量使用了collections类
*
* dom4j是jdom的一种智能分支,具有性能优异,灵活性好,功能强大和易使用的特点
更多推荐
所有评论(0)