DOM,SAX,JDOM,DOM4J 四种方式解析xml

来源:互联网 发布:灌篮高手山王数据 编辑:程序博客网 时间:2024/05/02 10:44

首先创建一个xml文档,文档内容如下


<?xml version="1.0" encoding="UTF-8"?><bookstore><book id="1"><name>编程之美</name><price>34.0</price><author>《编程之美》小组</author></book><book id="2"><name>平凡的世界</name><price>56.0</price><author>路遥</author><language>中文</language></book></bookstore>


因为xml定义是书店的书本详情,解析完xml之后,希望把解析之后的数据保存下来,所以定义了一个Book的Entity,定义好各个属性


package com.ikok.parsexml;public class Book {private String id;private String name;private String price;private String author;private String language;public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPrice() {return price;}public void setPrice(String price) {this.price = price;}public String getAuthor() {return author;}public void setAuthor(String author) {this.author = author;}public String getLanguage() {return language;}public void setLanguage(String language) {this.language = language;}}


DOM解析:


package com.ikok.parsexml;import java.io.IOException;import java.util.ArrayList;import java.util.List;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;public class domXml {private static List<Book> booksList = new ArrayList<Book>();public static void main(String[] args) {// 创建一个DocumentBuilderFactory对象DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();try {// 创建一个DocumentBuilder对象DocumentBuilder db = dbf.newDocumentBuilder();// 通过DocumentBuilder对象的parse方法加载xml文件到当前项目Document document = db.parse("books.xml");// 获取所有book节点的集合NodeList bookList = document.getElementsByTagName("book");// 遍历每一个book节点,通过bookList.getLength()方法知道集合的长度System.out.println("一共有 " + bookList.getLength() + " 本书");for (int i = 0; i < bookList.getLength(); i++) {Book bookItem = new Book();System.out.println("-----------开始遍历第" + (i+1) + "本书的内容-----------");// 通过item(i)的方法获取一个book节点,NodeList的索引值从0开始Node book = bookList.item(i);// 获取book节点的所有属性集合NamedNodeMap attrs = book.getAttributes();System.out.println("第 " + (i+1) + " 本书共有 " + attrs.getLength() + " 个属性");// 遍历book的属性for (int j = 0; j < attrs.getLength(); j++) {// 通过item(i)的方法获取一个book节点的某个属性Node attr = attrs.item(j);// 获取属性名System.out.print("属性名为:" + attr.getNodeName());// 获取属性值System.out.println("----属性值为:" + attr.getNodeValue());if(attr.getNodeName().equals("id")){bookItem.setId(attr.getNodeValue());}}// 当知道节点有且只有一个属性时,进行强制类型转换,通过getAttribute()方法获取属性值//Element book = (Element) bookList.item(i);//String attrValue = book.getAttribute("id");//System.out.println("id :" + attrValue);//解析book节点的子节点NodeList childList = book.getChildNodes();System.out.println("第 " + (i+1) + " 本书共有 " + childList.getLength() + " 个子节点");for (int k = 0; k < childList.getLength(); k++) {// 区分出text类型的node以及element类型nodeif (childList.item(k).getNodeType() == Node.ELEMENT_NODE) {// 获取了element类型节点的节点名System.out.print("第 " + (i+1) + " 本书的子节点名: " + childList.item(k).getNodeName() + "----");// 如果当前节点中还有节点,则属性值为空。比如<name><a>aa</a><b>bb</b>第一行代码</name>System.out.println(" 属性值: " + childList.item(k).getFirstChild().getNodeValue());// 这样会输出所有子节点和节点之间的内容。会输出    aabb第一行代码//System.out.println(childList.item(k).getTextContent());if(childList.item(k).getNodeName().equals("name")){bookItem.setName(childList.item(k).getFirstChild().getNodeValue());} else if(childList.item(k).getNodeName().equals("price")){bookItem.setPrice(childList.item(k).getFirstChild().getNodeValue());} else if(childList.item(k).getNodeName().equals("author")){bookItem.setAuthor(childList.item(k).getFirstChild().getNodeValue());} else if(childList.item(k).getNodeName().equals("language")){bookItem.setLanguage(childList.item(k).getFirstChild().getNodeValue());}}}System.out.println("-----------结束遍历第" + (i+1) + "本书的内容-----------");System.out.println();booksList.add(bookItem);bookItem = null;}for (Book item : booksList) {System.out.println("书本id :" + item.getId());System.out.println("书本名字 :" + item.getName());System.out.println("书本价格 :" + item.getPrice());System.out.println("书本作者 :" + item.getAuthor());System.out.println("书本语言 :" + item.getLanguage());System.out.println("---------------------------------");}} catch (ParserConfigurationException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (SAXException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
结果:

一共有 2 本书-----------开始遍历第1本书的内容-----------第 1 本书共有 1 个属性属性名为:id----属性值为:1第 1 本书共有 7 个子节点第 1 本书的子节点名: name---- 属性值: 编程之美第 1 本书的子节点名: price---- 属性值: 34.0第 1 本书的子节点名: author---- 属性值: 《编程之美》小组-----------结束遍历第1本书的内容----------------------开始遍历第2本书的内容-----------第 2 本书共有 1 个属性属性名为:id----属性值为:2第 2 本书共有 9 个子节点第 2 本书的子节点名: name---- 属性值: 平凡的世界第 2 本书的子节点名: price---- 属性值: 56.0第 2 本书的子节点名: author---- 属性值: 路遥第 2 本书的子节点名: language---- 属性值: 中文-----------结束遍历第2本书的内容-----------书本id :1书本名字 :编程之美书本价格 :34.0书本作者 :《编程之美》小组书本语言 :null---------------------------------书本id :2书本名字 :平凡的世界书本价格 :56.0书本作者 :路遥书本语言 :中文---------------------------------



SAX解析:


package com.ikok.parsexml;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 SAXXml {public static void main(String[] args) {// 创建一个SAXParserFactory的实例SAXParserFactory saxpf = SAXParserFactory.newInstance();try {// 通过SAXParserFactory的实例获取SAXParser的实例SAXParser parser = saxpf.newSAXParser();SAXParserHandler handler = new SAXParserHandler();parser.parse("books.xml", handler);System.out.println("共有  " + handler.getBookList().size() + " 本书");for (Book book : handler.getBookList()) {System.out.println("书本id :" + book.getId());System.out.println("书本名字 :" + book.getName());System.out.println("书本价格 :" + book.getPrice());System.out.println("书本作者 :" + book.getAuthor());System.out.println("书本语言 :" + book.getLanguage());System.out.println("---------------------------------");}} catch (ParserConfigurationException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (SAXException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}


因为SAX解析xml的解析方法需要一个DefaultHandler参数,所以我定义了一个SAXParserHandler来继承这个类,重写部分方法


package com.ikok.parsexml;import java.util.ArrayList;import java.util.List;import org.xml.sax.Attributes;import org.xml.sax.SAXException;import org.xml.sax.helpers.DefaultHandler;public class SAXParserHandler extends DefaultHandler {// 书本的序号int bookIndex = 0;/** * 某个属性值 * 因为属性名在startElement()方法中得到,而属性值却在characters()方法中得到 * 为了能把属性名和属性值加到book实例中去,在endElement()方法前,另外两个方法都执行了,所以在这进行处理 */String value = null;Book book = null;private List<Book> bookList = new ArrayList<Book>();public List<Book> getBookList() {return bookList;}// 用来遍历xml文件的开始标签@Overridepublic void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {super.startElement(uri, localName, qName, attributes);// 开始解析book元素的属性if(qName.equals("book")){// 创建一个book对象book = new Book();bookIndex++;System.out.println("-----------开始遍历第" + bookIndex + "本书的内容-----------");//// 已知book元素下属性的名称,根据属性名获取属性值//String value = attributes.getValue("id");//System.out.println("id:" + value);// 不知道book元素下属性的名称以及个数,获取属性名及属性值// 属性个数int num = attributes.getLength();for (int i = 0; i < num; i++) {System.out.print("第 " + (i+1) + "个属性名: " + attributes.getQName(i));System.out.println(" 属性值: " + attributes.getValue(i));if (attributes.getQName(i).equals("id")) {book.setId(attributes.getValue(i));}}} else if(!qName.equals("book") && !qName.equals("bookstore")){System.out.print("节点名:" + qName + " 节点值:");}};// 用来遍历xml文件的结束标签@Overridepublic void endElement(String uri, String localName, String qName) throws SAXException {super.endElement(uri, localName, qName);// 针对一本书的内容是否遍历结束if (qName.equals("book")) {// 清空book,方便执行下一个bookList.add(book);book = null;System.out.println("-----------结束遍历第" + bookIndex + "本书的内容-----------");} else if(qName.equals("name")){book.setName(value);} else if(qName.equals("price")){book.setPrice(value);} else if(qName.equals("author")){book.setAuthor(value);} else if(qName.equals("language")){book.setLanguage(value);}};// 用来标志解析开始@Overridepublic void startDocument() throws SAXException {// TODO Auto-generated method stubsuper.startDocument();System.out.println("SAX解析开始");}// 用来标志解析结束@Overridepublic void endDocument() throws SAXException {// TODO Auto-generated method stubsuper.endDocument();System.out.println("SAX解析结束");}@Overridepublic void characters(char[] ch, int start, int length) throws SAXException {// TODO Auto-generated method stubsuper.characters(ch, start, length);// 获取了属性值value = new String(ch, start, length);// 默认情况下,会把xml中的换行符也算进去,输出格式不正确,去掉换行符if (!value.trim().equals("")) {System.out.println(value);}}}
结果:

SAX解析开始-----------开始遍历第1本书的内容-----------第 1个属性名: id 属性值: 1节点名:name 节点值:编程之美节点名:price 节点值:34.0节点名:author 节点值:《编程之美》小组-----------结束遍历第1本书的内容----------------------开始遍历第2本书的内容-----------第 1个属性名: id 属性值: 2节点名:name 节点值:平凡的世界节点名:price 节点值:56.0节点名:author 节点值:路遥节点名:language 节点值:中文-----------结束遍历第2本书的内容-----------SAX解析结束共有  2 本书书本id :1书本名字 :编程之美书本价格 :34.0书本作者 :《编程之美》小组书本语言 :null---------------------------------书本id :2书本名字 :平凡的世界书本价格 :56.0书本作者 :路遥书本语言 :中文---------------------------------


JDOM解析:


package com.ikok.parsexml;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.List;import org.jdom2.Attribute;import org.jdom2.Document;import org.jdom2.Element;import org.jdom2.JDOMException;import org.jdom2.input.SAXBuilder;public class JdomXml {private static List<Book> bookList = new ArrayList<Book>();public static void main(String[] args) {// 创建一个SAXBuilder对象SAXBuilder saxbuilder = new SAXBuilder();// 创建一个输入流,将xml加载到输入流中InputStream is;try {is = new FileInputStream("books.xml");// 防止解析乱码,将xml的encoding属性改为UTF-8,或者在代码中设置输入流的编码方式//InputStreamReader isr = new InputStreamReader(is, "UTF-8");//Document document = (Document) saxbuilder.build(isr);// 通过saxbuilder.build()方法,将输入流加载到saxbuilder中Document document = (Document) saxbuilder.build(is);// 通过document对象获取xml的根节点Element rootElement = document.getRootElement();// 获取根节点下的子节点的集合List<Element> elementList = rootElement.getChildren();for (Element element : elementList) {Book book = new Book();System.out.println("---------开始解析第" + (elementList.indexOf(element)+1) + "本书-----------------");//// 知道属性的名字及个数//System.out.println(element.getAttributeValue("id"));// 获取属性集合,不知道属性的名字及个数List<Attribute> attrList = element.getAttributes();for (Attribute attribute : attrList) {// 属性名String attrName = attribute.getName();// 属性值String attrValue = attribute.getValue();// 存储到Book中if (attrName.equals("id")) {book.setId(attrValue);}System.out.println("属性名:" + attrName + "----属性值:" + attrValue);}// 对book节点下的子节点的节点名以及节点值进行解析List<Element> childList = element.getChildren();for (Element child : childList) {// 属性名String attrName = child.getName();// 属性值String attrValue = child.getValue();// 存储到Book中if(attrName.equals("name")){book.setName(attrValue);} else if(attrName.equals("price")){book.setPrice(attrValue);} else if(attrName.equals("author")){book.setAuthor(attrValue);} else if(attrName.equals("language")){book.setLanguage(attrValue);}System.out.println("子节点名:" + attrName + "----子节点属性值:" + attrValue);}System.out.println("---------结束解析第" + (elementList.indexOf(element)+1) + "本书-----------------");bookList.add(book);book = null;}for (Book item : bookList) {System.out.println("书本id :" + item.getId());System.out.println("书本名字 :" + item.getName());System.out.println("书本价格 :" + item.getPrice());System.out.println("书本作者 :" + item.getAuthor());System.out.println("书本语言 :" + item.getLanguage());System.out.println("---------------------------------");}} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (JDOMException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}

结果:

---------开始解析第1本书-----------------属性名:id----属性值:1子节点名:name----子节点属性值:编程之美子节点名:price----子节点属性值:34.0子节点名:author----子节点属性值:《编程之美》小组---------结束解析第1本书--------------------------开始解析第2本书-----------------属性名:id----属性值:2子节点名:name----子节点属性值:平凡的世界子节点名:price----子节点属性值:56.0子节点名:author----子节点属性值:路遥子节点名:language----子节点属性值:中文---------结束解析第2本书-----------------书本id :1书本名字 :编程之美书本价格 :34.0书本作者 :《编程之美》小组书本语言 :null---------------------------------书本id :2书本名字 :平凡的世界书本价格 :56.0书本作者 :路遥书本语言 :中文---------------------------------


DOM4J解析:


package com.ikok.parsexml;import java.io.File;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import org.dom4j.Attribute;import org.dom4j.Document;import org.dom4j.DocumentException;import org.dom4j.Element;import org.dom4j.io.SAXReader;public class dom4jXml {private static List<Book> bookList = new ArrayList<Book>();// 书的序号static int bookIndex = 0;public static void main(String[] args) {// 创建SAXReader的对象SAXReader reader = new SAXReader();try {// 通过reader的read()方法加载xml文件,获取document对象Document document = reader.read(new File("books.xml"));// 获取根节点Element rootElement = document.getRootElement();// 获取迭代器Iterator iterator = rootElement.elementIterator();// 遍历迭代器,获取根节点中的信息while (iterator.hasNext()) {bookIndex++;Book bookItem = new Book();System.out.println("----------开始遍历第" + bookIndex + "本书------------");Element book = (Element) iterator.next();// 获取属性名和属性值List<Attribute> attrList = book.attributes();for (Attribute attr : attrList) {if(attr.getName().equals("id")){bookItem.setId(attr.getValue());}System.out.println("属性名:" + attr.getName() + "----属性值:" + attr.getValue());}Iterator it = book.elementIterator();while (it.hasNext()) {Element element = (Element) it.next();if(element.getName().equals("name")){bookItem.setName(element.getStringValue());} else if(element.getName().equals("price")){bookItem.setPrice(element.getStringValue());} else if(element.getName().equals("author")){bookItem.setAuthor(element.getStringValue());} else if(element.getName().equals("language")){bookItem.setLanguage(element.getStringValue());}System.out.println("子节点名:" + element.getName() + "----子节点属性值:" + element.getStringValue());}System.out.println("----------结束遍历第" + bookIndex + "本书------------");bookList.add(bookItem);bookItem = null;}for (Book item : bookList) {System.out.println("书本id :" + item.getId());System.out.println("书本名字 :" + item.getName());System.out.println("书本价格 :" + item.getPrice());System.out.println("书本作者 :" + item.getAuthor());System.out.println("书本语言 :" + item.getLanguage());System.out.println("---------------------------------");}} catch (DocumentException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
结果:

----------开始遍历第1本书------------属性名:id----属性值:1子节点名:name----子节点属性值:编程之美子节点名:price----子节点属性值:34.0子节点名:author----子节点属性值:《编程之美》小组----------结束遍历第1本书----------------------开始遍历第2本书------------属性名:id----属性值:2子节点名:name----子节点属性值:平凡的世界子节点名:price----子节点属性值:56.0子节点名:author----子节点属性值:路遥子节点名:language----子节点属性值:中文----------结束遍历第2本书------------书本id :1书本名字 :编程之美书本价格 :34.0书本作者 :《编程之美》小组书本语言 :null---------------------------------书本id :2书本名字 :平凡的世界书本价格 :56.0书本作者 :路遥书本语言 :中文---------------------------------


这里,JDOM我用的是2.0.5的包,DOM4J我用的是1.6.1的包。

以当前这个XML为解析的目标的情况下,解析耗时,SAX耗时比DOM短,DOM4J耗时比JDOM短。

目前hibernate框架中也是使用的DOM4J解析XML。



0 0
原创粉丝点击