博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java 读取 xml 文件
阅读量:4877 次
发布时间:2019-06-11

本文共 11909 字,大约阅读时间需要 39 分钟。

冰与火之歌
乔治马丁
2014
89

 

这是一个简单的xml文件,根节点是bookstore,book是bookstroe的子节点,book节点有属性id ,也有子节点name author year price。子节点name author year price没有属性 ,只有值。

1、DOM: Document Object Model 文档对象模型

  DOM解析会一次性的将xml读取到内存中,并形成一个DOM树,如果xml非常大会浪费时间,对内存性能要求高。

  优点:形成树结构,直观好理解,代码更易编写,解析过程中树结构保留在内存中,方便修改。

    缺点:当xml文件较大时,对内存耗费比较大,容易影响解析性能并造成内存溢出。

package com.zhao.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.Element;import org.w3c.dom.NamedNodeMap;import org.w3c.dom.Node;import org.w3c.dom.NodeList;import org.xml.sax.SAXException;public class DOMTest {/*** 应用DOM方式解析XML DOM: Document Object Model 文档对象模型* DOM解析会一次性的将xml读取到内存中,并形成一个dom树,如果xml非常大会浪费时间,对内存性能要求高* @author zhao* @param args*/public static void main(String[] args) {// 创建一个DocumentBuilderFactory的对象DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();try {// 创建一个DocumentBuilder的对象DocumentBuilder builder = factory.newDocumentBuilder();// 通过DocumentBuilder对象的parse方法加载bookstroe.xml文件到当前项目下Document document = builder.parse("bookstore.xml");// 获取所有book节点的集合NodeList bookList = document.getElementsByTagName("book");// 通过NodeList的getLength方法可以获取boolList的长度System.out.println("===========" + bookList.getLength() + "===========");// 遍历每一个book节点for (int i = 0; i < bookList.getLength(); i++) {// 已经知道节点元素的属性名:/** Element element=(Element) bookList.item(i); String* id=element.getAttribute("id"); System.out.println(id);*/// 不知道节点元素的属性名:// 通过item(i)方法获取一个book节点,NodeList的索引值从0开始Node book = bookList.item(i);// 获取book节点的所有属性集合NamedNodeMap map = book.getAttributes();// 遍历book的属性System.out.println("第" + (i + 1) + "本书共有" + map.getLength() + "个属性");for (int j = 0; j < map.getLength(); j++) {// 通过item(j)方法获取book节点的某一个属性Node attr = map.item(j);// 获取属性名和属性值System.out.println(attr.getNodeName() + "=" + attr.getNodeValue());}// 解析book节点的子节点NodeList childNode = book.getChildNodes();System.out.println(childNode.getLength());/** 通过book元素的getChildNodes()得到所有子节点的集合,需要注意的是,在DOM的读取中,* 会将空格和回车看成是text节点类型,因此需要注意区分开。通过item(index)遍历所有子节点,通过item(* index)的getNodeName()方法还来获取子节点的名字,而获取它的属性值时,* 要注意直接使用getNodeValue()得到的是标签的值(一般是空)因此可以使用两种方法:* 1.使用item(index).getFirstNode().getNodeValue()来返回值(
冰与火之歌*
中冰与火之歌是name的子节点,而且这个节点类型是text,现在我们有节点name,* 只需要找到它的第一个节点的节点值便可以了)* 2.使用item(index).getTextContent()来返回属性值* 上面两种方法的区别在于在一个标签中是否包含的其他的子标签,如果有的话,那么第1个方法就仍得到null,* 第二个方法会返会将自标签的内容一起获得。*/// 遍历childNode获取每个节点的节点名和节点值for (int j = 0; j < childNode.getLength(); j++) {Node child = childNode.item(j);// System.out.println(child.getNodeName());// 区分test类型的node和element类型的nodeif (child.getNodeType() == Node.ELEMENT_NODE) {System.out.println(child.getNodeName() + "=" + child.getTextContent());}}}} catch (ParserConfigurationException e) {e.printStackTrace();} catch (SAXException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}

 

分析:

  DOM使用DocumenBuilder的parse方法加载xml文件到当前目录下,parse是分析的意思。首先会用到工厂模式,先生成DocumentBuilderFactory,再由其生成DocumentBuilder,DocumentBuilder.parse会返回一个Document对象,这是xml文件到Document的过程,无论使用DOM ,SAX,JDOM,DOM4J,此步骤大同小异。

  Document就是上面写好的xml文件。

  常用节点类型       nodeName      nodeValue

  Element      element Name      null

  Attr          属性名称                   属性值

  Test          #text        节点内容

  在此document中,bookstroe是节点,book是节点,name是节点,id也是节点。类似于HTML,document.getElementsByTagName("book")可以得到所有book element,book节点有属性节点Attr,有子节点Element,也有空格Text。Node是所有节点的总称,在未知节点类型时使用Node,所有有book node。

  book node的getAttributes返回属性节点的集合NamedNodeMap,进而得到其每个属性节点node,由上述可得属性名称是node.getNodeName,属性值是node.getNodeValue。

 book.getChildNodes得到子节点集合,这里我们依旧用Node此时node是element或Text,判断child.getNodeType() == Node.ELEMENT_NODE才是我们需要的子节点,对

<name>冰与火之歌</name>而言,node是name,类型是element,而element的NodeValue却不是冰与火之歌,而是null。冰与火之歌是node的子节点text。故node.getFirstNode().getNodeValue()才是我们需要的结果。

2:SAX

  优点:采用事件驱动模式,对内存耗费比较小,适用于只需要处理xml数据时。

  缺点:不易编码,很难同时访问同一个xml中的多处不通过数据

package com.zhao.sax;import java.io.IOException;import javax.xml.parsers.ParserConfigurationException;import javax.xml.parsers.SAXParser;import javax.xml.parsers.SAXParserFactory;import org.xml.sax.SAXException;import org.xml.sax.helpers.DefaultHandler;public class SAXTest {/*** 应用SAX方式解析XML* sax解析是基于事件的解析,每解析一部分就会触发saxHandler的具体方法* @author zhao* @param args*/public static void main(String[] args) {// 获取一个SAXParserFactory的实例SAXParserFactory factory = SAXParserFactory.newInstance();try {// 通过factory获取SAXParser实例SAXParser saxParser = factory.newSAXParser();// 创建SAXHandler对象SAXHandler handler = new SAXHandler();saxParser.parse("bookstore.xml", handler);} 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();}}}

 

----------------------

package com.zhao.sax;import java.util.ArrayList;import java.util.List;import org.xml.sax.Attributes;import org.xml.sax.SAXException;import org.xml.sax.helpers.DefaultHandler;import com.zhao.entity.Book;/*** SAXParserHandler类的执行顺序为:startDocument()开始Xml解析--->第一行,以后每行的执行顺序为——>* startElement()---characters()--->endElemnet()---->到最后一行的* 
---->endDcunment()。* * @author zhao**/public class SAXHandler extends DefaultHandler {private int bookIndex = 0;private Book book;private String value=null;private List
books=new ArrayList
();/*** 用于标识解析开始*/@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解析结束");for (Book book : books) {System.out.println(book);}}/*** 用来遍历xml文件的开始标签 在开始时可用知道属性*/@Overridepublic void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {// 调用DefaultHandler类的startElement方法super.startElement(uri, localName, qName, attributes);// 开始解析book元素的属性if ("book".equals(qName)) {bookIndex++;System.out.println(bookIndex + "本书开始");book=new Book();// 已知book元素的下属性的名称,根据属性名称获取属性值// String id=attributes.getValue("id");// System.out.println("id: "+id);// 不知道book元素下的属性名称,以及个数for (int i = 0; i < attributes.getLength(); i++) {System.out.println(attributes.getQName(i) + ": " + attributes.getValue(i));if ("id".equals(attributes.getQName(i))) {book.setId(attributes.getValue(i));}}} else if (!"book".equals(qName) && !"bookstore".equals(qName)) {System.out.print(qName);}}/*** 用来遍历xml文件的结束标签*/@Overridepublic void endElement(String uri, String localName, String qName) throws SAXException {// TODO Auto-generated method stubsuper.endElement(uri, localName, qName);if ("book".equals(qName)) {System.out.println(bookIndex + "本书结束");books.add(book);book=null;value=null;}else if (!"bookStore".equals(qName)&&!"book".equals(qName)) {if ("name".equals(qName)) {book.setName(value);}else if ("author".equals(qName)) {book.setAuthor(value);}else if("year".equals(qName)){book.setYear(value);}else if ("price".equals(qName)) {book.setPrice(value);}else if ("language".equals(qName)) {book.setLanguage(value);}}}/*** * @param ch* @param start* @param length* @throws SAXException*/@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).trim();if (!value.equals("")) {System.out.println(value);}}}

 

分析:

  SAX使用SAXParser的parse方法解析xml,也是通过SAXParserFactory生成SAXParser。不同于DOMde 节点,sax采用事件驱动,要重写DefaultHandler类,在此类中指明解析xml的过程。

  重写DefaultHandler的startDocument endDocument startElement endElement characters方法。

  解析顺序为:

  startDocument()开始xml解析--》startDocument()开始<bookstore>--》startDocument()开始<book>--》startDocument()开始<name>--》~~~endDocument。

  以<>开始,以</>结束,事件驱动,读到标签开始就是startElement,读到标签结束就是endElement。在二者之间是在characters中读内容。

3:JDOM

  仅适用具体类而不适用接口,API大量使用了Colletions类

package com.zhao.jdom;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;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;import com.zhao.entity.Book;public class JDOMTest {/*** 应用JDOM方式解析xml* * @author zhao* @param args*/public static void main(String[] args) {// 准备工作// 1:创建一个SAXBuilder对象SAXBuilder saxBuilder = new SAXBuilder();InputStream inputStream;try {// 创建一个输入流,把xml文件加载到输入流inputStream = new FileInputStream("bookstore.xml");InputStreamReader streamReader = new InputStreamReader(inputStream, "UTF-8");// 通过saxBuilder的build方法,将输入流加载到saxBuilder中Document doucment = saxBuilder.build(streamReader);// 通过document对象获取xml文件的根节点Element rootElement = doucment.getRootElement();// 获取根节点下的子节点的List集合List
bookList = rootElement.getChildren();// 继续进行解析for (Element element : bookList) {Book book = new Book();System.out.println("开始解析" + (bookList.indexOf(element) + 1));// Attribute id=element.getAttribute("id");// System.out.println(id.getName()+" "+id.getValue());// 解析book的属性List
attributes = element.getAttributes();for (Attribute attribute : attributes) {System.out.println(attribute.getName() + " " + attribute.getValue());if ("id".equals(attribute.getName())) {book.setId(attribute.getValue());}}// 对book节点的子节点的节点名和节点值的遍历List
bookChilds = element.getChildren();for (Element child : bookChilds) {System.out.println(child.getName() + " " + child.getValue());if ("name".equals(child.getName())) {book.setName(child.getValue());}if ("author".equals(child.getName())) {book.setAuthor(child.getValue());}if ("year".equals(child.getName())) {book.setYear(child.getValue());}if ("price".equals(child.getName())) {book.setPrice(child.getValue());}if ("language".equals(child.getName())) {book.setLanguage(child.getValue());}}System.out.println(book);}} 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();}}}

 

4:DOM4J    DOM FOR JAVA

  JDOM的一种智能分之,它合并了许多超出基本xml文档表示的功能,使用接口和抽象基本类方法,是一个优秀的Java xml API,具有性能优异,灵活性好,功能强大和极端易用使用的特点。

package com.zhao.dom4j;import java.io.File;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 DOM4JTest {/*** 应用DOM4J解析xml* * @author zhao* @param args*/public static void main(String[] args) {// 创建SAXReader的readerSAXReader saxReader = new SAXReader();try {// 通过reader的read方法加载xml文件,获取document对象Document document = saxReader.read(new File("bookstore.xml"));// 通过document对象获取根节点bookstoreElement bookStore = document.getRootElement();//通过element对象的elementIterator方法获取迭代器Iterator iterator = bookStore.elementIterator();//遍历迭代器,获取根节点中的信息(书籍)while (iterator.hasNext()) {System.out.println("开始遍历");Element book = (Element) iterator.next();//获取book的属性名和属性值List
attributes=book.attributes();for (Attribute attribute : attributes) {System.out.println(attribute.getName()+" "+attribute.getValue());}//Iterator
iterator2=book.elementIterator();while (iterator2.hasNext()) {Element element = (Element) iterator2.next();System.out.println(element.getName()+" "+element.getStringValue());}}} catch (DocumentException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}

 

转载于:https://www.cnblogs.com/zhao307/p/5348198.html

你可能感兴趣的文章
hud 4454 Stealing a Cake 解题报告
查看>>
冒泡排序
查看>>
深入理解java:1.3.1 JVM内存区域的划分(运行时数据区)
查看>>
hdu_3518_Boring counting(后缀数组)
查看>>
逆波兰表达式计算'1 + (5 - 2) * 3'
查看>>
【洛谷2051】[AHOI2009] 中国象棋(烦人的动态规划)
查看>>
常见渗透测试工具集成系统简介
查看>>
Cannot run Eclipse; JVM terminated. Exit code=13
查看>>
文件上传
查看>>
敏捷软件开发_UML<一>
查看>>
Coursera台大机器学习技法课程笔记07-Blending and Bagging
查看>>
(五)函数装饰器和闭包
查看>>
经典变量练习
查看>>
SQL注入学习总结(四):SQL注入中的绕过
查看>>
Ajax笔记
查看>>
Nginx配置文件详细说明
查看>>
python遇到的问题汇总
查看>>
DBGRID 拖动滚动条 和 鼠标滚轮的问题
查看>>
快速排序、冒泡排序
查看>>
多个Tomcat同时启动的解决方案
查看>>