第10天xml解析
一.xml介绍:
1.XML:Extensible Markup Language,即可扩展标记语言. 用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。非常适合 Web 传输。XML 提供统一的方法来描述和交换独立于应用程序或供应商的结构化数据.
举例如下:
<?xml version="1.0" encoding="utf-8" ?>
<country>
<name>中国</name>
<province>
<name>黑龙江</name>
<citys>
<city>哈尔滨</city>
<city>大庆</city>
</citys>
</province>
<province>
</country>
2.XML和Json都可以在网络传输中使用的。现在主要是使用Json传输.
Json:
{
name: "中国",
provinces: [
{ name: "黑龙江", citys: { city: ["哈尔滨", "大庆"]} },
{ name: "广东", citys: { city: ["广州", "深圳", "珠海"]} },
{ name: "台湾", citys: { city: ["台北", "高雄"]} },
{ name: "新疆", citys: { city: ["乌鲁木齐"]} }
]
}
- 两者比较:
A,可读性来说,XML有明显的优势,毕竟人类的语言更贴近这样的说明结构。JSON读起来更像一个数据块,但读起来就比较费解了。
B,传输效率上来说,JSON更为清晰且冗余更少些。JSON网站提供了对JSON语法的严格描述,只是描述较简短。
从总体来看,XML比较适合于标记文档(配置工程),而JSON却更适于进行数据交换的处理。
C,编码难度XML有丰富的编码工具,比如Dom4j、JDom等,JSON也有json.org提供的工具,但是JSON的编码明显比XML容易许多,即使不借助工具也能写出JSON的代码,可是要写好XML就不太容易了。
//1.获得客户端Socket
BluetoothSocket socket = bluetoothDevice.createRfcommSocketToServiceRecord(uuid);
socket.connect();
//2.获得服务端Socket
BluetoothServerSocket serverSocket = bluetoothAdapter.listenUsingRfcommWithServiceRecord(bluetoothAdapter.getName(),uuid);
serverSocket.accpet();
二.Xml解析:
1.PULL
Pull 内置于 Android 系统中。也是官方解析布局文件所使用的方式。Pull 与 SAX 有点类似,都提供了类似的事件,如开始元素和结束元素。
不同的是,SAX 的事件驱动是回调相应方法,需要提供回调的方法,而后在 SAX 内部自动调用相应的方法。
而Pull解析器并没有强制要求提供触发的方法。因为他触发的事件不是一个方法,而是一个数字。它使用方便,效率高。
2.SAX
SAX(Simple API for XML) 使用流式处理的方式,它并不记录所读内容的相关信息。它是一种以事件为驱动的XML API,解析速度快,占用内存少。使用回调函数来实现。缺点是不能倒退。
3.DOM
DOM(Document Object Model) 是一种用于XML文档的对象模型,可用于直接访问 XML 文档的各个部分。它是一次性全部将内容加载在内存中,生成一个树状结构,它没有涉及回调和复杂的状态管理。
缺点是加载大文档时效率低下。
4.SAX、DOM、Pull三种解析方式的比较
- 内存占用:SAX、Pull比DOM要好;
- 编程方式:SAX 采用事件驱动,在相应事件触发的时候,会调用用户编好的方法,也即每解析一类 XML,就要编写一个新的适合该类XML的处理类。DOM 是 W3C 的规范,Pull 简洁。
- 访问与修改:SAX 采用流式解析,DOM 随机访问。
- 访问方式:SAX,Pull 解析的方式是同步的,DOM 逐字逐句。
三 .下面分别采用3种方式进行解析xml文件
<students>
<student>
<name sex="man" age="15">小明</name>
<nickName>明明</nickName>
</student>
<student>
<name sex="woman" age="16">小红</name>
<nickName>红红</nickName>
</student>
<student>
<name sex="man" age="16">小亮</name>
<nickName>亮亮</nickName>
</student>
</students>
1.Pull解析
/**
* 一。5种事件类型
* XmlPullParser.START_DOCUMENT:文档的开始
* XmlPullParser.END_DOCUMENT:文档的结束
* XmlPullParser.START_TAG:开始标签
* XmlPullParser.END_TAG:结束标签
* XmlPullParser.TEXT:内容
*二。重要的方法:
* 1。XmlPullParser:getEventType()获得当前事件类型
* 2。XmlPullParser:getAttributeValue()获得该标签的属性值
* 3。XmlPullParser:next()向下移动一个
* 4。XmlPullParser:nextText()向下移动一个并获得文本内容
* */
public class PullUtils {
public static List<StudentBean>PullList(InputStream inputStream) throws XmlPullParserException, IOException {
List<StudentBean>list = new ArrayList<>();
//TODO 1:pull解析器工厂
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
//TODO 2:获取pull解析器
XmlPullParser parser = factory.newPullParser();
//TODO 3:设置要解析的数据
parser.setInput(inputStream,"utf-8");
//TODO 4:获得当前类型
int type = parser.getEventType();
StudentBean bean = null;
//标签类型不为文档结束
while (type!=XmlPullParser.END_DOCUMENT){
switch (type){
case XmlPullParser.START_TAG:
//标签开始
if (parser.getName().equals("student")){
bean = new StudentBean();
}else if (parser.getName().equals("name")){
bean.sex = parser.getAttributeValue(0);
bean.age = parser.getAttributeValue(1);
bean.name = parser.nextText();
}else if (parser.getName().equals("nickName")){
bean.nickName = parser.nextText();
}
break;
case XmlPullParser.END_TAG:
//标签结束
if (parser.getName().equals("student"))
list.add(bean);
break;
}
type = parser.next();//向下读取
}
return list;
}
}
2.DOM解析
/**
* 一。重要的方法:
* 1。Document:getElementsByTagName(节点名称):根据节点名称获得节点列表
* 2。Node:getChildNodes():获得当前节点所有的子节点
* 3。Node:getAttributes():获取当前节点所有的属性和值
* 4。Node:getNodeValue():获得当前自节点的值
* 5。Node:getTextContent():获得当前节点的文本
* 6。Node:getNodeName():获得当前节点的名称
* */
public class DomUtils {
public static List<StudentBean>DomList(InputStream in) throws ParserConfigurationException, IOException, SAXException {
List<StudentBean>list = new ArrayList<>();
//TODO 1:获取dom解析器工厂
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
//TODO 2:获取解析器
DocumentBuilder builder = factory.newDocumentBuilder();
//TODO 3:设置要解析的数据
Document document = builder.parse(in);
//TODO 4:获得所有的student节点集合
NodeList nodeList = document.getElementsByTagName("student");
//TODO 5:遍历集合
for (int i = 0;i < nodeList.getLength();i ++){
Node node = nodeList.item(i);//对应student标签
StudentBean bean = new StudentBean();
//遍历student标签下子标签
NodeList childList = node.getChildNodes();
for (int j = 0;j < childList.getLength();j ++){
Node child = childList.item(j);//name标签;nickname标签
//获取name标签下的属性以及值
if (child.getNodeName().equals("name")){
//获取属性sex以及age值
NamedNodeMap map = child.getAttributes();
Node sex = map.getNamedItem("sex");
Node age = map.getNamedItem("age");
bean.sex = sex.getNodeValue();
bean.age = age.getNodeValue();
bean.name = child.getTextContent();
}else if (child.getNodeName().equals("nickName")){
//获取nickname标签下的值
bean.nickName = child.getTextContent();
}
}
list.add(bean);
}
return list;
}
}
五.SAX解析
public class SaxUtils {
private List<StudentBean>list = new ArrayList<>();
public List<StudentBean>SaxList(InputStream inputStream) throws IOException, ParserConfigurationException, SAXException {
//TODO 1:获取解析器工厂
SAXParserFactory factory = SAXParserFactory.newInstance();
//TODO 2:获取解析器
SAXParser parser = factory.newSAXParser();
//TODO 3:绑定字节流与解析器工具类->按照标签位置解析xml
parser.parse(inputStream,new SaxHelp());
return list;
}
//创建内部类解析器->xml解析
class SaxHelp extends DefaultHandler{
String buff;
StudentBean bean;
@Override
public void startDocument() throws SAXException {
super.startDocument();
//文档开始
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
if (qName.equals("student")){
bean = new StudentBean();
}else if (qName.equals("name")){
//获取sax以及age属性值
bean.sex = attributes.getValue("sex");
bean.age = attributes.getValue("age");
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
if (qName.equals("name")){
bean.name = buff;
}else if (qName.equals("nickName")){
bean.nickName = buff;
}else if (qName.equals("student")){
list.add(bean);
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
super.characters(ch, start, length);//读取标签内容
buff = new String(ch,start,length);//标签内容char数组转化为String字符串buff
//在endElement 赋值给bean.name或bean.nickname
}
@Override
public void endDocument() throws SAXException {
super.endDocument();
//文档结束
}
}
}