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

来源:互联网 发布:天知地知你知我知 编辑:程序博客网 时间:2024/06/11 15:20

今天我们首先讲了运用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;@Overrideprotected 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);}@Overridepublic 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;}@Overridepublic void startDocument() throws SAXException {super.startDocument();//System.out.println("---------startDocument()-----------");//实例化cities = new ArrayList<City>();}@Overridepublic void endDocument() throws SAXException {super.endDocument();System.out.println("---------endDocument()-----------");}@Overridepublic 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();//判断属性对象是否为NULLif (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;}@Overridepublic 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;}@Overridepublic 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;@Overrideprotected 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();}@Overridepublic 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;}}}@Overridepublic 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则不行。

1 0
原创粉丝点击