dom4j和sax解析XML文档以及简单工厂模式介绍
XML编程(C.R.U.D) |
XML解析技术概述 |
XML解析方式主要分为两种:dom和sax |
dom:document object model(即文档对象模型) |
sax:simple API for xml(见名知意) |
XML解析器:Crimson(SUN)、Xerces(IBM->APACHE) 、Aelfred2(DOM4J开源组织) |
XML解析技术API/开发包(程序员主要关心这个API.....{[(-_-)(-_-)]}zzz) Jaxp(SUN/dom/sax)、Jdom、dom4j |
DOM4J解析XML文档
|
Dom4j是一个简单、灵活的开放源代码的库。Dom4j是由早期开发JDOM的人分离出来而后独立开发的。与JDOM不同的是,dom4j使用接口和抽象基类,虽然Dom4j的API相对要复杂一些,但它提供了比JDOM更好的灵活性。 Dom4j是一个非常优秀的Java XML API,具有性能优异、功能强大和极易使用的特点。现在很多软件采用的Dom4j,例如Hibernate。 使用Dom4j开发,需下载dom4j相应的jar文件。 查看Dom4j文档
|
dom4j解析器 1)CRUD的含义:Create Read Update Delete增删查改 2)XML解析器有二类,分别是DOM和SAX。 a)DOM一次性将整个XML文件读到内存,形成一个倒状的树形结构 b)SAX多次将整个XML文件读到内存 c)Document对象代表XML文件在内存中的映像 |
|
|
使用dom4j解析XML文件 |
//创建dom4j解析器 SAXReader saxReader = new SAXReader(); //加载需要解析的xml文件 Document document = saxReader.read(new File("src/cn/itcast/xml/dom4j/car.xml")); //取得根元素 Element rootElement = document.getRootElement(); //显示根元素的名称 System.out.println(rootElement.getName());//车辆清单 //取得根元素下的子元素 List<Element> elementList = rootElement.elements(); System.out.println("共有" + elementList.size()+"辆车"); for(Element e : elementList){ System.out.println("车牌:" + e.elementText("车牌")); System.out.println("产地:" + e.elementText("产地")); System.out.println("出产时间:" + e.element("车牌").attributeValue("出产时间")); System.out.println("------------------------------"); } |
输出结果: |
车辆清单 共有2辆车 车牌:奥迪 产地:北京 出产时间:2010年 ------------------------------ 车牌:本田 产地:广州 出产时间:2011年 ------------------------------ |
//使用dom4j操作xml文件的cud |
获得document对象 |
private Document getDocument() throws Exception { SAXReader saxReader = new SAXReader(); Document document = saxReader.read(new File("src/cn/itcast/xml/dom4j/car.xml")); return document; } |
//将内存中的xml文件写到硬盘中 |
private void write2xml(Document document) throws Exception { OutputFormat format = OutputFormat.createPrettyPrint(); OutputStream os = new FileOutputStream("src/cn/itcast/xml/dom4j/car.xml"); XMLWriter xmlWriter = new XMLWriter(os,format); xmlWriter.write(document); xmlWriter.close(); } |
@Test public void create() throws Exception{ Document document = getDocument(); Element rootElement = document.getRootElement(); //取得第一辆汽车 Element firstCarElement = (Element) rootElement.elements().get(0); //添加新元素"单价",并设置文本为30 firstCarElement.addElement("单价").setText("40"); //将内存中的xml文件写到硬盘中 write2xml(document); } |
|
|
@Test public void update() throws Exception{ Document document = getDocument(); Element rootElement = document.getRootElement(); Element firstCarElement = (Element) rootElement.elements().get(0); firstCarElement.element("单价").setText("60"); write2xml(document); } |
|
@Test public void delete() throws Exception{ Document document = getDocument(); Element rootElement = document.getRootElement(); Element firstCarElement = (Element) rootElement.elements().get(0); Element firstCarPriceElement = firstCarElement.element("单价"); firstCarElement.remove(firstCarPriceElement); //firstCarPriceElement.getParent().remove(firstCarPriceElement); write2xml(document); } |
|
需求:从src/cn/itcast/xml/dom4j/car.xml解析数据并封装到JavaBean中,并按汽车单价进行排序 |
package cn.itcast.xml.dom4j;
import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader;
public class Demo3 { public static void main(String[] args) throws Exception { SAXReader saxReader = new SAXReader(); Document document = saxReader.read(new File("src/cn/itcast/xml/dom4j/car.xml")); List<Element> elementList = document.getRootElement().elements(); List<Car> carList = new ArrayList<Car>(); for(Element e : elementList){ Car car = new Car(); car.setBand(e.elementText("车牌")); car.setPlace(e.elementText("产地")); car.setTime(e.element("车牌").attributeValue("出产时间")); car.setPrice(Integer.parseInt(e.elementText("单价"))); carList.add(car); } System.out.println("按单价排序前:"); show(carList); System.out.println("按单价排序后:"); sortByPriceDesc(carList); } public static void sortByPriceDesc(List<Car> carList) { Collections.sort(carList); show(carList); } public static void show(List<Car> carList){ if(carList!=null && carList.size()>0){ for(Car car : carList){ System.out.print("车牌:"+car.getBand()+"\t"); System.out.print("产地:"+car.getPlace()+"\t"); System.out.print("单价:"+car.getPrice()+"\t"); System.out.println("出产时间:"+car.getTime()); } } } }javabean中需要让其实现 public class Car implements Comparable<Car> Comparable这个接口,并重写其compareTo方法, 调用此集合排序方法Collections.sort(carList); |
public int compareTo(Car car) { if(this.price<car.getPrice()){ return 1; }else if(this.price>car.getPrice()){ return -1; }else{ return 0; } } |
//使用dom4j其它的API |
/*String->XML*/ String text = "<root><res>这是根元素</res></root>"; //主动创建document对象 Document document = DocumentHelper.parseText(text); //使用缩格形式写XML文件 OutputFormat format = OutputFormat.createPrettyPrint(); OutputStream os = new FileOutputStream("src/cn/itcast/xml/dom4j/string2xml_copy.xml"); XMLWriter xmlWriter = new XMLWriter(os,format); xmlWriter.write(document); xmlWriter.close(); |
|
//创建空XML文件 Document document = DocumentHelper.createDocument(); document.addElement("root").setText("这是根元素"); OutputFormat format = OutputFormat.createPrettyPrint(); OutputStream os = new FileOutputStream("src/cn/itcast/xml/dom4j/empty.xml"); XMLWriter xmlWriter = new XMLWriter(os,format); xmlWriter.write(document); xmlWriter.close(); |
|
/*指定插入次序,默认插入到最后*/ SAXReader saxReader = new SAXReader(); Document document = saxReader.read(new File("src/cn/itcast/xml/dom4j/car.xml")); List<Element> elementList = document.getRootElement().elements(); Element newCarElement = DocumentHelper.createElement("汽车"); newCarElement.setText("这是我的汽车"); elementList.add(1,newCarElement); OutputFormat format = OutputFormat.createPrettyPrint(); OutputStream os = new FileOutputStream("src/cn/itcast/xml/dom4j/car.xml"); XMLWriter xmlWriter = new XMLWriter(os,format); xmlWriter.write(document); xmlWriter.close(); |
//XML->String SAXReader saxReader = new SAXReader(); Document document = saxReader.read(new File("src/cn/itcast/xml/dom4j/car.xml")); Element rootElement = document.getRootElement(); Element firstCarElement = (Element) rootElement.elements().get(0); String xml = firstCarElement.asXML(); System.out.println(xml); |
常用的API如下: SAXReader saxReader = new SAXReader(); SAXReader是dom4j的核心类 Document document = saxReader.read("*.xml") Document.getRootElement() Element.getName() Element.elements():取得该元素下的所有直接子元素 Element.elementText():从一个元素导航到另一个元素且取出该元素的文本 Element.element("车牌") :从一个元素导航到另一个元素 Element.attributeValue("出产时间"):取得一个元素对应的属性 Element.addElement("单价").setText("40"):添加新元素,同时设置该元素文本的值 OutputFormat format = OutputFormat.createPrettyPrint():使用缩格形式写XML文件 XMLWriter xmlWriter = new XMLWriter(os,format):构造XML写入器 xmlWriter.write(document):将内存中的document对象写入硬盘 firstCarElement.remove(firstCarPriceElement):从直接父元素删除直接子元素 //firstCarPriceElement.getParent().remove(firstCarPriceElement):从直接父元素删除直接子元素 |
//使用xpath技术取得xml文件中任意级别下的内容 |
package cn.itcast.xml.xpath; import java.io.File; import java.util.List; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; //使用xpath技术取得xml文件中任意级别下的内容 public class Demo1 { public static void main(String[] args) throws Exception { SAXReader reader = new SAXReader(); Document document = reader.read(new File("src/cn/itcast/xml/xpath/car.xml")); String xpath = "//单价"; Element element = (Element) document.selectSingleNode(xpath); System.out.println("第一辆汽车的单价是:" + element.getText()); List<Element> elementList = document.selectNodes(xpath); System.out.println("第二辆汽车的单价是:" + elementList.get(1).getText()); } } |
package cn.itcast.xml.xpath;
import java.io.File; import java.util.Scanner; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader;
//使用Xpath,模拟用户登录 public class Demo2 { public static void main(String[] args) throws Exception { //读取用户在键盘的输入信息 Scanner scanner = new Scanner(System.in); System.out.print("用户名:"); String username = scanner.nextLine(); System.out.print("密码:"); String password = scanner.nextLine(); //解析XML文件,并查询指定的元素 SAXReader saxReader = new SAXReader(); Document document = saxReader.read(new File("src/cn/itcast/xml/xpath/users.xml")); String xpath = "//user[@username='"+username+"' and @password='"+password+"']"; Element element = (Element) document.selectSingleNode(xpath); //输出结果 if(element!=null){ System.out.println("登录成功"); }else{ System.out.println("登录失败"); } } } |
user.xml |
<?xml version="1.0" encoding="UTF-8"?> <root> <user id="u01" username="jack" password="123456"/> <user id="u02" username="marry" password="654321"/> </root> |
基于dom4j的xpath技术 1)能够在xml文件中,快速定位需要元素,无需从根元素一个一个的导航到需要的子元素 Document.selectNodes():取得所有符合xpath格式的元素 Document.selectSingleNode():取得所有符合xpath格式的元素的第一个元素 Node类型是Element/Text/Attribute/Document/...类型的父接口 |
//使用sax解析器解析xml文件 |
JAXP(了解) JAXP 开发包是JavaSE的一部分,它由javax.xml、org.w3c.dom 、org.xml.sax 包及其子包组成。 在 javax.xml.parsers 包中,定义了几个工厂类,程序员调用这些工厂类,可以得到对xml文档进行解析的 DOM 或 SAX 的解析器对象 |
SAX解析允许在读取文档的时候,即对文档进行处理,而不必等到整个文档装载完才会文档进行操作。
|
SAX采用事件处理的方式解析XML文件,利用 SAX 解析 XML 文档,涉及两个部分:解析器和事件处理器: 解析器可以使用JAXP的API创建,创建出SAX解析器后,就可以指定解析器去解析某个XML文档。 解析器采用SAX方式在解析某个XML文档时,它只要解析到XML文档的一个组成部分,都会去调用事件处理器的一个方法,解析器在调用事件处理器的方法时,会把当前解析到的xml文件内容作为方法的参数传递给事件处理器。 事件处理器由程序员编写,程序员通过事件处理器中方法的参数,就可以很轻松地得到sax解析器解析到的数据,从而可以决定如何对数据进行处理。
|
<?xml version="1.0" encoding="UTF-8"?> <车辆清单> <汽车> <车牌 出产时间="2011年">奥迪</车牌> <产地>北京</产地> <单价>30</单价> </汽车> </车辆清单> |
package cn.itcast.xml.sax;
import java.io.File; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.Attributes; import org.xml.sax.helpers.DefaultHandler;
//使用sax解析器解析xml文件 public class Demo1 { public static void main(String[] args) throws Exception { //创建SAX解析器工厂 SAXParserFactory factory = SAXParserFactory.newInstance(); //创建SAX解析器 SAXParser saxParser = factory.newSAXParser(); //加载xml文件 saxParser.parse( new File("src/cn/itcast/xml/sax/car.xml"), new MyHandler()); } } //自定义SAX处理器 class MyHandler extends DefaultHandler{ private long begin; public void startDocument(){ System.out.println("解析XML文件开始"); begin = System.currentTimeMillis(); } public void endDocument() { System.out.println("解析XML文件结束"); long end = System.currentTimeMillis(); System.out.println("解析XML共用" + (end-begin) + "毫秒"); } public void startElement( String uri, String localName, String qName, Attributes attributes){ System.out.println("<"+qName+">"); System.out.println("有"+attributes.getLength()+"个属性"); System.out.println(attributes.getValue("出产时间")); } public void endElement( String uri, String localName, String qName){ System.out.println("</"+qName+">"); } public void characters( char[] ch, int start, int length){ String content = new String(ch,start,length); if(content.trim().length()>0){ System.out.println(content); } } } |
SAX解析器 1)sun公司提供的一个基于事件的xml解析器 2)SAXParser是SAX解析器的核心类,在使用过程中,需要一个SAX处理器,该处理器必须扩展DefaultHandler 3)SAX解析器在解析XML文件时,会根据XML文件此时的状态,即开始标签,结束标签,调用SAX处理器对应的方法 4)SAX解析器在解析XML文件时,自动导航,无需像dom4j一样,人为导航 5)SAX解析器会将空白字符当作一个有效字符对待
|
简单工厂设计模式 |
定义:简单工厂模式属于创建型模式有叫做静态工厂方法模式,是一个工厂对象决定创建出哪一种产品类的实例。 |
简单工厂模式结构图 |
|
Factory:工厂类,简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类的创建产品类方法可以被外界直接调用,创建所需的产品对象。 |
IProduct:抽象产品类,简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。 |
Product:具体产品类,是简单工厂模式的创建目标。 |
简单工厂模式简单实现 |
以生产电脑为例: |
创建抽象产品类: |
public abstract class Computer { /** * 产品的抽象方法,由具体的产品类去实现 */ public abstract void start(); } |
穿件具体产品类 |
public class LenovoComputer extends Computer{ @Override public void start() { System.out.println("联想电脑启动"); } |
public class HpComputer extends Computer{ @Override public void start() { System.out.println("惠普电脑启动"); } } |
public class AsusComputer extends Computer { @Override public void start() { System.out.println("华硕电脑启动"); } } |
创建工厂类: |
提供一个静态方法createComputer方法用来生产电脑,你只需要传入你想生产的电脑品牌,此方法就返回实例化相应品牌的电脑对象。 |
public class ComputerFactory { public static Computer createComputer(String type){ Computer mComputer=null; switch (type) { case "lenovo": mComputer=new LenovoComputer(); break; case "hp": mComputer=new HpComputer(); break; case "asus": mComputer=new AsusComputer(); break; } return mComputer; } } |