XML基础编程解析(DOM SAX Dom4J)
XML编程:利用java程序去增删改查(CRUD)xml中的数据 解析思想: dom解析 sax解析 基于这两种解析思想市面上就有了很多的解析api sun jaxp既有dom方式也有sax方式,并且这套解析api已经加入到j2se的规范中,意味这不需要导入任何第三方开发包就可以直接使用这种解析方式.但是这种解析方式效率低下,没什么人用. dom4j 可以使用dom方式高效的解析xml. pull !!dom4j 导入开发包,通常只需要导入核心包就可以了,如果在使用的过程中提示少什么包到lib目录下在导入缺少的包即可
先看看两种解析思想的比较:
对于Sax解析:
我们先看一个列子
book.xml
<?xml version="1.0" encoding="UTF-8"?> <书架> <书> <书名>Java就业培训教程</书名> <作者>张孝祥</作者> <售价>39.00元</售价> </书> <书> <书名>JavaScript网页开发</书名> <作者>张孝祥</作者> <售价>28.00元</售价> </书> </书架>
现在要解析出来: JavaScript网页开发
用SAX解析:
package com.itheima.sax; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; import org.xml.sax.Locator; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.DefaultHandler; public class SaxDemo1 { public static void main(String[] args) throws Exception { //1.获取解析器工厂 SAXParserFactory factory = SAXParserFactory.newInstance(); //2.通过工厂获取sax解析器 SAXParser parser = factory.newSAXParser(); //3.获取读取器 XMLReader reader = parser.getXMLReader(); //4.注册事件处理器 reader.setContentHandler(new MyContentHandler2() ); //5.解析xml reader.parse("book.xml"); } } //适配器设计模式 class MyContentHandler2 extends DefaultHandler{ private String eleName = null; private int count = 0; @Override public void startElement(String uri,String localName,String name,Attributes attributes) throws SAXException { this.eleName = name; } @Override public void characters(char[] ch,int start,int length) throws SAXException { if("书名".equals(eleName) && ++count==2){ System.out.println(new String(ch,start,length)); } } @Override public void endElement(String uri,String name) throws SAXException { eleName = null; } } class MyContentHandler implements ContentHandler{ public void startDocument() throws SAXException { System.out.println("文档解析开始了......."); } public void startElement(String uri,Attributes atts) throws SAXException { System.out.println("发现了开始标签,"+name); } public void characters(char[] ch,int length) throws SAXException { System.out.println(new String(ch,length)); } public void endElement(String uri,String name) throws SAXException { System.out.println("发现结束标签,"+name); } public void endDocument() throws SAXException { System.out.println("文档解析结束了......."); } public void endPrefixMapping(String prefix) throws SAXException { // TODO Auto-generated method stub } public void ignorableWhitespace(char[] ch,int length) throws SAXException { // TODO Auto-generated method stub } public void processingInstruction(String target,String data) throws SAXException { // TODO Auto-generated method stub } public void setDocumentLocator(Locator locator) { // TODO Auto-generated method stub } public void skippedEntity(String name) throws SAXException { // TODO Auto-generated method stub } public void startPrefixMapping(String prefix,String uri) throws SAXException { // TODO Auto-generated method stub } } 这里要了解适配器模式,Sax解析的两大步骤:解析器 事件处理器
下面详解解析器步骤:
//1.获取解析器工厂 SAXParserFactory factory = SAXParserFactory.newInstance(); //2.通过工厂获取sax解析器 SAXParser parser = factory.newSAXParser(); //3.获取读取器 XMLReader reader = parser.getXMLReader(); //4.注册事件处理器 reader.setContentHandler(new MyContentHandler2() ); //5.解析xml reader.parse("book.xml");
理解适配器模式://4.注册事件处理器
我们注册解析处理器的时候用的是:MyContentHandler2而不是MyContentHandler
原因:我们可以看到用MyContentHandler的时候,解析的是整个文档,基于每个标签都会触发事件,这个我们并不需要这样的功能,但是我们要实现特定的标签触发特定的事件,我们就需要一个适配器了,这个适配器MyContentHandler2继承了默认的处理器:extends DefaultHandler
然后我们队需要的处理器中的方法重写即可,为什么用继承,这样在DefaultHandler中已经实现了所有的处理器的方法,知识其它方法在默认处理其中返回的都是null,什么也不做。
对于Dom4J
dom4J是基于dom解析的方式解析的,只是更加的高效。
先了解一下
它的用法:
package com.itheima.dom4j; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; public class Dom4jDemo1 { public static void main(String[] args) throws Exception { //1.获取解析器 SAXReader reader = new SAXReader(); //2.解析xml获取代表整个文档的dom对象 Document dom = reader.read("book.xml"); //3.获取根节点 Element root = dom.getRootElement(); //4.获取书名进行打印 String bookName = root.element("书").element("书名").getText(); System.out.println(bookName); } } 这个例子要了解Sax即系的基本步骤:分为那几步
这三部不管是CRUD都是不可少的
SAXReader reader = new SAXReader(); Document dom = reader.read("book.xml"); Element root = dom.getRootElement();
Dom4J的CRUD操作:
package com.itheima.dom4j; import java.io.FileOutputStream; import java.util.List; import org.dom4j.Attribute; import org.dom4j.Document; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.io.OutputFormat; import org.dom4j.io.SAXReader; import org.dom4j.io.XMLWriter; import org.junit.Test; public class Demo4jDemo2 { @Test public void attr() throws Exception{ SAXReader reader = new SAXReader(); Document dom = reader.read("book.xml"); Element root = dom.getRootElement(); Element bookEle = root.element("书"); //bookEle.addAttribute("出版社","传智出版社"); //String str = bookEle.attributeValue("出版社"); //System.out.println(str); Attribute attr = bookEle.attribute("出版社"); attr.getParent().remove(attr); XMLWriter writer = new XMLWriter(new FileOutputStream("book.xml"),OutputFormat.createPrettyPrint()); writer.write(dom); writer.close(); } @Test public void del() throws Exception{ SAXReader reader = new SAXReader(); Document dom = reader.read("book.xml"); Element root = dom.getRootElement(); Element price2Ele = root.element("书").element("特价"); price2Ele.getParent().remove(price2Ele); XMLWriter writer = new XMLWriter(new FileOutputStream("book.xml"),OutputFormat.createPrettyPrint()); writer.write(dom); writer.close(); } @Test public void update()throws Exception{ SAXReader reader = new SAXReader(); Document dom = reader.read("book.xml"); Element root = dom.getRootElement(); root.element("书").element("特价").setText("4.0元"); XMLWriter writer = new XMLWriter(new FileOutputStream("book.xml"),OutputFormat.createPrettyPrint()); writer.write(dom); writer.close(); } @Test public void add()throws Exception{ SAXReader reader = new SAXReader(); Document dom = reader.read("book.xml"); Element root = dom.getRootElement(); //凭空创建<特价>节点,设置标签体 Element price2Ele = DocumentHelper.createElement("特价"); price2Ele.setText("40.0元"); //获取父标签<书>将特价节点挂载上去 Element bookEle = root.element("书"); bookEle.add(price2Ele); //将内存中的dom树会写到xml文件中,从而使xml中的数据进行更新 // FileWriter writer = new FileWriter("book.xml"); // dom.write(writer); // writer.flush(); // writer.close(); //加了一个OutputFormat.createPrettyPrint()格式转化器,作用是让让新增节点对齐 XMLWriter writer = new XMLWriter(new FileOutputStream("book.xml"),OutputFormat.createPrettyPrint()); writer.write(dom); writer.close(); } @Test public void find() throws Exception{ SAXReader reader = new SAXReader(); Document dom = reader.read("book.xml"); Element root = dom.getRootElement(); List<Element> list = root.elements(); Element book2Ele = list.get(1); System.out.println(book2Ele.element("书名").getText()); } }
关于一些资料的学习:
Dom4J全而好的文章:http://download.csdn.net/detail/itjavawfc/8075049
Dom4J.1.6.1下载:http://download.csdn.net/detail/itjavawfc/8075067
你所应该知道的Dom4J创建解析器: SAXReaderreader=newSAXReader(); 利用解析器读入xml文档: 获取文档的根节点: Elementroot=document.getRootElement(); 接口继承结构: Node --- Branch --Document --Element ---- Attribute Node接口
Branch接口(实现了Node接口)
Element接口(实现了Branch,接口)
Attribute接口(实现了接口)
DocumentHelper类
将节点写出到XML文件中去 方法1: 调用Node提供的write(Writerwriter)方法,使用默认方式将节点输出到流中: node.write(newFileWriter("book.xml")); 乱码问题: Dom4j在将文档载入内存时使用的是文档声明中encoding属性声明的编码集进行编码, 如果在此时使用writer输出时writer使用的内部编码集与encoding不同则会有乱码问题。 FileWriter默认使用操作系统本地码表即gb2312编码,并且无法更改。 此时可以使用OutputStreamWriter(FileOutputStream("filePath"),"utf-8");的方式自己封装 一个指定码表的Writer使用,从而解决乱码问题。 方式2: 利用XMLWriter写出Node: 乱码问题: (1)使用这种方式输出时,XMLWriter首先会将内存中的docuemnt翻译成UTF-8 格式的document,在进行输出,这时有可能出现乱码问题。 可以使用OutputFormat指定XMLWriter转换的编码为其他编码。 OutputFormatformat=OutputFormat.createPrettyPrint(); format.setEncoding("GBK"); (2)Writer使用的编码集与文档载入内存时使用的编码集不同导致乱码,使用字节流 或自己封装指定编码的字符流即可(参照方法1)。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |