基本概念
概念: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解析xml
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解析xml
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解析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); ... } ...
- 常用api
//獲取屬性值
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;
}
}
- PULL解析
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;
}
- SAX解析
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;
}
}
- DOM解析
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