今天我们首先讲了运用DOM方法来解析XML,实现天气预报的显示还有城市间的切换功能:
DOM功能类的实现代码如下:
package com.example.example;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class DOMXML {
public List<City> domXml() {
// 创建返回的集合对象
List<City> cities = new ArrayList<City>();
// 创建了文档解析器的工厂对象
DocumentBuilderFactory builderFactory = DocumentBuilderFactory
.newInstance();
try {
// 得到文档解析器对象
DocumentBuilder builder = builderFactory.newDocumentBuilder();
// 获取输入流对象
InputStream is = getClass().getClassLoader().getResourceAsStream(
"china.xml");
// 通过解析器的parse方法解析is对象,转换成Document对象
Document document = builder.parse(is);
//返回的是文档的根节点
Element rootElement = document.getDocumentElement();
// 判断它是否有孩子节点
if (rootElement.hasChildNodes()) {
// 获取所有子节点
NodeList nodeList = rootElement.getChildNodes();
System.out.println("子节点的长度是:" + nodeList.getLength());
// 遍历子节点
for (int i = 0; i < nodeList.getLength(); i++) {
// 获取子节点对象
Node node = nodeList.item(i);
// 判断这个子节点是什么类型的子节点,文本节点
if (node.getNodeType() == Element.ELEMENT_NODE) {
// 获取元素节点的属性节点
// 转换成元素节点
// 创建一个实体对象,保存元素节点的值:
City city = new City();
// 造型
Element element = (Element) node;
cities.add(new City(element.getAttribute("cityName"),
element.getAttribute("pyName"), element
.getAttribute("quName"), element
.getAttribute("state1"), element
.getAttribute("state2"), element
.getAttribute("stateDetailed"), element
.getAttribute("tem1"), element
.getAttribute("tem2"), element
.getAttribute("windState")));
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return cities;
}
/* //前一种方法:不好用
public List<City> domXml1() {
// 创建返回的集合对象
List<City> cities = new ArrayList<City>();
// 创建了文档解析器的工厂对象
DocumentBuilderFactory builderFactory = DocumentBuilderFactory
.newInstance();
try {
// 得到文档解析器对象
DocumentBuilder builder = builderFactory.newDocumentBuilder();
// 获取输入流对象
InputStream is = getClass().getClassLoader().getResourceAsStream(
"china.xml");
// 通过解析器的parse方法解析is对象,转换成Document对象
Document document = builder.parse(is);
Element rootElement = document.getDocumentElement();
// 判断它是否有孩子节点
if (rootElement.hasChildNodes()) {
// 获取所有子节点
NodeList nodeList = rootElement.getChildNodes();
System.out.println("子节点的长度是:" + nodeList.getLength());
// 遍历子节点
for (int i = 0; i < nodeList.getLength(); i++) {
// 获取子节点对象
Node node = nodeList.item(i);
* System.out.println(node.getNodeType() + "------" +
* Element
* .DOCUMENT_TYPE_NODE+"------------"+Element.ELEMENT_NODE
* +"---------");
// 判断这个子节点是什么类型的子节点,文本节点
if (node.getNodeType() == Element.ELEMENT_NODE) {
// 获取元素节点的属性节点
// 转换成元素节点
// 创建一个实体对象,保存元素节点的值:
City city = new City();
// 造型
Element element = (Element) node;
// 得到这个节点中的所有属性
NamedNodeMap map = element.getAttributes();
// 遍历属性节点
for (int j = 0; j < map.getLength(); j++) {
// 获取具体的某个属性节点
Attr attr = (Attr) map.item(j);
// 具体判断,属性节点只能这样做
if ("cityname".equals(attr.getNodeName())) {
city.setCityName(attr.getNodeValue());
} else if ("pyName".equals(attr.getNodeName())) {
city.setPyName(attr.getNodeValue());
} else if ("quName".equals(attr.getNodeName())) {
city.setQuName(attr.getNodeValue());
} else if ("state1".equals(attr.getNodeName())) {
city.setState1(attr.getNodeValue());
} else if ("state2".equals(attr.getNodeName())) {
city.setState2(attr.getNodeValue());
} else if ("stateDetailed".equals(attr
.getNodeName())) {
city.setStateDetailed(attr.getNodeValue());
} else if ("windState".equals(attr.getNodeName())) {
city.setWindState(attr.getNodeValue());
}
// 获取属性值和属性名
// System.out.println("属性名:" + attr.getName() +
// "属性值"
// + attr.getValue());
}
cities.add(city);
// // 是否还有子节点
// if (node.hasChildNodes()) {
// // 获取所有的子节点
// NodeList list1 = node.getChildNodes();
// // 遍历
// for (int k = 0; k < list1.getLength(); k++) {
// // 获取子节点
// Node nk = list1.item(k);
// // 判断是否是元素节点
// if (nk.getNodeType() == Element.ELEMENT_NODE) {
// System.out.println("节点名称:"
// + nk.getNodeName() + "节点值:"
// + nk.getFirstChild().getNodeValue());
// }
// }
// }
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return cities;
}*/
}
MainActicity,安卓方面的操作的实现:
package com.example.example;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.TextView;
public class MainActivity extends Activity implements OnCheckedChangeListener{
//初始化标签
private RadioGroup rg;
private TextView tv_wendu,tv_fengli;
private DOMXML domxml;
private List<City> cities;
private int checkedId=1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rg = (RadioGroup) findViewById(R.id.rg);
rg.setOnCheckedChangeListener(this);
tv_wendu = (TextView) findViewById(R.id.tv_wendu);
tv_fengli =(TextView) findViewById(R.id.tv_fengli);
//解析xml文件
domxml = new DOMXML();
cities = domxml.domXml();
//获取被选中的控件的ID值
checkedId = rg.getCheckedRadioButtonId();
initData(checkedId);
}
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
initData(checkedId);
}
private void initData(int checkedId) {
City city = null;
//System.out.println(checkedId+"---------------"+R.id.radio1);
switch (checkedId) {
case R.id.radio0:
//北京天气:
for(City c:cities){
if("北京".equals(c.getCityName())){
city=c;
}
}
break;
case R.id.radio1:
for(City c:cities){
if("南京".equals(c.getCityName())){
city=c;
}
}
break;
case R.id.radio2:
for(City c:cities){
if("连云港".equals(c.getCityName())){
city=c;
}
}
break;
}
if(city!=null){
tv_wendu.setText(city.getTem2()+"°~"+city.getTem1()+"°");
tv_fengli.setText(city.getWindState());
}
}
}
<!--
节点名称 节点值 节点值 类型值
元素节点: 标签名 null 1
属性节点: 属性名 属性值 2
文本节点: #text 文本内容 3
-->
然后我们用第二种方法来解析XML,那就是利用SAX工厂模式:
SAX功能类的实现:
package com.example.example;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class SaxXML {
public List<City> saxXML() {
MyDefaultHandler myHandler = new MyDefaultHandler();
// 第一步:创建解析器工厂
SAXParserFactory spf = SAXParserFactory.newInstance();
try {
// 第二步:使用单签配置的工厂参数穿件SAXParser的一个新实例
SAXParser saxParser = spf.newSAXParser();
saxParser.parse(
getClass().getClassLoader()
.getResourceAsStream("china.xml"), myHandler);
} catch (Exception e) {
e.printStackTrace();
}
return myHandler.cities;
}
class MyDefaultHandler extends DefaultHandler {
private String tagName=null;//当前解析的标签
private City currentCity = null;
private List<City> cities;//当前解析的对象
public List<City> getCities() {
return cities;
}
@Override
public void startDocument() throws SAXException {
super.startDocument();
//System.out.println("---------startDocument()-----------");
//实例化
cities = new ArrayList<City>();
}
@Override
public void endDocument() throws SAXException {
super.endDocument();
System.out.println("---------endDocument()-----------");
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
// System.out.println("---------startElement()-----------"+uri+localName+qName+attributes);
//判断是不是CITY标签
if (qName.equals("city")) {
//实例化对象
currentCity = new City();
//判断属性对象是否为NULL
if (attributes != null) {
//如果不为NULL,就获取属性值,并且复制到CITY对象中
currentCity.setCityName(attributes.getValue("cityName"));
currentCity.setPyName(attributes.getValue("pyName"));
currentCity.setQuName(attributes.getValue("quName"));
currentCity.setState1(attributes.getValue("state1"));
currentCity.setState2(attributes.getValue("state2"));
currentCity.setStateDetailed(attributes
.getValue("stateDetailed"));
currentCity.setTem1(attributes.getValue("tem1"));
currentCity.setTem2(attributes.getValue("tem2"));
currentCity.setWindState(attributes.getValue("windState"));
}
}
/*
* int length = attributes.getLength(); for(int
* index=0;index<length;index++){
* String attrQName = attributes.getQName(index);
* String attrValue =attributes.getValue(attrQName);
* Sysout.out.println(attrQName+"------------"+attrValue);
* }
*/
this.tagName = qName;
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
super.endElement(uri, localName, qName);
// System.out.println("-----------endElement()---------------"+uri+localName+qName);
if (qName.equals("city")) {
cities.add(currentCity);
currentCity = null;
}
this.tagName = null;
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
super.characters(ch, start, length);
if (tagName != null) {
String value = new String(ch, start, length);
if (tagName.equals("name")) {
// System.out.println("------characters()-------"+new
// String(ch, start,length));
currentCity.setCityName(value);
}else if(tagName.equals("pyName")){
currentCity.setPyName(value);
}else if(tagName.equals("quName")){
currentCity.setQuName(value);
}else if(tagName.equals("state1")){
currentCity.setState1(value);
}else if(tagName.equals("state2")){
currentCity.setState2(value);
}else if(tagName.equals("stateDetailed")){
currentCity.setStateDetailed(value);
}else if(tagName.equals("tem1")){
currentCity.setTem1(value);
}else if(tagName.equals("tem2")){
currentCity.setTem2(value);
}else if(tagName.equals("windState")){
currentCity.setWindState(value);
}
}
}
}
}
然后是MainActivity关于安卓方面的实现:
package com.example.example;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity implements OnItemSelectedListener{
private Spinner sp_cities;
private String cities[];
private SaxXML saxXML;
private TextView tv_fengli;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sp_cities = (Spinner) findViewById(R.id.sp_city);
tv_fengli = (TextView) findViewById(R.id.tv_fengli);
//注册时间
sp_cities.setOnItemSelectedListener(this);
cities=getResources().getStringArray(R.array.cities);
sp_cities.setSelection(2);
saxXML = new SaxXML();
}
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position,
long id) {
System.out.println(parent+"---"+view+"---"+position+"---"+id);
Toast.makeText(this, cities[position], Toast.LENGTH_LONG).show();
List<City> entities = saxXML.saxXML();
for(City c:entities){
if(c.getQuName().equals(cities[position])){
tv_fengli.setText(c.getWindState());
break;
}
}
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
System.out.println("没选择");
}
}
补充知识:
SAX 是用于处理XML时间驱动的推模型来进行操作,最大的优点是内存消耗较小,因为整个文档无需一次加载到内存中,这种SAX解析可以解析大于系统内存的文档。
缺点是:不能直接获取一个标签内的内容,必须从头到尾解析一遍。文档越复杂, 你的逻辑就越复杂。
SAX解析中用到了DefaultHandler实现了以下的接口:用于访问XML:DtdHandler,用于低级访问解析错误的:ErrorHandler,用于访问文档内容的:ContentHandler
DOM解析与SAX解析的区别:
1、dom的优点:易用性强,使用DOM时,将把所有的XML文档信息都存于内存中,并且遍历简单,支持XPath,增强了易用性。
2、dom的缺点:效率地,解析速度慢,内存占用量过高,对于大文件来说几乎不可能,另外效率低还表现在大量的消耗时间。
区别:1、把所有的XML文档信息都存于内存中。
2、SAX无需一次把XML文件加载到内存中,采用的是事件驱动的操作。
3、应用场景不一样,DOM只能用于小文件,SAX可以应用在大文件上
4、DOM可以直接获取某个结点,但是SAX则不行。