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


    首先创建一个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类型node
    					if (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 block
    			e.printStackTrace();
    		} catch (SAXException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.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 block
    			e.printStackTrace();
    		} catch (SAXException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.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文件的开始标签
    	@Override
    	public 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文件的结束标签
    	@Override
    	public 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);
    		}
    		
    	};
    	
    	// 用来标志解析开始
    	@Override
    	public void startDocument() throws SAXException {
    		// TODO Auto-generated method stub
    		super.startDocument();
    		System.out.println("SAX解析开始");
    	}
    	
    	// 用来标志解析结束
    	@Override
    	public void endDocument() throws SAXException {
    		// TODO Auto-generated method stub
    		super.endDocument();
    		System.out.println("SAX解析结束");
    	}
    	
    	@Override
    	public void characters(char[] ch, int start, int length) throws SAXException {
    		// TODO Auto-generated method stub
    		super.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解析:

    ---------开始解析第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 block
    			e.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。
  • 相关阅读:
    windows下建立多重文件夹
    one-hot向量,softmax向量和反向传播
    牛客网高级项目实战课第一章
    Mysql索引的创建与删除
    Tomcat服务器
    JavaWeb基本概念
    Windows系统下Elasticsearch集群搭建
    数据结构之排序算法1
    如何求一个数的平方根
    数据结构之查找算法
  • 原文地址:https://www.cnblogs.com/miaozhenzhong/p/5931031.html
Copyright © 2020-2023  润新知