安卓实训第十一天--DOM、SAX解析XML

今天我们首先讲了运用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则不行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值