JAVA学习之路(三)。。。

    这是开始学Java的第三天,今天看了Java的关于XML的解析,总共看了有三种,一是DOM,二是SAX,还有三是STAX,对XML的解析有了更进一步的了解。在DOM中,是将整个XML文档加载到内存中,形成一个文档对象,所有的对XML操作都是对内存中文档对象进行,如果过大的XML文档用DOM的话,会让内存空间变小,但是只是一般的小项目,XML文档不算大的话,用DOM解析会好一点。其次是SAX解析,这是一种一边解析,一边处理,一边释放内存资源,不会再内存中保留大规模内存数据,这是一种推(push)模式:有服务器为主导,向客户端主动发送数据。最后一个是STAX,这个实际上和SAX差不多,只是具体的实现的方式有所不同,STAX是一种拉(pull)模式:由客户端为主导,主动向服务器申请数据。感觉今天收获挺多,一下是今天整个总结的内容:

 使用XML  存储和传输数据
1.通过程序生成xml
2.读取xml中数据 --- xml解析
XML解析方式分为两种:dom和sax
dom:(Document Object Model,即文档对象模型)是W3C组织推荐的解析XML的一种方式。
DOM思想:将整个xml文档加载到内存中,形成文档对象,所有对xml操作都对内存中文档对象进行。
DOM是官方xml解析程序
*所有语言都支持
sax:(Simple API for XML)不是官方推荐,它产生自XML社区,几乎所有的XML解析器都支持它。
发明sax的原因:当xml文档非常大,不可能将xml所有数据加载到内存
sax思想:一边解析,一边处理,一边释放内存资源 ---- 不允许在内存中保留大规模xml数据
JDK6的新特性StAX是JDK6.0中除了DOM和SAX之外的又一种拉模式处理XML文档的API
XML解析开发包
Jaxp(sun)、xml pull、dom4j
stAX The Stream API for XML ------  XML流API
stAX 是一种拉模式 xml解析模式,sax是推模式xml解析方式
推push模式:由服务器为主导,向客户端主动发送数据
拉pull模式:由客户端为主导,主动向服务器申请数据

程序员在实际开发中,使用已经开发好的工具包-----JAXP、DOM4j、XML PULL
解析方式使解析xml思想,没有具体代码,解析开发包是解析xml思想具体代码实现    
JAXP是sun官方推出的实现技术 同时支持DOM SAX STAX
DOM4j 是开源社区开源框架 支持DOM解析方式
XML PULL Android移动设备内置xml

DOM和SAX/STAX区别
DOM支持回写
会将整个XML载入内存,以树形结构方式存储
XML比较复杂的时候,或者当你需要随机处理文档中数据的时候不建议使用
SAX/STAX
相比DOM是一种更为轻量级的方案
采用串行方法读取---文件输入流(字节、字符)读取
编程较为复杂
无法再读取过程中修改XML数据 解析技术 STAX解析方式

当SAX和STAX读取xml数据时,如果读取到内存数据不释放 ----- 内存中将存在整个xml文档数据(类似DOM支持修改和回写)
选择DOM还是SAX/STAX,这取决于几个因素
应用程序的目的:如果必须对数据进行更改,并且作为XML将他输出,则在多数情况下,使用DOM
数据的数量:对于大文件,SAX/STAX是更好的选择
将如何使用数据:如果实际上只使用一小部分数据,则使用SAX/STAX将数据抽取到应用程序中,这种方法更好
需要速度:通常,SAX/STAX实现比DOM更快
在JAVAee日常开发中----优先使用DOM(变成简单)
在XML文档数据非常多,不可能使用DOM --- 造成内存溢出 ---- 优先使用STAX
移动开发 使用STAX ---- Android XML PULL

JAXP开发 进行xml解析:
javax.xml.parsers 存放DOM和SAX解析器
javax.xml.stream 存放STAX解析相关类
orgw3c.dom 存放DOM解析时 数据结点类
org.xml.sax 存放SAX解析相关工具类

DOM是以层次结构组织的结点或信息片段的集合,是XML数据的一种树形表示
文档中所有的元素、树形、文本都会被解析成node结点
结点之间关系----parent、children、sibling
使用DOM方式解析XML
解析器工厂类DocumentBuilderFactory
DocumentBuilderFactory dbf= DocumentBuilderFactory.newInstance();
解析器类DocumentBuilder
DocumentBuilder db = dbf.newDocumentBuilder();
解析生成Document对象
Document doc = db.parse("message.xml");
 通过Document对象查询结点
document.getElementsByTagName返回NodeList对象
节点列表内NodeList就是代表了一个包含一个或多个Node的列表
可以简单的把他看成一个Node数组
常用方法
getLength():返回列表长度
类似ArrayList size()
item(index):返回指定位置的Node对象
类似ArrayList get(index)
节点对象Node
Node对象提供了一系列常量来代表节点的类型
当开发人员获得某个Node类型后,就可以把Node节点转换成相应的结点对象
Element、Attr、Text
节点的操作:三个node的通用API
getNodeName():返回节点的名称
getNodeType():返回节点的类型
getNodeValue():返回节点的值----所有元素节点的value都是null
节点对象 Element Attr Text
元素节点:
获得元素节点中的属性值
element.getAttribute(属性名称);
获得元素节点内部文本内容
element.getTextContent();
element.getFirstChild().getNodeValue();  
更新javax.xml.transform包中的Transformer类用于把代表XML文件的Document对象转换成XML格式进行输出
Transformer对象通过TransformerFactory获得
Transformer类通过transfoem方法完成转换操作,该方法接收一个源和一个目的地。
我们可以通过:
javax.xml.transform.dom.DOMSource类来关联要转换的document对象
用javax.xml.transform.stream.StreamResult对象来表示数据的目的地
节点对象的增加、修改、删除总结
*节点对象的增加
document.createXXX()创建节点
element.appendChild(org.w3c.dom.Node)添加节点
*节点对象的修改
修改元素的属性值element.setAttribute(name,value);
修改元素的文本内容element.setTextContent(value);
节点对象的删除
删除节点.getParentNode().removeChild()删除节点

DOM解析快速入门
1.创建XML文档 books.xml
在企业实际开发中,为了简化xml生成和解析 ---- xml数据文件通常不使用约束
2.使用DOM解析xml
将整个xml文档加载到内存中
 工厂----解析器----解析加载
3.Document通过getElementsByName 获得节点集合 NodeList
通过NodeList提供getLength和item遍历节点集合
节点对象的查询总结
全局查找元素节点
document.getElementsByTagName
document.getElementById
相对节点位置查找节点
getChildNodes():返回这个节点的所有子节点列表
getFirstChild():返回这个节点的第一个子节点
getParentNode():返回这个节点的父节点对象
getNextSibling():返回该节点下一个兄弟节点
getPreviousSibling():返回其前一个兄弟节点
遍历ArrayList
for(int i=0;i<arrayList.size();i++){
    arrayList.get(i);
}
遍历NodeList
for(int i=0;i<nodeList.getLength();i++){
    nodeList.item(i);//----------将遍历每个结点转换成子接口类型
}
什么是Node?---对于xml来说,xml所有数据都是node节点(元素节点、属性节点、文本节点、注释节点、CDATA节点、文档节点)
Element(元素)、Attr(属性)、Text(文本)、Comment(注释)、CDATASection、Document(文档)----都是Node的子接口  
DOM编程思路小结
1.装载XML文档--------Document
2.Document获得置顶元素 ---------getElementsByName(返回NodeList)
3.遍历NodeList获得每个Node
4.将每个Node强制转换成Element
5.通过元素节点API操作属性和文本内容
getAttrbute 获得属性值
getTextCotent 获得元素内部文本内容

强化查询
1.获得Document文档树对象
2.全局查找
document.getElementsByTagName----根据元素名称进行全局查找 NodeList
document.getElementById----默认情况下该方法不能直接用,必须要有约束,才能使用该方法
3.相对位置查找
*在企业使用XML作为配置文件时,一般xml都有约束,但是使用XML存储和传输文件时,需要用程序生成XML,大多数情况不使用约束
*XML的DTD约束默认支持的,如果使用的是Schema约束,单独编程导入约束文件schema

XML DOM增加 修改和删除操作------操作内存中文档对象
XML的回写
XML元素添加:1.创建节点元素 2.将节点元素加入指定位置
XML元素修改:查询指定元素 1.修改属性setAttribute 2.修改元素的文本内容 setTextContent
SAX解析原理
SAX是事件驱动的XML处理方法
它是基于事件驱动的
startElement()回调在每次SAX解析器遇到元素的起始标记时被调用
characters()回调为字符数据所调用
endElement()为元素的结束标记所调用
DefaultHandler(在org.xml.sax.helpers软件包中)来实现所有这些回调,并提供所有回调方法默认的空实现

SAX解析原理
SAX是事件驱动的XML处理方法
它是基于事件驱动的
startElement()回调在每次SAX解析器遇到元素的起始标记时被调用
characters()回调为字符数据所调用
endElement()为元素的结束标记所调用
DefaultHandler(在org.xml.sax.helpers软件包中)来实现所有这些回调,并提供所有回调方法默认的空实现
SAX和STAX都是基于事件驱动----SAX推模式 STAX拉模式
SAX常用事件
startDocument() ---- 文档开始事件
startElement() ---- 元素开始事件
characters() ---- 文本元素事件
endElement() ---- 元素结束事件
endDocument() ---- 文档结束事件
使用SAX方式解析XML
使用SAXParserFactory创建SAX解析工厂
SAXParserFactory spf = SAXParserFactory.newInstance();
通过SAX解析工厂得到解析器对象
SAXParser sp = spf.newSAXParser();
通过解析器对象解析xml文件
xmlReader.parse("book.xml",new XMLConteneHandler());
这里的XMLContentHandler继承DefaultHandler
为什么叫推模式-----由解析内部主导 事件方法调用
在startElement() endElement()获得开始和结束元素名称
在characters()获得读取到文本内容
在startElement()读取属性值


使用XML PULL解析XML
PULL是STAX的一个实现技术
STAX是The Streaming API for XML的缩写,一种利用拉模式解析(pull-parsing)XML文档的API。
STAX通过提供一种基于事件迭代器(Iterator)的API让程序员取控制xml文档解析过程
Android系统内置的Pull解析器也可以进行XML文件的解析
Pull解析器是一个开源的Java项目,既可以用于Android,也可以用于JavaEE
官方站点:http://www.xmlpull.org/
下载实现xpp3
Pull解析器运行方式与SAX解析器类似
基于事件驱动
关键代码
创建解析器工厂
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();//根据工厂创建解析器
xpp.setInput(inStream,"UTF-8");//读取xml文件
int eventType = xpp.getEventType(); ---- 当前节点事件类型
eventType = xpp.next(); ---- 下一个节点事件
xpp.getAttributeValue ---- 获得标签属性值
xpp.nextText ---- 获得标签属性值

STAX拉模式xml解析方式 ---- 客户端程序,自己控制xml事件,主动调用相应事件方法
当使用XML PULL如果使用Android系统,系统内置无需下载任何开发包,如果想JavaSE JavaEE 使用pull解析技术 下载单独pull开发工具包
xpp3-----XML Pull Parser 3 是pull API代码实现
使用pull解析器
1.网上下载pull解析器实现xpp3(Android内置)
2.将xpp3-1.1.3.4.C.jar导入java工程
导入jar包 位于当前工程内部,在工程内新建lib,将jar赋值过来,将pull解析器jar添加build path
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:生成文档声明(文档开始)、元素开始、文本内容、元素结束、文档结束

一下代码实例:

将XML文档存入List集合示例:
package cn.huangnan.stax.jaxp;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException ;
import org.xmlpull.v1.XmlPullParserFactory;
public class PullCURD {
     @Test
      public void demo1 () throws Exception {
           List<Company> companies = new ArrayList<Company>();
           Company company = null ;
           //創建pull解析器
           XmlPullParserFactory factory =XmlPullParserFactory. newInstance ();
           XmlPullParser parser = factory .newPullParser();
            parser .setInput( new FileInputStream( "company.xml" ), "utf-8" );//对XML文档进行解析,解析为parser
           
            int event ;//设置 pull的事件
          while((event=parser.getEventType())!=XmlPullParser.END_DOCUMENT) {
                 if ( event ==XmlPullParser. START_TAG && parser .getName().equals( "company" )) {
                      company = new Company();
                }
                 if ( event ==XmlPullParser. END_TAG && parser .getName().equals( "company" )) {
                     companies.add(company);
                }
                 if ( event ==XmlPullParser. START_TAG && parser .getName().equals( "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());
                }
                parser.next();
           }
            for (Company com : companies ) {
                System.out.println(com.getName());
                System.out.println(com.getPnum());
                System.out.println(com.getAddress());
                System.out.println("------------------");
           }
     }
}
class Company {
      private String name ;
      private int pnum ;
      private String address ;
      public String getName() {
            return name ;
     }
      public void setName(String name ) {
            this . name = name ;
     }
      public int getPnum() {
            return pnum ;
     }
      public void setPnum( int pnum ) {
            this . pnum = pnum ;
     }
      public String getAddress() {
            return address ;
     }
      public void setAddress(String address ) {
            this . address = address ;
     }
      /*public Company(String name, int pnum , String address) {
           this.name = name;
           this.pnum = pnum ;
           this.address = address;
     }*/
}
在程序中抽取出两个方法:1.XML转化成List对象 2.List对象生成XML
最后对内存中的List对象进行CURD操作
以下为示例:
package cn.huangnan.stax.pull;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException ;
import org.xmlpull.v1.XmlPullParserFactory;
import org.xmlpull.v1.XmlSerializer;
/**
 * 抽取两个方法 从List到XML 和 从XML到List
 * @author Administrator
 *
 */
public class PullUtils {
     /**
      * 接收xml文件返回List集合
      * @return
      * @throws Exception
      */
      public static List<Company> ParseXml2List(String filename ) throws Exception{
           List<Company> companies = new ArrayList<Company>();
           Company company = null ;
           //获得解析器
           XmlPullParserFactory factory =XmlPullParserFactory. newInstance ();
           XmlPullParser parser = factory .newPullParser();
           //设置xml输入文件
            parser .setInput( new FileInputStream( filename ), "utf-8" );
           //解析遍历
            int event ;
          while((event=parser.getEventType())!=XmlPullParser.END_DOCUMENT) {
                //将每个<company>元素 封装成Company对象
                //1.在company开始的时候创建一个对象
                if(event==XmlPullParser.START_TAG&&parser.getName().equals("company")) {
                      company = new Company();
                }
                if(event==XmlPullParser.START_TAG&&parser.getName().equals("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("adderss")) {
                     company.setAddress(parser.nextText());
                }
                if(event==XmlPullParser.END_TAG&&parser.getName().equals("company")) {
                     companies.add(company);
                }
                
                parser.next();
           }
            return companies ;
           
     }
     /*
      * 同时接收List集合和xml文件 将集合中数据写入xml
      */
      public static void Serializer2Xml(List<Company> companies ,String fileName ) throws Exception {
           //获得序列化对象
           XmlPullParserFactory factory =XmlPullParserFactory. newInstance ();
           XmlSerializer serializer = factory .newSerializer();
           //写文件之前,指定输出文件
            serializer .setOutput( new FileOutputStream( fileName ), "utf-8" );
           //文档开始
            serializer .startDocument( "utf-8" , true );
           //根元素开始 companies
           serializer.startTag(null,"companies");
           //遍历集合List 每个List中Company对象生成一个片段
            for (Company c : companies ) {
                //company开始
                 serializer .startTag( null , "company" );
                //name开始
                 serializer .startTag( null , "name" );
                //输入name文本
                serializer.text(c.getName());
                //name结束
                 serializer .endTag( null , "name" );
                 serializer .startTag( null , "pnum" );
                serializer.text(String.valueOf(c.getPnum()));
                 serializer .endTag( null , "pnum" );
                 serializer .startTag( null , "address" );
                serializer.text(c.getAddress());
                 serializer .endTag( null , "address" );
                //company结束
                 serializer .endTag( null , "company" );
           }
           //文档结束
            serializer .endTag( null , "companies" );
           serializer.endDocument();
     }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值