JAXP DOM 解析
JAXP SAX 解析
XML PULL 进行STAX 解析
XML 技术主要企业应用
1、存储和传输数据
2、作为框架的配置文件
使用xml存储和传输数据
1、通过程序生成xml
2、读取xml中数据---- xml 解析
什么是DOM和SAX?
DOM Document ObjectModel ----- 文档对象模型
DOM思想:将整个xml 加载内存中,形成文档对象,所有对xml操作都对内存中文档对象进行
DOM 是官方xml解析标准
* 所有开发语言都支持的
Java、JavaScript都支持DOM
SAX Simple API for XML----- XML 简单API
程序员为什么发明sax解析方式??当xml 文档非常大,不可能将xml所有数据加载到内存
SAX 思想:一边解析,一边处理,一边释放内存资源---- 不允许在内存中保留大规模xml数据
StAX The Stream API forXML ----- XML 流API
STAX 是一种拉模式 xml解析方式,SAX是一种推模式 XML解析方式
推push模式:由服务器为主导,向客户端主动发送数据
拉pull模式:由客户端为主导,主动向服务器申请数据
程序员在实际开发中,使用已经开发好工具包----- JAXP 、DOM4j、XMLPULL
解析方式与 解析开发包关系?
解析方式是解析xml思想,没有具体代码,解析开发包是解析xml思想具体代码实现
JAXP 是sun官方推出实现技术同时支持 DOMSAX STAX
DOM4j 是开源社区开源框架 支持 DOM解析方式
XML PULL Android移动设备内置xml解析技术支持 STAX解析方式
当SAX和STAX读取xml数据时,如果读取到内存数据不释放----- 内存中将存在整个xml文档数据(类似DOM 支持修改和回写)
DOM、SAX、STAX在实际开发中选择?
在javaee日常开发中---- 优先使用DOM(编程简单)
当xml文档数据非常多,不可能使用DOM---造成内存溢出 ------ 优先使用STAX
移动开发使用 STAX---- Android XML PULL
JAXP 开发进行 xml解析:
javax.xml.parsers 存放DOM 和SAX 解析器
javax.xml.stream 存放STAX 解析相关类
org.w3c.dom 存放DOM解析时数据节点类
org.xml.sax存放SAX解析相关工具类
DOM 解析快速入门
1、创建xml 文档books.xml
在企业实际开发中,为了简化xml生成和解析---- xml 数据文件通常不使用约束的
2、使用DOM解析xml
将整个xml文档加载到内存中: 工厂--- 解析器--- 解析加载
3、Document通过getElementsByTagName 获得节点集合 NodeList
通过NodeList 提供getLength 和item 遍历节点集合
遍历ArrayList
for (inti=0;i<arraylist.size();i++){
arraylist.get(i);
}
遍历NodeList
for (inti=0;i<nodelist.getLength();i++){
nodelist.item(i); ----- 将遍历每个节点转换子接口类型
}
什么是Node? 对于xml来说,xml所有数据都是node节点(元素节点、属性节点、文本节点、注释节点、CDATA节点、文档节点)
Element Attr TextComment CDATASection Document ----- 都是Node 子接口
node有三个通用API:
getNodeName():返回节点的名称
getNodeType():返回节点的类型
getNodeValue():返回节点的值 ---- 所有元素节点value都是null
----------------------------------------------------------------------------------------
DOM 编程思路小结
1、装载XML文档---- Document
2、Document获得指定元素----- getElementsByTagName (返回NodeList)
3、遍历NodeList获得每个 Node
4、将每个Node强制转换Element
5、通过元素节点API操作属性和文本内容
getAttribute 获得属性值
getTextContent获得元素内部文本内容
先用全局查找锁定范围,再用相对关系查找得到需要数据
getElementById 方法必须用于带有约束xml文档中!!!!!!!
所以开发语言默认支持DTD,当使用Schema时,单独编程导入schema!
XML DOM 增加、修改 和删除操作 ------操作内存中文档对象
XML的回写
XML元素添加: 1、创建节点元素2、将节点元素加入指定位置
XML元素修改: 查询到指定元素1、修改属性setAttribute 2、修改元素文本内容setTextContent
XML元素删除:删除节点.getParentNode().removeChild(删除节点)
-------------------------------------------------------------------------------------------------
SAX 和STAX 都是基于事件驱动 -----SAX推模式STAX拉模式
SAX常用事件
startDocument() ----文档开始事件
startElemen() ----元素开始事件
characters() ----文本元素事件
endElement() ----元素结束事件
endDocument() -----文档结束事件
为什么说SAX是推模式解析?解析器控制xml文件解析,由解析器调用相应事件方法
在startElemen()endElement() 获得开始和结束元素名称
在characters()获得读取到文本内容
在startElemen()读取属性值
STAX 拉模式xml解析方式----- 客户端程序,自己控制xml事件,主动调用相应事件方法
当使用XMLPULL 如果使用Android系统,系统内置无需下载任何开发包,如果想JavaSEJavaEE 使用pull解析技术下载单独pull 开发工具包
xpp3 ----- XML PullParser 3 是pullAPI 代码实现
使用pull解析器
1、去网站上下载 pull解析器实现xpp3 (Android 内置)
2、将xpp3-1.1.3.4.C.jar 导入java工程
导入jar包位于 当前工程内部, 在工程内新建lib ,将jar复制过来, 将pull解析器jar 添加buildpath
jar 包就是.class文件集合压缩包(采用zip格式压缩)
Pull解析器使用 stax解析方式---- 拉模式解析
Pull采用将xml文档传递解析器,手动通过next触发文档解析事件,在客户端代码中获取当前事件,从而调用相应事件处理方法
3、创建pull解析器
4、将xml文档内容传递pull 解析器
为什么STAX 解析方式效率 好于SAX ?
1、SAX无选择性的,所有事件都会处理解析方式,Stax 由用户控制需要处理事件类型
2、在使用Stax进行数据解析时,随时终止解析
Pull 解析器生成 xml文档功能---- 通过XmlSerializer 生成xml 文档
解析xml:文档开始、元素开始、文本元素、元素结束、文档结束
生成xml:生成文档声明(文档开始),元素开始、文本内容、元素结束、文档结束
1、生成简单xml
2、通过对象数据生成xml
3、通过对象List数据生成xml
在程序中抽取两个方法----- 1. xml --- List对象 2. List对象生成xml
对内存中List进行CURD操作
作业:
1、整理DOM 、SAX、STAX原理和区别
2、编写商品xml文件--- 通过JAXPDOM 完成CURD操作
3、编写SAX运行案例----- 了解
4、编写商品XML文件--- 通过Pull解析器完成CURD操作 ---- 重点xml2List list2xml 两个方法
//需要解析的xml文件
<?xmlversion="1.0" encoding="UTF-8"?>
<!DOCTYPEbooks [
<!ELEMENTbooks (book+) >
<!ELEMENTbook (name,price) >
<!ELEMENTname (#PCDATA) >
<!ELEMENTprice (#PCDATA) >
<!ATTLISTbook
id ID #REQUIRED
>
]>
<books>
<bookid="b001">
<name>java编程基础</name>
<price>80</price>
</book>
<bookid="b002">
<name>java高级应用</name>
<price>100</price>
</book>
<bookid="boo3">
<name>编程高手秘笈</name>
<price>200</price>
</book>
</books>
//Pull 解析代码
import org.junit.Test;
importorg.xmlpull.v1.XmlPullParser;
importorg.xmlpull.v1.XmlPullParserFactory;
public class PullTest {
@Test
// 通过pull 解析技术查看 "编程高手秘笈"价格
public void demo2()throws Exception {
// 1. 创建pull 解析器
XmlPullParserFactoryfactory = XmlPullParserFactory.newInstance();
XmlPullParser parser= factory.newPullParser();
// 2. 将xml文档传递解析器
parser.setInput(newFileInputStream("books.xml"), "utf-8");
// 通过循环驱动事件解析
int event;
// 查找name标识位
boolean isFound =false;
while ((event =parser.getEventType()) != XmlPullParser.END_DOCUMENT) {
// 获得开始元素 name
if (event ==XmlPullParser.START_TAG
&&parser.getName().equals("name")) {
// 获得元素后面文本
String bookname =parser.nextText();
if(bookname.equals("编程高手秘笈")){
isFound = true;
// 这本书就是我找到
// parser.next();
//System.out.println(parser.getEventType());
// parser.next();// price 开始
//System.out.println(parser.getEventType());
// String money =parser.nextText();
//System.out.println(money);
}
}
if (event ==XmlPullParser.START_TAG
&&parser.getName().equals("price") && isFound) {
System.out.println(parser.nextText());
break;
}
parser.next();
}
}
@Test
public void demo1()throws Exception {
// 1、创建xml pull 解析器
// 工厂
XmlPullParserFactoryxmlPullParserFactory = XmlPullParserFactory
.newInstance();
// 通过工厂获得解析器
XmlPullParser parser= xmlPullParserFactory.newPullParser();
// 2、将xml 文件传递 解析器
parser.setInput(newFileInputStream("books.xml"), "utf-8");
// pull 解析器用得是拉模式 数据解析
int event;
while ((event =parser.getEventType()) != XmlPullParser.END_DOCUMENT) {
// 打印哪个元素开始了---- 判断当前事件是 元素开始事件
if (event ==XmlPullParser.START_TAG) {
// 所有数据从解析器 获得
System.out.println(parser.getName()+ "元素开始了...");
}
// 打印哪个 元素结束了
if (event ==XmlPullParser.END_TAG) {
System.out.println(parser.getName()+ "元素结束了...");
}
// 处理下一个事件
parser.next();
}
// // 获得当前事件类型
// int event =parser.getEventType();
//
//System.out.println(event);
//
// parser.next(); //解析器解析下一个事件
//
// int event2 =parser.getEventType();
//
//System.out.println(event2);
//
// parser.next();
//
// int event3 =parser.getEventType();
//
//System.out.println(event3);
}
}
//生成pull笔记
import org.junit.Test;
importorg.xmlpull.v1.XmlPullParserFactory;
importorg.xmlpull.v1.XmlSerializer;
/**
* 生成xml
*
*/
public classSerializerTest {
@Test
// 根据List<Company> 生成xml
public void demo3()throws Exception {
List<Company>companies = new ArrayList<Company>();
Company company = newCompany();
company.setName("Google");
company.setPnum(200);
company.setAddress("软件园!");
Company company2 =new Company();
company2.setName("CSDN");
company2.setPnum(1000);
company2.setAddress("软件园 ");
companies.add(company);
companies.add(company2);
// 序列化对象
XmlSerializerserializer = XmlPullParserFactory.newInstance()
.newSerializer();
// 设置输出文件
serializer.setOutput(newFileOutputStream("company.xml"), "utf-8");
serializer.startDocument("utf-8",true);
serializer.startTag(null,"companies");
// 遍历list集合
for (Company c :companies) {
serializer.startTag(null,"company");
serializer.startTag(null,"name");
serializer.text(c.getName());
serializer.endTag(null,"name");
serializer.startTag(null,"pnum");
serializer.text(c.getPnum()+ "");
serializer.endTag(null,"pnum");
serializer.startTag(null,"address");
serializer.text(c.getAddress());
serializer.endTag(null,"address");
serializer.endTag(null,"company");
}
serializer.endTag(null,"companies");
serializer.endDocument();
}
@Test
// 根据company对象数据生成xml
public void demo2()throws Exception {
Company company = newCompany();
company.setName("我的百度");
company.setPnum(200);
company.setAddress("西二旗软件园!");
/*
* <company>
*
* <name>我的百度</name>
*
* <pnum>200</pnum>
*
*<address>西二旗软件园</address>
*
* </company>
*/
// 获得序列化对象
XmlSerializerserializer = XmlPullParserFactory.newInstance()
.newSerializer();
// 传递输出目标文件 给序列化对象
serializer.setOutput(newFileOutputStream("company.xml"), "utf-8");
serializer.startDocument("utf-8",true);
serializer.startTag(null,"company");
serializer.startTag(null,"name");
serializer.text(company.getName());
serializer.endTag(null,"name");
serializer.startTag(null,"pnum");
serializer.text(company.getPnum()+ "");
serializer.endTag(null,"pnum");
serializer.startTag(null,"address");
serializer.text(company.getAddress());
serializer.endTag(null,"address");
serializer.endTag(null,"company");
serializer.endDocument();
}
@Test
public void demo1()throws Exception {
// 获得XmlSerializer对象
XmlPullParserFactoryfactory = XmlPullParserFactory.newInstance();
XmlSerializerserializer = factory.newSerializer();
// 设置序列化输出文档
serializer.setOutput(newFileOutputStream("company.xml"), "utf-8");
// 文档开始
serializer.startDocument("utf-8",true);
// 元素开始
serializer.startTag(null,"company"); // 没有命名空间,"" 或者null
// 文本元素
serializer.text("我的百度");
// 元素结束
serializer.endTag(null,"company");
// 文档结束
serializer.endDocument();
/*
* <?xmlversion="1.0" encoding="UTF-8" standalone="yes"?>
*
* <company>
*
* 我的百度
*
* </company>
*/
}
}
创建的xml文件
<?xml version="1.0"encoding="utf-8" standalone="yes"?>
<companies>
<company>
<name>我的百度</name>
<pnum>200</pnum>
<address>西二旗软件园!</address>
</company>
<company>
<name>CSDN</name>
<pnum>1000</pnum>
<address>软件园 </address>
</company>
</companies>
//增删改查xml内容
import org.junit.Test;
importorg.xmlpull.v1.XmlPullParser;
importorg.xmlpull.v1.XmlPullParserFactory;
importcn.itcast.domain.Company;
/**
* 完成pull解析器CURD操作
*
*/
public class PullCURD {
@Test
// 将xml中数据---- List集合对象
public void demo1()throws Exception {
List<Company>companies = new ArrayList<Company>();
Company company =null;
// 获得解析器
XmlPullParserFactoryfactory = XmlPullParserFactory.newInstance();
XmlPullParser parser= factory.newPullParser();
// 向解析器传入xml文件
parser.setInput(newFileInputStream("company.xml"), "utf-8");
// 遍历解析
int event;
while ((event =parser.getEventType()) != XmlPullParser.END_DOCUMENT) {
if (event ==XmlPullParser.START_TAG
&&parser.getName().equals("company")) {
// company 开始创建 company对象
company = newCompany();
}
if (event ==XmlPullParser.START_TAG
&&parser.getName().equals("name")) {
// name 元素开始-- 封装name属性
company.setName(parser.nextText());
}
if (event ==XmlPullParser.START_TAG
&&parser.getName().equals("pnum")) {
company.setPnum(Integer.parseInt(parser.nextText()));
}
if (event ==XmlPullParser.START_TAG
&&parser.getName().equals("address")) {
company.setAddress(parser.nextText());
}
if (event ==XmlPullParser.END_TAG
&&parser.getName().equals("company")) {
// company 结束
companies.add(company);
}
parser.next();
}
for (Company c :companies) {
System.out.println(c.getName());
System.out.println(c.getPnum());
System.out.println(c.getAddress());
System.out.println("----------------------");
}
}
}