浅谈Android Studio 解析XML的三种方法

时间:2021-05-19

一丶概述

文件解析要求,json解析和xml解析,前面文章说过Json转实体类,这里就说说解析XML

内容:

Android Studio 解析XML常见的三种方式:DOM PULL SAX (实现XML转实体类并打印输出)

效果演示:


二丶正文

SAX(Simple API for XML) 使用流式处理的方式,它并不记录所读内容的相关信息。它是一种以事件为驱动的XML API,解析速度快,占用内存少。使用回调函数来实现。 缺点是不能倒退。

DOM(Document Object Model) 是一种用于XML文档的对象模型,可用于直接访问XML文档的各个部分。它是一次性全部将内容加载在内存中,生成一个树状结构,它没有涉及回调和复杂的状态管理。 缺点是加载大文档时效率低下。

Pull内置于Android系统中。也是官方解析布局文件所使用的方式。Pull与SAX有点类似,都提供了类似的事件,如开始元素和结束元素。不同的是,SAX的事件驱动是回调相应方法,需要提供回调的方法,而后在SAX内部自动调用相应的方法。而Pull解析器并没有强制要求提供触发的方法。因为他触发的事件不是一个方法,而是一个数字。它使用方便,效率高。

SAX、DOM、Pull的比较:

1. 内存占用:SAX、Pull比DOM要好;
2. 编程方式:SAX采用事件驱动,在相应事件触发的时候,会调用用户编好的方法,也即每解析一类XML,就要编写一个新的适合该类XML的处理类。DOM是W3C的规范,Pull简洁。
3. 访问与修改:SAX采用流式解析,DOM随机访问。
4. 访问方式:SAX,Pull解析的方式是同步的,DOM逐字逐句

这里不做详细讲解,看注释,上代码

看项目文件,注意XML放的位置,不会建assets参考


XML

<?xml version="1.0" encoding="UTF-8" ?><persons> <person id="23"> <name>李雷</name> <age>30</age> </person> <person id="20"> <name>韩梅梅</name> <age>25</age> </person></persons>

person.Java

public class Person { Integer id; String name; Short age; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Short getAge() { return age; } public void setAge(Short age) { this.age = age; } @Override public String toString() { return "Person{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + '}'; }}

XMLtoEntityActivity

public class XMLtoEntityActivity extends AppCompatActivity { private TextView tv_show_entity; private String string = ""; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.xmlto_entity_activity); tv_show_entity = (TextView) findViewById(R.id.tv_show_entity); } public void startXML(View view){// SAXService saxService = new SAXService();// DOMService domService = new DOMService(); PULLService pullService = new PULLService(); try { InputStream inputStream = getAssets().open("Users.xml");// List<Person> persons = saxService.getPerson(inputStream);// List<Person> persons = domService.getPersons(inputStream); List<Person> persons = pullService.getPersons(inputStream); for (Person person : persons) { Log.e("TAG",person.toString()); string += person.toString(); } } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } tv_show_entity.setText(string); }}

DOM方法

/** * 采用DOM解析XML内容 */public class DOMService { public List<Person> getPersons(InputStream inputStream) throws Exception { List<Person> persons = new ArrayList<>(); //获取DOM解析器工厂 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); //获DOM解析器 DocumentBuilder builder = factory.newDocumentBuilder(); //将解析树放入内存,通过返回值Document来描述结果 Document document = builder.parse(inputStream); //取得根元素<personos> Element root = document.getDocumentElement(); //取得所有person节点集合 NodeList personNodes = root.getElementsByTagName("person"); for (int i = 0; i < personNodes.getLength(); i++) { Person person = new Person(); //取得person节点元素 Element personElement = (Element) personNodes.item(i); //取得属性值并设置ID person.setId(Integer.parseInt(personElement.getAttribute("id"))); //获取person的子节点 NodeList personChilds = personElement.getChildNodes(); for (int j = 0; j < personChilds.getLength(); j++) { //判断当前节点是否是元素类型的节点 if (personChilds.item(j).getNodeType() == Node.ELEMENT_NODE) { Element childElement = (Element) personChilds.item(j); if ("name".equals(childElement.getNodeName())) { //获取孙节点的值 person.setName(childElement.getFirstChild().getNodeValue()); } else if ("age".equals(childElement.getNodeName())) { person.setAge(Short.parseShort(childElement.getFirstChild().getNodeValue())); } } } persons.add(person); } return persons; }}

PULL方法

/** * 采用PULL解析XML内容 */public class PULLService { public List<Person> getPersons(InputStream inputStream) throws Exception { List<Person> persons = null; Person person = null; //得到PULL解析器 XmlPullParser parser = Xml.newPullParser(); parser.setInput(inputStream,"UTF-8"); //产生事件 int eventType = parser.getEventType(); //如果不是文档结束事件就循环推进 while (eventType != XmlPullParser.END_DOCUMENT) { switch (eventType) { case XmlPullParser.START_DOCUMENT://开始文档事件 persons = new ArrayList<>(); break; case XmlPullParser.START_TAG://开始元素事件 //获取解析器当前指向的元素的名称 String name = parser.getName(); if ("person".equals(name)) { person = new Person(); person.setId(Integer.parseInt(parser.getAttributeValue(0))); } if (person != null) { if ("name".equals(name)) { //获取解析器当前指向元素的下一个文本节点的值 person.setName(parser.nextText()); } if ("age".equals(name)) { person.setAge(Short.parseShort(parser.nextText())); } } break; case XmlPullParser.END_TAG://结束元素事件 //判断是都是person的结束事件 if ("person".equals(parser.getName())) { persons.add(person); person = null; } break; } //进入下一个元素并触发相应的事件 eventType = parser.next(); } return persons; }}

SAX方法

/** * 采用SAX解析XML内容 */public class SAXService { public List<Person> getPerson(InputStream inputStream) throws Exception { //得到SAX解析工厂 SAXParserFactory factory = SAXParserFactory.newInstance(); //得到SAX解析器 SAXParser parser = factory.newSAXParser(); PersonParser personParser = new PersonParser(); parser.parse(inputStream,personParser); inputStream.close(); return personParser.getPersons(); } private final class PersonParser extends DefaultHandler { private List<Person> persons = null; private String tag = null;//记录当前解析到了那个元素节点名称 private Person person; public List<Person> getPersons(){ return persons; } //一开始会执行这个方法,所以在这里面完成初始化 @Override public void startDocument() throws SAXException { persons = new ArrayList<>(); } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { //判断元素节点是否等于person if ("person".equals(localName)) { person = new Person(); //获取数据,参数为索引下标 person.setId(Integer.parseInt(attributes.getValue(0))); } tag = localName; } @Override public void endElement(String uri, String localName, String qName) throws SAXException { if ("person".equals(localName)) { persons.add(person); person = null; } tag = null; } @Override public void characters(char[] ch, int start, int length) throws SAXException { if (tag != null) { //获取文本节点的数据 String data = new String(ch, start, length); if ("name".equals(tag)) { person.setName(data); } else if ("age".equals(tag)) { person.setAge(Short.parseShort(data)); } } } }}

总结:Android开发主流是传json,而XML解析一般跟网络请求,爬虫数据相关。当然两者也是可以相互转换的,Java只强大在于提供了很多的类和方法。只要你愿意学,方法总是有的

源码下载欢迎Star(updating):https://github.com/JinBoy23520/CoderToDeveloperByTCLer

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。

相关文章