android 中的 xml 解析方法
常用的方法有三种 分别是 sax ,dom , pull;
在org 中 org.w3c.dom 、org.w3c.dom.ls、org.xml.sax、org.xml.sax.ext、org.xml.sax.helpers、org.xmlpull.v1、org.xmlpull.v1.sax2 定义了 dom 、sax、pull的接口
在javax中 javax.xml.parsers 中定义了 dom 和 sax 的 解析接口 和工厂 (DocumentBuilder 、 SAXParser 和 DocumentBuilderFactory、SAXParserFactory)
在 android.util 中 定义了 pull 的 工厂(Xml),org中也提供了 pull的工厂 和解析类
1、sax 方法:
/**
*
* SAX是一个解析速度快并且占用内存少的xml解析器,非常适合用于Android等移动设备。
* SAX解析XML文件采用的是事件驱动,也就是说,它并不需要解析完整个文档,在按内容顺序解析文档的过程中,
* SAX会判断当前读到的字符是否合法XML语法中的某部分,如果符合就会触发事件。
* 所谓事件,其实就是一些回调方法,这些方法(事件)定义在ContentHandler接口。
*一般需要继承 DefaultHandler 重写里面的回调方法
*/
public List<Person> saxParser(InputStream is) { try { SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser saxParser = spf.newSAXParser(); // 创建解析器 SaxHandler handler = new SaxHandler(); saxParser.parse(is, handler); is.close(); return handler.getPersons(); } catch (Exception e) { e.printStackTrace(); } return null; }
2、dom方法:
/**
*
* 除了可以使用 SAX解析XML文件,大家也可以使用熟悉的DOM来解析XML文件。
* DOM解析XML文件时,会将XML文件的所有内容读取到内存中,然后允许您使用DOM API遍历XML树、检索所需的数据。
* 使用DOM操作XML的代码看起来比较直观,并且,在某些方面比基于SAX的实现更加简单。
* 但是,因为DOM需要将XML文件的所有内容读取到内存中,所以内存的消耗比较大,
* 特别对于运行Android的移动设备来说,因为设备的资源比较宝贵,所以建议还是采用SAX来解析XML文件,
* 当然,如果XML文件的内容比较小采用DOM是可行的。
*
* dom方式需要先生成 dom树,然后从中提取需要的内容 sax 直接从字节流中获取需要的内容,并且建立自定义的数据结构
*
* @param is
* @return
*/
public List<Person> domParser(InputStream is)
{
List<Person> persons = new ArrayList<Person>();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
try
{
DocumentBuilder builder = factory.newDocumentBuilder();
Document dom = builder.parse(is);
Element root = dom.getDocumentElement();
NodeList items = root.getElementsByTagName("person");// 查找所有person节点
for (int i = 0; i < items.getLength(); i++)
{
Person person = new Person();
// 得到第一个person节点
Element personNode = (Element) items.item(i);
// 获取person节点的id属性值
person.setId(new Integer(personNode.getAttribute("id")));
// 获取person节点下的所有子节点(标签之间的空白节点和name/age元素)
NodeList childsNodes = personNode.getChildNodes();
for (int j = 0; j < childsNodes.getLength(); j++)
{
Node node = (Node) childsNodes.item(j); // 判断是否为元素类型
if (node.getNodeType() == Node.ELEMENT_NODE)
{
Element childNode = (Element) node;
// 判断是否name元素
if ("name".equals(childNode.getNodeName()))
{
// 获取name元素下Text节点,然后从Text节点获取数据
person.setName(childNode.getFirstChild().getNodeValue());
}
else if ("age".equals(childNode.getNodeName()))
{
person.setAge(new Short(childNode.getFirstChild().getNodeValue()));
}
}
}
persons.add(person);
}
is.close();
}
catch (Exception e)
{
e.printStackTrace();
}
return persons;
}
3、pull方法
/**
* 除了可以使用 SAX和DOM解析XML文件,大家也可以使用Android内置的Pull解析器解析XML文件。
* Pull解析器的运行方式与 SAX 解析器相似。它提供了类似的事件,
* 如:开始元素和结束元素事件,使用parser.next()可以进入下一个元素并触发相应事件。
* 事件将作为数值代码被发送,因此可以使用一个switch对感兴趣的事件进行处理。当元素开始解析时,
* 调用parser.nextText()方法可以获取下一个Text类型元素的值。
*
* 但 Xml pull 比 Sax 更简明,而且不需要扫描完整个流。它通过使用 nextext 控制扫描进度
*
* @param is
* @return
*/
public List<Person> pullParser(InputStream is)
{
XmlPullParser parser = Xml.newPullParser();
try
{
parser.setInput(is, "UTF-8");
int eventType = parser.getEventType();
Person currentPerson = null;
List<Person> persons = null;
while (eventType != XmlPullParser.END_DOCUMENT)
{
switch (eventType)
{
case XmlPullParser.START_DOCUMENT:// 文档开始事件,可以进行数据初始化处理
persons = new ArrayList<Person>();
break;
case XmlPullParser.START_TAG:// 开始元素事件
String name = parser.getName();
if (name.equalsIgnoreCase("person"))
{
currentPerson = new Person();
currentPerson.setId(new Integer(parser.getAttributeValue(null, "id")));
}
else if (currentPerson != null)
{
if (name.equalsIgnoreCase("name"))
{
currentPerson.setName(parser.nextText());// 如果后面是Text元素,即返回它的值
}
else if (name.equalsIgnoreCase("age"))
{
currentPerson.setAge(new Short(parser.nextText()));
}
}
break;
case XmlPullParser.END_TAG:// 结束元素事件
if (parser.getName().equalsIgnoreCase("person") && currentPerson != null)
{
persons.add(currentPerson);
currentPerson = null;
}
break;
}
eventType = parser.next();
}
is.close();
return persons;
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
1、dom 需要读入保存整个文件,生成一颗document 数,然后可以从中选择需要的节点、属性;
2、sax 需要扫描整个文件,并且封装事件驱动
3、pull 不需要扫码整个文件,可以使用nextText控制扫码进度,也是事件驱动,但没有封装。