<?xml version="1.0" encoding="UTF-8"?>
<books>
<book id="12">
<name>thinking in java</name>
<price>85.5</price>
</book>
<book id="15">
<name>Spring in Action</name>
<price>39.0</price>
</book>
</books>
其中,像<books>、<book>这种节点就属于ElementNode,而thinking in java、85.5这种就属于TextNode。
下面结合一张图来详细讲解Sax解析。
xml文件被Sax解析器载入,由于Sax解析是按照xml文件的顺序来解析,当读入<?xml.....>时,会调用startDocument()方法,当读入<books>的时候,由于它是个ElementNode,所以会调用startElement(String uri, String localName, String qName, Attributes attributes) 方法,其中第二个参数就是节点的名称,注意:由于有些环境不一样,有时候第二个参数有可能为空,所以可以使用第三个参数,因此在解析前,先调用一下看哪个参数能用,第4个参数是这个节点的属性。这里我们不需要这个节点,所以从<book>这个节点开始,也就是图中1的位置,当读入时,调用startElement(....)方法,由于只有一个属性id,可以通过attributes.getValue(0)来得到,然后在图中标明2的地方会调用characters(char[] ch, int start, int length)方法,不要以为那里是空白,Sax解析器可不那么认为,Sax解析器会把它认为是一个TextNode。但是这个空白不是我们想要的数据,我们是想要<name>节点下的文本信息。这就要定义一个记录当上一节点的名称的TAG,在characters(.....)方法中,判断当前节点是不是name,是再取值,才能取到thinking in java。
ØAndroid中,解析Xml数据的三种方式:
第一种方法:SAX
- org.xml.sax.ContentHandler
- org.xml.sax.DocumentHandler
- org.xml.sax.DTDHandler
- org.xml.sax.EntityResolver
- org.xml.sax.ErrorHandler
- java.lang.Object
- javax.xml.parsers.DocumentBuilder
- javax.xml.parsers.DocumentBuilderFactory
- javax.xml.parsers.SAXParser
- javax.xml.parsers.SAXParserFactory
XMLReader 是 XML 解析器的 SAX2 驱动程序必须实现的接口。此接口允许应用程序设置和查询解析器中的功能和属性,注册文档处理的事件处理程序,以及开始文档解析。
此接口取代了(现在不推荐) SAX 1.0 Parser
接口。与旧的解析器接口(和某些监控器接口)相比,XMLReader 接口具有两大重要增强:
- 它增加了查询和设置功能和属性的标准方法;并且
- 增加了对名称空间的支持,这是许多高层的 XML 标准所必需的。
- org.xml.sax.AttributeList
- org.xml.sax.Attributes
- org.xml.sax.ContentHandler
- org.xml.sax.DocumentHandler
- org.xml.sax.DTDHandler
- org.xml.sax.EntityResolver
- org.xml.sax.ErrorHandler
- org.xml.sax.Locator
- org.xml.sax.Parser
- org.xml.sax.XMLReader
- org.xml.sax.XMLFilter
方法摘要 | |
---|---|
ContentHandler | getContentHandler() 返回当前的内容处理程序。 |
DTDHandler | getDTDHandler() 返回当前的 DTD 处理程序。 |
EntityResolver | getEntityResolver() 返回当前的实体解析器。 |
ErrorHandler | getErrorHandler() 返回当前的错误处理程序。 |
boolean | getFeature(String name) 查找功能标志的值。 |
Object | getProperty(String name) 查找属性的值。 |
void | parse(InputSource input) 解析 XML 文档。 |
void | parse(String systemId) 从系统标识符 (URI) 解析 XML 文档。 |
package com.sax.test;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import com.sax.http.HttpUtils;
import com.sax.service.SaxService;
public class Test {
public Test() {
// TODO Auto-generated constructor stub
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
String path = "http://192.168.0.101:8080/myhttp/person.xml";
InputStream inputStream = HttpUtils.getXML(path);
if(inputStream==null){
System.out.println("sss");//说明输入流为null
}
try {
List<HashMap<String, String>> list = SaxService.readXML(
inputStream, "person");
for (HashMap<String, String> map : list) {
System.out.println(map.toString());
}
} catch (Exception e) {
// TODO: handle exception
}
}
}
SaxService.java
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser parser = spf.newSAXParser();// 解析xml
MyHandler handler = new MyHandler(nodeName);
parser.parse(inputStream, handler);
package com.sax.service;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import com.sax.handler.MyHandler;
public class SaxService {
public SaxService() {
// TODO Auto-generated constructor stub
}
public static List<HashMap<String, String>> readXML(
InputStream inputStream, String nodeName) {
try {
// 创建一个解析xml的工厂对象
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser parser = spf.newSAXParser();// 解析xml
MyHandler handler = new MyHandler(nodeName);
parser.parse(inputStream, handler);
inputStream.close();
return handler.getList();
} catch (Exception e) {
// TODO: handle exception
}
return null;
}
}
MyHandler.java
package com.sax.handler;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.jar.Attributes.Name;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class MyHandler extends DefaultHandler {
private HashMap<String, String> map = null;// 存储单个解析的完整对象
private List<HashMap<String, String>> list = null;// 存储所有的解析对象
private String currentTag = null;// 正在解析的元素的标签
private String currentValue = null;// 解析当前元素的值
private String nodeName = null;// 解析当前的节点名称
public MyHandler(String nodeName) {
// TODO Auto-generated constructor stub
this.nodeName = nodeName;
}
public List<HashMap<String, String>> getList() {
return list;
}
@Override
public void startDocument() throws SAXException {
// TODO Auto-generated method stub
// 当读到第一个开始标签的时候,会触发这个方法
list = new ArrayList<HashMap<String, String>>();
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
// 当遇到文档的开头的时候,调用这个方法
System.out.println("-->>startElement "+qName);
if (qName.equals(nodeName)) {
map = new HashMap<String, String>();
if (attributes != null && map != null) {
for (int i = 0; i < attributes.getLength(); i++) {
map.put(attributes.getQName(i), attributes.getValue(i));
}
}
System.out.println(map.toString());
}
currentTag = qName;
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
// TODO Auto-generated method stub
// 这个方法是用来处理xml文件所读取到的内容
System.out.println("characters-->>"+ch.toString());
if(currentTag== null){
System.out.println("-->>当前节点为空");
}else{
System.out.println("-->>当前节点为"+currentTag);
}
if (currentTag != null && map != null) {
currentValue = new String(ch, start, length);
if (currentValue != null && !currentValue.trim().equals("")
&& !currentValue.trim().equals("\n")) {
map.put(currentTag, currentValue);
}
}
currentTag = null;// 把当前的节点的对应的值和标签设置为空
currentValue = null;
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
// TODO Auto-generated method stub
// 遇到结束标记的时候,会调用这个方法
if (qName.equals(nodeName)) {
list.add(map);
map = null;
}
super.endElement(uri, localName, qName);
}
}
package com.sax.http;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class HttpUtils {
public HttpUtils() {
// TODO Auto-generated constructor stub
}
public static InputStream getXML(String path) {
InputStream inputStream = null;
try {
URL url = new URL(path);
if (url != null) {
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setConnectTimeout(3000);
connection.setDoInput(true);
connection.setRequestMethod("GET");
int code = connection.getResponseCode();
if (code == 200) {
inputStream = connection.getInputStream();
}
}
} catch (Exception e) {
// TODO: handle exception
}
return inputStream;
}
}
执行结果:
-->>startElement persons
characters-->>[C@1ef3212
-->>当前节点为persons
-->>startElement person
{id=23}
characters-->>[C@1ef3212
-->>当前节点为person
-->>startElement name
characters-->>[C@1ef3212
-->>当前节点为name
characters-->>[C@1ef3212
-->>当前节点为空
-->>startElement age
characters-->>[C@1ef3212
-->>当前节点为age
characters-->>[C@1ef3212
-->>当前节点为空
characters-->>[C@1ef3212
-->>当前节点为空
-->>startElement person
{id=20}
characters-->>[C@1ef3212
-->>当前节点为person
-->>startElement name
characters-->>[C@1ef3212
-->>当前节点为name
characters-->>[C@1ef3212
-->>当前节点为空
-->>startElement age
characters-->>[C@1ef3212
-->>当前节点为age
characters-->>[C@1ef3212
-->>当前节点为空
characters-->>[C@1ef3212
-->>当前节点为空
{id=23, age=21, name=张老师}
{id=20, age=25, name=李老师}
说明: