概念:extensive markup language(可扩展的标记语言)
XML是一种通用的数据存储和交换格式,与平台无关,与编程语言无关,与操作系统无关。给数据集成和交互提供了极大的便利。
将数据格式化成XML文件后,真正实现了数据跨平台的交互和共享。在不同语言中,xml的解析方式都一样。
XML文件格式:
1.每个xml文件中要有一个,且只能有一个xml根节点;
2.xml文件的数据中不可以 出现”< “或者” >”;
XML的解析方式:
DOM(document object model :文档对象模型):借助文档树模型对xml文档进行分析。
SAX(simple API for xml :xml的简单api):利用事件流的形式解析XML
PULL:利用事件流模型来解析XML。
备注:DOM和SAX解析的优劣分析:DOM是将文档一次性读入到内存,然后以文档树模进行分析节点信息。获取到希望获取的数据;
而SAX是事件流的形式去分析xml文件。DOM可以做到对文档中部分节点的修改、删除和新增,而SAX无法做到。
PULL Parser中的几种event值
1、START_DOCUMENT: 0
2、END_DOCUMENT: 1
3、START_TAG: 2
4、END_TAG: 3
5、TEXT: 4
核心类:
XmlPullParserFactory
XmlPullParser
核心代码:
// 实例化一个xml pull解析的工厂
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
// 实例化一个xml pull解析对象
XmlPullParser parser = factory.newPullParser();
// xml解析对象接收输入流对象
parser.setInput(instream, "utf-8");
int event = parser.getEventType();//获取事件类型
while (event != XmlPullParser.END_DOCUMENT) {
switch (event) {
case XmlPullParser.START_DOCUMENT:
//开始读取文档
break;
case XmlPullParser.START_TAG:
//读取元素开始标签
break;
case XmlPullParser.TEXT:
//读取文本
break;
case XmlPullParser.END_TAG:
//读取闭合标签
break;
}
event = parser.next();//获取下一次解析事件
}
常用api
//获取属性名
parser.getAttributeName()
//获取属性值
parser.getAttributeValue()
//获取文本值
parser.getText();
//获取标签名
parser.getName();
//获取下一个文本解析事件,返回文本值(如果当前是START_TAG,且下一个节点是TEXT,则返回文本,如果下一个是END_TAG,返回null,否则则会抛出异常)
parser.nextText();
//获取下一个标签解析事件,返回事件类型,如果下一个事件不是START_TAG或END_TAG,则抛出异常
parser.nextTag();
//获取下一个解析事件,返回事件类型
parser.next();
SAX解析基本与PULL解析基本相同,也是通过事件流的形式解析xml,SAX的解析借助于DefaultHandler这个处理类。该类实现如下:
class MyXmlHandler extends DefaultHandler {
/** * 开始读取文档 * * @throws SAXException */
@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);
//uri:命名空间
//localName:不带前缀(命名空间)的标签名
//qName:带前缀的标签名
//attributes:属性集合
}
/** * 开始读取Text */
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
super.characters(ch, start, length);
}
/** * 结束读取元素 */
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
//uri:命名空间
//localName:不带前缀(命名空间)的标签名
//qName:带前缀的标签名
}
/** * 结束读取文档 */
@Override
public void endDocument() throws SAXException {
super.endDocument();
}
}
核心代码如下:
SAXParserFactory factory=SAXParserFactory.newInstance();
SAXParser parser=factory.newSAXParser();
MyXmlHandler handler=new MyXmlHandler();//继承自DefaultHandler
parser.parse(in,handler);//插入一个自定义的xml处理器
DOM树中对节点(NODE)的分类如下
1、文档节点,Document
2、元素节点,Element
3、属性节点,Attribute
4、文本节点,Text
5、注释节点,Comment
核心类:
DocumentBuilderFactory
DocumentBuilder
Doucment,一个xml就是一个Document
Element ,…就是一个元素
NodeList ,节点集合
Node,节点,包括文档、元素、属性、文本节点等
核心代码
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// 使用工厂来实例化一个构造Document的对象
DocumentBuilder builder = factory.newDocumentBuilder();
// 利用DocumentBuilder来构造一个Document对象
Document document = builder.parse(filename);
// 获取Document文档的根节点对象
Element root = document.getDocumentElement();
// 通过根节点,获取到根节点下面的所有二级子节点
NodeList nodeList = root.getChildNodes();
// 遍历子节点,获取内部的每一个节点
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
...
}
...
//获取属性值
element.getAttribute();
//获取属性节点,没有则null
element.getAttributeNode();
//根据标签名返回当前节点下的后代(子子孙孙)节点
element.getElementsByTagName();
//获取标签名
element.getTagName();
//获取当前节点及其子节点的所有文本内容
node.getTextContent();
//获取儿子子节点
node.getChildNodes();
//获取节点名字(属性节点返回属性名字,元素节点返回标签名,Text节点返回"#text",Document节点返回"#document")
node.getNodeName();
//获取节点值(属性节点返回属性值,文本节点返回文本内容,Comment节点返回内容,CDATASection节点返回内容,其他节点返回null);
node.getNodeValue();
//返回当前节点的第一个子节点
node.getFirstChild();
//返回当前节点的最后子节点
node.getLastChild();
//获取节点类型
node.getNodeType();
//返回下一个兄弟节点
node.getNextSibling();
//返回上一个兄弟节点
node.getPreviousSibling();
//不包含命名空间的名字
node.getLocalName();
//以当前节点为根节点获取一个document对象
node.getOwnerDocument();
下面是一段显示近三日天气的xml,分别采用三种方式进行解析。
<weatherinfo>
<data d_id="01">
<date>2016-05-07</date>
<icon>d04|n04</icon>
<weather>雷阵雨</weather>
<temperature>36℃~28℃</temperature>
<winddirect>西南风3-4级</winddirect>
</data>
<data d_id="02">
<date>2016-05-08</date>
<icon>d04|n04</icon>
<weather>雷阵雨</weather>
<temperature>32℃~26℃</temperature>
<winddirect>西风3-4级转西北3-4级</winddirect>
</data>
<data d_id="03">
<date>2016-05-09</date>
<icon>d04|n04</icon>
<weather>雷阵雨</weather>
<temperature>32℃~26℃</temperature>
<winddirect>西北风3-4级</winddirect>
</data>
</weatherinfo>
首先根据xml创建一个Weather类。实现如下:
public class Weather {
private String id;
private String date;
private String icon;
private String weather;
private String temperature;
private String winddirect;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
public String getWeather() {
return weather;
}
public void setWeather(String weather) {
this.weather = weather;
}
public String getTemperature() {
return temperature;
}
public void setTemperature(String temperature) {
this.temperature = temperature;
}
public String getWinddirect() {
return winddirect;
}
public void setWinddirect(String winddirect) {
this.winddirect = winddirect;
}
}
public static List<Weather> pullParser(InputStream in) throws XmlPullParserException, IOException {
//初始化核心类
XmlPullParserFactory factory=XmlPullParserFactory.newInstance();
XmlPullParser parser=factory.newPullParser();
parser.setInput(in,"utf-8");
//初始化集合
List<Weather> list=new ArrayList<>();
Weather weather=null;
boolean flag=false;//weather类实例化的标识
//获取事件类型
int type=parser.getEventType();
while(type!=XmlPullParser.END_DOCUMENT){
switch (type) {
//开始标签
case XmlPullParser.START_TAG:
//如果开始标签是data,初始化Weather类
if(parser.getName().equals("data")){
weather=new Weather();
//读取属性值
String id=parser.getAttributeValue(null,"d_id");
weather.setId(id);
flag=true;
list.add(weather);
}
if(flag){//如果Weather类已实例化,就开始设置值
if(parser.getName().equals("date")){
//读取当前START_TAG的下一个文本节点
weather.setDate(parser.nextText());
}
else if(parser.getName().equals("weather")){
weather.setWeather(parser.nextText());
}
else if(parser.getName().equals("icon")){
weather.setIcon(parser.nextText());
}
else if(parser.getName().equals("temperature")){
weather.setTemperature(parser.nextText());
}
else if(parser.getName().equals("winddirect")){
weather.setWinddirect(parser.nextText());
}
}
break;
//闭合标签
case XmlPullParser.END_TAG:
if(parser.getName().equals("data")){
flag=false;
weather=null;
}
break;
}
//开始下一次解析事件
type=parser.next();
}
return list;
}
public static List<Weather> saxParser(InputStream in) throws ParserConfigurationException, SAXException, IOException{
SAXParserFactory factory=SAXParserFactory.newInstance();
SAXParser parser=factory.newSAXParser();
XmlHandler handler=new XmlHandler();//继承自DefaultHandler
parser.parse(in,handler);//插入一个自定义的xml处理器
return handler.getList();
}
static class XmlHandler extends DefaultHandler{
private List<Weather> list;
private String tagName;
private boolean flag=false;
private Weather weather;
/** * 开始读取文档 * @throws SAXException */
@Override
public void startDocument() throws SAXException {
super.startDocument();
list=new ArrayList<>();
}
/** * 开始读取元素 */
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
//uri:命名空间
//localName:不带前缀(命名空间)的标签名
//qName:带前缀的标签名
//attributes:属性集合
this.tagName=localName;
if(tagName.equals("data")){
weather=new Weather();
String id=attributes.getValue(0);
weather.setId(id);
flag=true;
}
//
}
/** * 开始读取Text */
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
super.characters(ch, start, length);
String str=new String(ch,start,length).trim();
if(tagName!=null){
if(flag){
if(tagName.equals("date")){
weather.setDate(str);
}else if(tagName.equals("icon")){
weather.setIcon(str);
}else if(tagName.equals("weather")){
weather.setWeather(str);
}else if(tagName.equals("temperature")){
weather.setTemperature(str);
}else if(tagName.equals("winddirect")){
weather.setWinddirect(str);
}
}
}
}
/** * 结束读取元素 */
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
if(localName.equals("data")){
list.add(weather);
flag=false;
}
tagName=null;
}
/** * 结束读取文档 */
@Override
public void endDocument() throws SAXException {
super.endDocument();
}
public List<Weather> getList(){
return list;
}
}
public static List<Weather> domParser(InputStream in) throws ParserConfigurationException, SAXException, IOException, XmlPullParserException {
/** * 初始化核心API */
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
DocumentBuilder builder=factory.newDocumentBuilder();
Document document=builder.parse(in);
List<Weather> list=new ArrayList<>();
NodeList nodes=document.getElementsByTagName("data");
for(int i=0;i<nodes.getLength();i++ ){
Element element= (Element) nodes.item(i);
Weather weather=new Weather();
weather.setId(element.getAttribute("d_id"));
NodeList childs=element.getChildNodes();
for(int j=0;j<childs.getLength();j++){
Node temp=childs.item(j);
if(temp.getFirstChild()!=null){
if(temp.getNodeName().equals("date")){
weather.setDate(temp.getFirstChild().getNodeValue());
}else if(temp.getNodeName().equals("icon")){
weather.setIcon(temp.getFirstChild().getNodeValue());
}else if(temp.getNodeName().equals("weather")){
weather.setWeather(temp.getFirstChild().getNodeValue());
}else if(temp.getNodeName().equals("temperature")){
weather.setTemperature(temp.getFirstChild().getNodeValue());
}else if(temp.getNodeName().equals("winddirect")){
weather.setWinddirect(temp.getFirstChild().getNodeValue());
}
}}
list.add(weather);
}
return list;
}
END