4.XML

4.XML

使用XMl序列化器生成xml文件

//1.拿到序列化器对象
 XmlSerializer xs = Xml.newSerializer();
 //2.初始化
 File file = new File("sdcard/sms2.xml");
 try {
 FileOutputStream fos = new FileOutputStream(file);
 //enconding:指定用什么编码生成xml文件
			xs.setOutput(fos, "utf-8");
 //3.开始生成xml文件
 //enconding:指定头结点中的enconding属性的值
			xs.startDocument("utf-8", true);
			xs.startTag(null, "message");
 for (Message sms : smsList) {
				xs.startTag(null, "sms");
				xs.startTag(null, "body");
				xs.text(sms.getBody() + "<body>");
				xs.endTag(null, "body");
				xs.startTag(null, "date");
				xs.text(sms.getDate());
				xs.endTag(null, "date");
				xs.startTag(null, "type");
				xs.text(sms.getType());
				xs.endTag(null, "type");
				xs.startTag(null, "address");
				xs.text(sms.getAddress());
				xs.endTag(null, "address");
				xs.endTag(null, "sms");
 }
			xs.endTag(null, "message");
 //告诉序列化器,文件生成完毕
			xs.endDocument();
 } catch (Exception e) {
 // TODO Auto-generated catch block
			e.printStackTrace();
 } 

pull解析xml文件

先自己写一个xml文件,存一些天气信息
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<weather>
 <city>
 <name>上海</name>
 <temp>5°</temp>
 <pm>80</pm>
 </city>
 <city>
 <name>北京</name>
 <temp>-5°</temp>
 <pm>800</pm>
 </city>
 <city>
 <name>西安</name>
 <temp>12°</temp>
 <pm>60</pm>
 </city>
</weather>
  • 事件类型主要有五种 首先xmlpullpares.geteventype获取事件类型
    • START_DOCUMENT:xml头的事件类型
    • END_DOCUMENT:xml尾的事件类型,一般代码中首先判断是不是尾事件
    • START_TAG:开始节点的事件类型,这这里判断节点名字
    • END_TAG:结束节点的事件类型
    • TEXT:文本节点的事件类型
  • 解析过程

通过 getEventType()可以得到当前的解析事件,然后在一个 while循环中不断地进行解析,如果当前的解析事件不等于 XmlPullParser.END_DOCUMENT,说明解析工作还没完成,调用 next()方法后可以获取下一个解析事件。在 while循环中, 通过 getName()方法得到当前结点的名字,如果发现结点名等于id、name或 version,就调用 nextText()方法来获取结点内具体的内容,每当解析完一个 app结点后就将获取到的内容打印出来。

public void click(View v){
 //获取到src文件夹下的资源文件
 InputStream is = getClassLoader().getResourceAsStream("weather.xml");
 //拿到pull解析器对象,和xml序列化器方法一样
 XmlPullParser xp = Xml.newPullParser();
  1. 也可以这样或得pull解析器: 首先要获取到一个XmlPullParserFactory 的实例,并借助这个实例得到 XmlPullParser 对象,然后调用XmlPullParser的 setInput()方法将服务器返回的 XML数据设置进去就可以开始解析
//XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
//XmlPullParser xmlPullParser = factory.newPullParser();
//xmlPullParser.setInput(new StringReader(xmlData));		
//初始化		
try {			xp.setInput(is, "gbk");

上面的xml解析是通过传入的InputStream来进行解析、也可以通过直接解析String、要想直接解析String、可将上面传参改为String类型并将parser.setInput(inputStream,encoding);改为parser.setInput(new StringReader(string));便可以直接解析字符串形式的xml文件

 //获取当前节点的事件类型,通过事件类型的判断,我们可以知道当前节点是什么节点,从而确定我们应该做什么操作

 int type = xp.getEventType();
 City city = null;
 while(type != XmlPullParser.END_DOCUMENT){
 //根据节点的类型,要做不同的操作
 switch (type) {
 case XmlPullParser.START_TAG:
 //					获取当前节点的名字
 if("weather".equals(xp.getName())){
 //创建city集合对象,用于存放city的javabean
						cityList = new ArrayList<City>();
 }
 else if("city".equals(xp.getName())){
 //创建city的javabean对象
						city = new City();
 }
 else if("name".equals(xp.getName())){
 //				获取当前节点的下一个节点的文本
 String name = xp.nextText();
						city.setName(name);
 }
 else if("temp".equals(xp.getName())){
 //				获取当前节点的下一个节点的文本
 String temp = xp.nextText();
						city.setTemp(temp);
 }
 else if("pm".equals(xp.getName())){
 //				获取当前节点的下一个节点的文本
 String pm = xp.nextText();
						city.setPm(pm);
 }
 break;
 case XmlPullParser.END_TAG:
 if("city".equals(xp.getName())){
 //把city的javabean放入集合中
						cityList.add(city);
 }
 break;
 }
 //把指针移动到下一个节点,并返回该节点的事件类型
				type = xp.next();
 }
 for (City c : cityList) {
 System.out.println(c.toString());
 }
 } catch (Exception e) {
 // TODO Auto-generated catch block
			e.printStackTrace();
 }
 }

SAX解析

  • 事件类型主要有五种
    • startDocument:xml头的事件类型,在这里创建节点里的各个参数的bulid
    • startElement:xml的某个节点,在定义个变量来记录当前节点的名字
    • characters:开始节点的事件类型,如果当前节点等于各个参数的话加入build
    • endElement:结束节点的事件类型,在这里已经解析出来了,可以打印看
    • endDocument:xml尾的事件类型
<apps slick-umid="3">
 <app>
 <id>1</id>
 <name>google maps</name>
 <veision>1.0</veision>
 </app>
 <app>
 <id>2</id>
 <name>chrome</name>
 <veision>2.1</veision>
 </app>
 <app>
 <id>3</id>
 <name>google play</name>
 <veision>3.0</veision>
 </app>
</apps>

Pull解析方式虽然非常的好用,但它并不是唯一的选择。SAX解析也是一种特别常用 的 XML解析方式,虽然它的用法比 Pull解析要复杂一些,但在语义方面会更加的清楚。 通常情况下都会新建一个类继承自 DefaultHandler,并重写父类的五个方法,如下

public class ContentHandler extends DefaultHandler
{
 private String nodeName;
 private StringBuilder id;
 private StringBuilder name;
 private StringBuilder version;
 @Override
 //开始 XML解析的时候调用
 public void startDocument() throws SAXException {
 //首先给id、name和version结点分别定义了一个StringBuilder对象,并在startDocument()方法里对它们进行了初始化
		id = new StringBuilder();
		name = new StringBuilder();
		version = new StringBuilder();
 }
 @Override
 public void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException{
 //每当开始解析某个结点的时候,startElement()方法就会得到调用,其中localName参数记录着当前结点的名字,这里把它记录下来
		nodeName = localName;
 }
 @Override
 public void characters(char[] ch, int start, int length) throws SAXException {
 //在解析结点中具体内容的时候就会调用characters()方法,根据当前的结点名进行判断,
 //将解析出的内容添加到哪一个StringBuilder对象中
 if ("id".equals(nodeName)) {
			id.append(ch, start, length);
 }
 else if ("name".equals(nodeName)) {
			name.append(ch, start, length);
 } 
 else if ("version".equals(nodeName)) {
			version.append(ch, start, length);
 }
 }
 @Override
 public void endElement(String uri, String localName, String qName) throws SAXException {
 //在endElement()方法中进行判断,如果app结点已经解析完成,就打印出id、name和version的内容。
 //需要注意的是,目前id、name和version中都可能是包括回车或换行符的,因此在打印之前还需要调用一下trim()方法
 if ("app".equals(localName)) {
 Log.d("ContentHandler", "id is " + id.toString().trim());
 Log.d("ContentHandler", "name is " + name.toString().trim());
 Log.d("ContentHandler", "version is " + version.toString().trim());
 // 最后要将StringBuilder清空掉,,不然的话会影响下一次内容的读取。
				id.setLength(0);
				name.setLength(0);
				version.setLength(0);
 }
 }
 @Override
 public void endDocument() throws SAXException {
 }
}
private void parseXMLWithSAX(String xmlData) {// xmlData
 try {
 //创建了一个SAXParserFactory的对象
 SAXParserFactory factory = SAXParserFactory.newInstance();
 //获取到XMLReader对象
 XMLReader xmlReader = factory.newSAXParser().getXMLReader();
 ContentHandler handler = new ContentHandler();
 // 将ContentHandler的实例设置到XMLReader中
			xmlReader.setContentHandler(handler);
 // 开始执行解析
			xmlReader.parse(new InputSource(new StringReader(xmlData)));
 } 
 catch (Exception e) {
			e.printStackTrace();
 }
 }

书上的方法

public class ContentHandler extends DefaultHandler {
 private String nodeName;
 private StringBuilder id;
 private StringBuilder mp3Name;
 private StringBuilder mp3Size;
 private StringBuilder lrcName;
 private StringBuilder lrcSize;
 // 开始 XML解析的时候调用
 public void startDocument() throws SAXException {
 // 首先给结点分别定义了一个StringBuilder对象,并在startDocument()方法里对它们进行了初始化
		id = new StringBuilder();
		mp3Name = new StringBuilder();
		mp3Size = new StringBuilder();
		lrcName = new StringBuilder();
		lrcSize = new StringBuilder();
 }
 @Override
 public void startElement(String uri, String localName, String qName,
			org.xml.sax.Attributes attributes) throws SAXException {
 // 每当开始解析某个结点的时候,startElement()方法就会得到调用,其中localName参数记录着当前结点的名字,这里把它记录下来
 // TODO Auto-generated method stub
 super.startElement(uri, localName, qName, attributes);
		nodeName = localName;
 }
 @Override
 public void characters(char[] ch, int start, int length)
 throws SAXException {
 // 在解析结点中具体内容的时候就会调用characters()方法,根据当前的结点名进行判断,
 // 将解析出的内容添加到哪一个StringBuilder对象中
 if ("id".equals(nodeName)) {
			id.append(ch, start, length);
 } else if ("mp3Name".equals(nodeName)) {
			mp3Name.append(ch, start, length);
 } else if ("mp3Size".equals(nodeName)) {
			mp3Size.append(ch, start, length);
 } else if ("lrcName".equals(nodeName)) {
			lrcName.append(ch, start, length);
 } else if ("lrcSize".equals(nodeName)) {
			lrcSize.append(ch, start, length);
 }
 }
 @Override
 public void endElement(String uri, String localName, String qName)
 throws SAXException {
 // 在endElement()方法中进行判断,如果app结点已经解析完成,就打印出节点的内容。
 // 需要注意的是,目前节点中都可能是包括回车或换行符的,因此在打印之前还需要调用一下trim()方法
 if ("resource".equals(localName)) {
 Log.d("ContentHandler", "id is " + id.toString().trim());
 Log.d("ContentHandler", "mp3Name is " + mp3Name.toString().trim());
 Log.d("ContentHandler", "mp3Size is " + mp3Size.toString().trim());
 // 最后要将StringBuilder清空掉,,不然的话会影响下一次内容的读取。
			id.setLength(0);
			mp3Name.setLength(0);
			mp3Size.setLength(0);
			lrcName.setLength(0);
			lrcName.setLength(0);
 }
 }
 @Override
 public void endDocument() throws SAXException {
 }
}

视频的方法

public class Mp3ListContentHandler extends DefaultHandler {
 private List<Mp3Info> infos = null;
 private Mp3Info mp3Info = null;
 private String tagName = null;
 public Mp3ListContentHandler(List<Mp3Info> infos) {
 super();
 this.infos = infos;
 }
 public List<Mp3Info> getInfos() {
 return infos;
 }
 public void setInfos(List<Mp3Info> infos) {
 this.infos = infos;
 }
 @Override
 public void startElement(String uri, String localName, String qName,
 Attributes attributes) throws SAXException {
 // TODO Auto-generated method stub
 super.startElement(uri, localName, qName, attributes);
 this.tagName = localName;
 if (tagName.equals("resource")) {
			mp3Info = new Mp3Info();
 }
 }
 @Override
 public void characters(char[] ch, int start, int length)
 throws SAXException {
 String temp = new String(ch, start, length);
 if (tagName.equals("id")) {
			mp3Info.setId(temp);
 } else if (tagName.equals("mp3.name")) {
			mp3Info.setMp3Name(temp);
 } else if (tagName.equals("mp3.size")) {
			mp3Info.setMp3Size(temp);
 } else if (tagName.equals("lrc.name")) {
			mp3Info.setLrcName(temp);
 } else if (tagName.equals("lrc.size")) {
			mp3Info.setLrcSize(temp);
 }
 super.characters(ch, start, length);
 }
 @Override
 public void endElement(String uri, String localName, String qName)
 throws SAXException {
 // TODO Auto-generated method stub
 super.endElement(uri, localName, qName);
 if (qName.equals("resource")) {
			infos.add(mp3Info);
 }
		tagName = "";
 }
 @Override
 public void startDocument() throws SAXException {
 // TODO Auto-generated method stub
 super.startDocument();
 }
 @Override
 public void endDocument() throws SAXException {
 // TODO Auto-generated method stub
 super.endDocument();
 }
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏李家的小酒馆

Java IO(IO流)-2

IO流 第一部分 (OutputStreamWriter BufferOutputStream) 转换流 超类为Reader和Writer 是字符流通向字节流的...

20500
来自专栏Java帮帮-微信公众号-技术文章全总结

JSP与EL表达式重点学习笔记(2)

EL(表达式语言) 1 EL概述 ? 1.1 EL的作用 JSP2.0要把html和css分离、要把html和javascript分离、要把Java脚本替换成标...

27940
来自专栏Android干货

Java数据解析---SAX

384120
来自专栏java架构师

Android一 流

补充Java知识:流 java.io 四个抽象类: 字节流:InputStream OutputStream 字符流:Reader Writer 站在程序角度上...

360110
来自专栏机器学习实践二三事

java IO体系

IO流 Java中IO流分为两种,字节流和字符流,顾名思义字节流就是按照字节来读取和写入的,字符刘是按照字符来存取的;常用的文件读取用的就是字符流,在网络通信里...

22970
来自专栏用户2442861的专栏

java IO流之四 使用转换流InputStreamReader和OutputStreamWriter

http://blog.csdn.net/a107494639/article/details/7586744

24210
来自专栏Python爱好者

Java基础笔记21

18440
来自专栏Hongten

java开发_读写txt文件操作

========================================================

76020
来自专栏钟绍威的专栏

初识字节流+实现缓冲字节流OutputStream的主要方法构造方法读关流实现BufferedInputStream实现BufferedOutputStream为什么read()返回的是Int型而不是

java中的IO流可以分为两种:字符流和字节流 字符流,顾名思义,就是对字符进行操作,只能操作文本文件 字节流,就是对字节进行操作,然而所有文件都是由字...

20080
来自专栏浪淘沙

java学习day12--IO对比,序列化

2018.6.19 1.IO 字节流 InputStream OutputStream 字符流 Reader Wr...

12820

扫码关注云+社区

领取腾讯云代金券