说明:此案例使用的是通过Dom方式解析xml文件这篇文章里的City类和china.xml文件。
1. 因为xml文件有两种格式,一是上面那篇文章里的那种元素节点里只包含属性节点,另一种就是元素节点里包含元素节点和文本节点,于是在china.xml中添加如下代码,以实现两种方式的解析:
<city>
<cityname>杭州</cityname>
<pyName>zhejiang</pyName>
<quName>浙江</quName>
<state1>1</state1>
<state2>1</state2>
<stateDetailed>阴</stateDetailed>
<tem1>34</tem1>
<tem2>20</tem2>
<windState>东北风1-2级</windState>
</city>
2. 布局文件有变,用Spinner控件代替了RadioGroup控件,界面如下图:
3. 因为使用了Spinner控件,所以要在res/values文件夹下创建一个array.xml文件,用来获取Spinner控件中的item值,如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="cities">
<item>北京</item>
<item>江苏</item>
<item>浙江</item>
</string-array>
</resources>
string.xml文件中的Spinner控件:
<Spinner
android:id="@+id/sp_cities"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:entries="@array/cities"
android:layout_below="@+id/textView1" />
4. SAXXML类中的主要代码如下,有详解注释:
public class SAXXML {
public List<City> saxXml() {
MyDefaultHandler myHandler = new MyDefaultHandler();
// 1.创建解析器工厂对象
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
// 2.使用当前配置的工厂参数创建SAXParser的一个新实例(解析器对象)
try {
SAXParser saxParser = saxParserFactory.newSAXParser();
// 3.解析xml文件
saxParser.parse(
getClass().getClassLoader()
.getResourceAsStream("china.xml"),
myHandler);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return myHandler.getCities();
}
// 事件驱动的处理者
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 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("cityname")) {
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);
}
}
}
@Override
public void endDocument() throws SAXException {
super.endDocument();
System.out.println("---endDocument()---");
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
super.endElement(uri, localName, qName);
if (qName.equals("city")) {
cities.add(currentCity);
currentCity = null;
}
this.tagName = null;
}
// 开始解析文档
@Override
public void startDocument() throws SAXException {
super.startDocument();
System.out.println("---startDocument()---");
cities = new ArrayList<>();
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
//判断标签是不是city标签
if (qName.equals("city")) {
//实例化对象
currentCity = new City();
//判断属性对象是否为空
if (attributes != 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"));
}
}
this.tagName = qName;
}
}
}
5.
MainActivity的主要步骤是:获取控件对象,实现OnItemSelectedListener接口注册监听事件,获取字符串数组,设置控件的默认值,获取解析的xml文件等,主要代码如下:
public class MainActivity extends Activity implements OnItemSelectedListener {
private Spinner sp_cities;
private TextView tv_fengli;
private String cities[];
private SAXXML saxXml;
private List<City> entities;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 获取控件对象
sp_cities = (Spinner) findViewById(R.id.sp_cities);
tv_fengli = (TextView) findViewById(R.id.tv_fengli);
// 注册事件
sp_cities.setOnItemSelectedListener(this);
// 获取字符串数组
cities = getResources().getStringArray(R.array.cities);
saxXml = new SAXXML();
// 设置控件的默认值
sp_cities.setSelection(2);
// 获取解析的xml文件
entities = saxXml.saxXml();
}
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position,
long id) {
for (City c : entities) {
// 找到对应的city对象
if (c.getQuName().equals(cities[position])) {
// 设置风力
tv_fengli.setText(c.getWindState());
break;
}
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
System.out.println("nothing");
}
}
6. 主要功能:
通过点击下拉列表里的城市进行切换,实现各城市风力的显示。