xml 文件在各种开发中都广泛应用.Android中也不例外.作为承载数据的一个重要角色.如何读写xml成为一项十分重要的技能.
在Android中,常见的xml解析器分为DOM解析器,SAX解析器,PULL解析器.
将该xml文件放置在assets目录中.
<?xml version="1.0" encoding="utf-8"?>
<persons>
<person id="1">
<name>zhangsan</name>
<age>21</age>>
</person>
<person id="2">
<name>lisi</name>
<age>22</age>>
</person>
<person id="2">
<name>wangwu</name>
<age>23</age>>
</person>
</persons>
DOM 解析器
DOM是基于树形结构的节点和信息片段的集合,允许开发人员使用DOM API遍历xml树,检索所需结构.分析该结构通常需要加载整个文档和构造整个树形结构,然后才可检索和更新节点信息.
在DOM解析过程中,会先把整个xml读入内存中,然后构建一个驻留内存的树结构,这样就可以通过代码使用DOM接口来操作整个树结构.由于DOM在内存中以树形结构存放,因此,检索和更新的效率会更高.但是对于特别大的文档,解析和加载会消耗比较大的资源,如果xml文件比较小,使用DOM也是可行的.
DOM解析的步骤
1.首先利用DocumentBuilderFactory 创建一个DocumentBuilderFactory实例.
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
2.利用DocumentBuilderFactory 创建一个DocumentBuilder实例.
DocumentBuilder build = factory.newDocumentBuilder() ;
3.加载整个xml文档(Document).
4.获取文档的根节点(Element).
5.获取根节点中所有子节点列表(NodeList).
6.然后获取子节点列表中的需要读取的节点
public List<Person> dom(Context context, String fileName){
List<Person> persons = new ArrayList<>();
//1首先利用DocumentBuilderFactory 创建一个DocumentBuilderFactory实例
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
InputStream is = null;
try{
//2利用DocumentBuilderFactory 创建一个DocumentBuilder实例
DocumentBuilder builder = factory.newDocumentBuilder();
is = context.getResources().getAssets().open(fileName);
//3加载整个文档(Document)
Document document = builder.parse(is);
//4获取文档的根节点(Element)
Element element = document.getDocumentElement();
//5获取根节点下所有标签为person的子节点
NodeList items = element.getElementsByTagName("person");
for (int i = 0; i < items.getLength(); i++){
Person person = new Person();
//得到一个person节点
Element personNode = (Element) items.item(i);
//得到person节点中的id的属性值
person.id = Integer.parseInt(personNode.getAttribute("id"));
Element name = (Element) personNode.getElementsByTagName("name").item(0);
person.name = name.getFirstChild().getNodeValue();
Element age = (Element) personNode.getElementsByTagName("age").item(0);
person.age = Integer.parseInt(age.getFirstChild().getNodeValue());
// NodeList childsNode = personNode.getChildNodes();
// for (int j = 0; j < childsNode.getLength(); j++) {
// Node node = childsNode.item(j);
// if (node.getNodeType() == Node.ELEMENT_NODE) {
// Element childNode = (Element) node;
// if (childNode.getNodeName().equals("name")) {
// person.name = childNode.getFirstChild().getNodeValue();
// } else if (childNode.getNodeName().equals("age")) {
// person.age = Integer.parseInt(childNode.getFirstChild().getNodeValue());
// }
// }
// }
persons.add(person);
}
}catch (ParserConfigurationException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}catch (SAXException e){
e.printStackTrace();
}finally {
try{
is.close();
}catch ( IOException e){
e.printStackTrace();
}
}
return persons;
}
SAX 解析器
SAX是一种基于事件的解析器,事件驱动的解析流程方式是从文档的开始解析到文档的结束.不可暂停或倒退.SAX解析器占用内存少,解析速度快.SAX解析的工作原理是对文档进行顺序扫描,当扫描到文档的开始(Document),元素(Element)的开始与结束,文档(Document)的结束.等地方时通知事件处理函数,由事件处理函数作相关的动作.然后继续扫描,直到文档的结束.
SAX解析的步骤
1首先利用SAXParserFactory创建一个SAXParserFactory实例.
SAXParserFactory factory = SAXParserFactory.newInstance();
2 利用SAXParserFactory.newSAXParser()返回一个SAXParser解析器
SAXParser parser = factory.newSAXParser();
3 利用SAXParser获取一个事件源对象XMLReader
4 实例化一个DefaultHandler对象
5 连接事件源对象XMLReader到事件处理类DefaultHandler中
6 调用XMLReader的parse方法从输入源中获取xml数据
7 通过 DefaultHandler 返回我们所需的数据
public List<Person> sax(Context context, String fileName){
//首先利用SAXParserFactory创建一个SAXParserFactory实例
SAXParserFactory factory = SAXParserFactory.newInstance();
InputStream is = null;
try{
is = context.getResources().getAssets().open(fileName);
//利用SAXParserFactory.newSAXParser()返回一个SAXParser解析器
SAXParser parser = factory.newSAXParser();
//利用SAXParser获取一个事件源对象XMLReader
XMLReader reader = parser.getXMLReader();
//实例化一个DefaultHandler对象
XMLContenHandler handler = new XMLContenHandler();
//连接事件源对象XMLReader到事件处理类DefaultHandler中
reader.setContentHandler(handler);
//调用XMLReader的parse方法从输入源中获取xml数据
reader.parse(new InputSource(is));
//通过 DefaultHandler 返回我们所需的数据
return handler.getPersons();
}catch (IOException e){
e.printStackTrace();
}catch (SAXException e) {
e.printStackTrace();
}catch (ParserConfigurationException e){
e.printStackTrace();
}finally {
try{
is.close();
}catch (IOException e){
e.printStackTrace();
}
}
return null;
}
class XMLContenHandler extends DefaultHandler{
private List<Person> persons;
private Person person;
private String tagName;
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 {
if ("person".equals(localName)) {
person = new Person();
person.id = Integer.parseInt(attributes.getValue("id"));
}
this.tagName = localName;
}
//读取到节点内容时回调
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (tagName != null) {
String data = new String(ch, start, length);
if ("name".equals(tagName)) {
person.name = data;
} else if("age".equals(tagName)){
person.age = Integer.parseInt(data);
}
}
}
//读取到一个标签结束时调用
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if ("person".equals(localName)) {
persons.add(person);
person = null;
}
this.tagName = null;
}
//文档结束时调用
@Override
public void endDocument() throws SAXException {
super.endDocument();
}
}
PULL 解析器
PULL解析器的运行方式与SAX类似,它提供了相似的事件,如开始元素和结束元素事件.不同的是,PULL解析在解析过程中返回的是数字.且需要我们自己获取产生的事件然后做相应的处理,而不像SAX由处理器触发一些事件.
PULL解析器小巧轻便,解析速度快.简单易用,非常适合在Android设备中使用,Android系统内部在解析xml时也是使用的PULL解析器.Android官方推荐开发者使用PULL解析器.
PULL解析的步骤
1 创建一个XmlPullParser 对象
XmlPullParser xmlPullParser = Xml.newPullParser();
2 添加文档信息进XmlPullParser解析器
3 得到个节点信息
public List<Person> pull(Context context, String fileName){
//获得一个pull解析器
XmlPullParser parser = Xml.newPullParser();
List<Person> persons = null;
Person person = null;
InputStream is = null;
try {
is = context.getResources().getAssets().open(fileName);
//添加文档信息进pull解析器
parser.setInput(is, "UTF-8");
//得到节点信息
int evtType = parser.getEventType();
while (evtType != XmlPullParser.END_DOCUMENT) {//如果不是文档结束节点
switch (evtType) {
case XmlPullParser.START_DOCUMENT: //文档的开始
persons = new ArrayList<>();
break;
case XmlPullParser.START_TAG: //开始标签
String tag = parser.getName();
if ("person".equals(tag)) {
person = new Person();
person.id = Integer.parseInt(parser.getAttributeValue(null, "id"));
} else if (person != null) {
if ("name".equals(tag)) {
person.name = parser.nextText();
} else if ("age".equals(tag)){
person.age = Integer.parseInt(parser.nextText());
}
}
break;
case XmlPullParser.END_TAG: //结束标签
if ("person".equals(parser.getName()) && person != null) {
persons.add(person);
person = null;
}
break;
}
evtType = parser.next();
}
return persons;
} catch (IOException e){
e.printStackTrace();
} catch (XmlPullParserException e){
e.printStackTrace();
} finally {
try{
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
以上三种解析xml文件的结果是一样的。