对xml的解析,我们在将j2ee中,常使用的解析器是DOM和SAX。而在android中,我们还可以使用PULL解析器。
pull是android中内置的解析器,可以直接的使用相关的类来解析大部分的xml文件了。pull也是采用事件驱动模型,跟SAX解析XML文件差不多。
xml文件:
<?xml version="1.0" encoding="UTF-8"?> <people> <person id="001"> <name>XY1</name> <age>22</age> </person> <person id="002"> <name>XY2</name> <age>22</age> </person> </people>这个xml文件为了获取流的方便,我是放在src目录下的。
解析的具体方法:
public class XmlTest extends Activity { private InputStream in = null; private List<Person> list = null; private Person person = null; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 将xml文件转换为输入流 in = Thread.currentThread().getContextClassLoader() .getResourceAsStream("people.xml"); // 新建List集合,来存放person数据 try { // 获取解析实例 XmlPullParser xmlparser = XmlPullParserFactory.newInstance() .newPullParser(); // 设置解析的xml xmlparser.setInput(in, "UTF-8"); // 取得事件 int event = xmlparser.getEventType(); /* * 开始循环解析xml里面的元素 当没到文档结束的位置,就一直循环下去 */ while (event != XmlPullParser.END_DOCUMENT) { // 获取节点的名字 String Node = xmlparser.getName(); if (Node != null) { Log.i("Node", Node); } else { Log.i("Node", Node + "=null"); } switch (event) { // 文档开始,即:<?xml version="1.0" encoding="UTF-8"?> case XmlPullParser.START_DOCUMENT: // 数据初始化 list = new ArrayList<Person>(); break; // 节点 case XmlPullParser.START_TAG: //初始化对象。 if ("person".equals(Node)) { person = new Person(); person.setId(Integer.parseInt(xmlparser .getAttributeValue(0))); } //设置对象的姓名 else if ("name".equals(Node)) { person.setName(xmlparser.nextText()); } //设置对象的年龄 else if ("age".equals(Node)) { person.setAge(xmlparser.nextText()); } break; // 结束节点 case XmlPullParser.END_TAG: if ("person".equals(Node)) { list.add(person); person = null; } break; default: break; } // 继续下一个标签 event = xmlparser.next(); } Log.i("list", list.get(0).toString() + "**" + list.get(1).toString()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }在上面的实例中,大家可以看到我在获取节点的时候,是打印了节点名字的,判断当节点获取为空的时候也会打印出来“Node=null”的字符窜。
我们来看下打印的日志:
在最后的时候,打印的list集合是符合我们的原来xml数据。
但为啥每次节点都会多个空节点呢??
原来,在xml中标签和内容都可以叫做节点。而节点分为两类,一个是ElementNode(元素节点),一个是TextNode(文本节点)。而在我们的xml中,每个节点都是换了行的,虽然看起来什么也没有,但也是节点,是文本节点,里面有回车和空格。
也许我这样更能理解点,可以明显的看出每个节点之间是换行了的。
那么该如何去纠正了??
1.修改xml的格式:
可以看到效果:
在这,name和age就没有空节点了。
不过这样的方式,只能说是一种取巧了,因为你不可能把所有的xml都放在同一行吧。
我们如此在意这个空节点的原因是,每次运行到空节点的时候,都会循环遍历依次,消耗我们的资源。如果当遇到空节点的时候,不遍历是不是可以呢?
protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 将xml文件转换为输入流 in = Thread.currentThread().getContextClassLoader() .getResourceAsStream("people.xml"); // 新建List集合,来存放person数据 try { // 获取解析实例 XmlPullParser xmlparser = XmlPullParserFactory.newInstance() .newPullParser(); // 设置解析的xml xmlparser.setInput(in, "UTF-8"); // 取得事件 int event = xmlparser.getEventType(); // 初始化person对象 person = new Person(); // 初始化集合 list = new ArrayList<Person>(); /* * 开始循环解析xml里面的元素 当没到文档结束的位置,就一直循环下去 */ while (event != XmlPullParser.END_DOCUMENT) { // 获取节点的名字 String Node = xmlparser.getName(); if (Node != null) { // Log.i("Node", Node); } else { // Log.i("Node", Node + "=null"); event = xmlparser.next(); Node = xmlparser.getName(); } switch (event) { // 文档开始,即:<?xml version="1.0" encoding="UTF-8"?> case XmlPullParser.START_DOCUMENT: break; // 节点 case XmlPullParser.START_TAG: if ("person".equals(Node)) { // person=new Person(); person.setId(Integer.parseInt(xmlparser .getAttributeValue(0))); } // 设置对象的姓名 else if ("name".equals(Node)) { person.setName(xmlparser.nextText()); } // 设置对象的年龄 else if ("age".equals(Node)) { person.setAge(xmlparser.nextText()); } break; // 结束节点 case XmlPullParser.END_TAG: if ("person".equals(Node)) { list.add(person); person = new Person(); } break; default: break; } if (Node != null) { Log.i("Node", Node); } else { Log.i("Node", Node + "=null"); } // 继续下一个标签 event = xmlparser.next(); } Log.i("list", list.get(0).toString() + "," + list.get(1).toString()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }
这就是效果图了,没有运行到null的节点了吧。
至于为啥,输出的集合元素中的有换行,那是因为解析的xml的字符窜中带有换行的字符。