对数据进行标记(结构化数据)、存储 & 传输
XML文档中的元素会形成一种树结构,从根部开始,然后拓展到每个树叶(节点),下面将以实例说明XML的树结构。
<?xml version="1.0" encoding="utf-8"?>
<classes><!--根节点 -->
<student id="0">
<name>Av</name>
<age>23</age>
<sax>男</sax>
<Courses>
<course name="语文" score="90"/>
<course name="数学" score="78"/>
</Courses>
</student>
<student id="1">
<name>Lance</name>
<age>22</age>
<sax>男</sax>
<Courses>
<course name="语文" score="59"/>
<course name="数学" score="38"/>
</Courses>
</student>
</classes>
树形结构
XML节点解释
XML文件是由节点构成的。它的第一个节点为“根节点”。一个XML文件必须有且只能有一个根节点,其他节点都必须是它的子节点,每个子节点又可以有自己的子节点。
解析XML,即从XML中提取有用的信息
XML的解析方式主要分为2大类:
| 解析方式 | 原理 | 类型 |
|---|---|---|
| 基于文档驱动 | 在解析XML文档前,需先将整个XML文档加载到内存中 | DOM方式 |
| 基于事件驱动 | 根据不同需求事件(检索,修改,删除等)去执行不同解析操作(不需要把整个XML 文档加载到内存中) | SAX方式,PULL方式 |
Document Object Model,即 文件对象模型,是 一种 基于树形结构节点 & 文档驱动 的XML解析方法,它定义了访问 & 操作xml文档元素的方法和接口
public void domTest(Context context) {
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document document = db.parse(context.getResources().openRawResource(R.raw.students));
//通过Document对象的getElementsByTagName()返根节点的一个list集合
NodeList studentList = document.getElementsByTagName("student");
for (int i = 0; i < studentList.getLength(); i++) {
Student student = new Student();
//循环遍历获取每一个student
Node studentNode = studentList.item(i);
if (((Element) studentNode).hasAttribute("id")) {
student.setId(Integer.parseInt(((Element) studentNode).getAttribute("id")));
}
//解析student节点的子节点
NodeList childList = studentNode.getChildNodes();
for (int t = 0; t < childList.getLength(); t++) {
//区分出text类型的node以及element类型的node
if (childList.item(t).getNodeType() == Node.ELEMENT_NODE) {
if (childList.item(t).getNodeName().equalsIgnoreCase("Courses")) {
NodeList courses = childList.item(t).getChildNodes();
for (int j = 0; j < courses.getLength(); j++) {
Node courseNode = courses.item(j);
if (courseNode.getNodeType() != Node.ELEMENT_NODE) {
continue;
}
NamedNodeMap namedNodeMap = courseNode.getAttributes();
Course course = new Course();
student.addCourse(course);
for (int k = 0; k < namedNodeMap.getLength(); k++) {
Node courseAttr = namedNodeMap.item(k);
if (courseAttr.getNodeName().equals("name")) {
course.setName(courseAttr.getNodeValue());
} else if (courseAttr.getNodeName().equals("score")) {
course.setScore(Float.parseFloat(courseAttr.getNodeValue()));
}
}
}
} else {
Node child = childList.item(t);
if (child.getNodeName().equals("name")) {
student.setName(child.getTextContent());
} else if (child.getNodeName().equals("age")) {
student.setAge(Integer.parseInt(child.getTextContent()));
} else if (child.getNodeName().equals("sax")) {
student.setSax(child.getTextContent());
}
}
}
}
Log.i("Zero", "解析完毕: " + student);
}
} catch (ParserConfigurationException | SAXException | IOException e) {
Log.e("Zero", e.getMessage());
}
}
即 Simple API for XML,一种 基于事件流驱动、通过接口方法解析 的XML解析方法
核心思想
基于事件流驱动,根据不同需求事件(检索,修改,删除等)去执行不同解析操作,不需要把整个XML 文档加载到内存中
解析过程
startDocument() startElement() characters() endElement() endDocument()
public void saxTest(Context context) throws Exception {
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
sp.parse(context.getResources().openRawResource(R.raw.students), new DefaultHandler() {
String currentTag = null;
Student student = null;
/**
* 文档解析开始时被调用
* @throws SAXException
*/
@Override
public void startDocument() throws SAXException {
super.startDocument();
}
/**
* 文档解析结束时被调用
* @throws SAXException
*/
@Override
public void endDocument() throws SAXException {
super.endDocument();
}
/**
*
* @param uri 命名空间
* @param localName 不带命名空间前缀的标签名
* @param qName 带命名空间的标签名
* @param attributes 标签的属性集合 <student id="0"></student>
* @throws SAXException
*/
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
currentTag = localName;
if ("student".equals(currentTag)) {
student = new Student();
student.setId(Integer.parseInt(attributes.getValue("id")));
}
if ("course".equals(currentTag)) {
if (student != null) {
Course course = new Course();
course.setName(attributes.getValue("name"));
course.setScore(Float.parseFloat(attributes.getValue("score")));
student.addCourse(course);
}
}
}
/**
* 解析到结束标签时被调用 '/>'
* @param uri
* @param localName
* @param qName
* @throws SAXException
*/
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
if ("student".equals(localName)) {
Log.i(TAG, "endElement: student: " + student);
}
}
/**
*
* @param ch 内容
* @param start 起始位置
* @param length 长度
* @throws SAXException
*/
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
super.characters(ch, start, length);
String str = new String(ch, start, length).trim();
if (TextUtils.isEmpty(str))
return;
if ("name".equals(currentTag) && student != null) {
student.setName(str);
}
if ("age".equals(currentTag)&& student != null) {
student.setAge(Integer.parseInt(str));
}
if ("sax".equals(currentTag) && student != null) {
student.setSax(str);
}
}
});
}
一种 基于事件流驱动 的XML解析方法,是Android系统特有的解析方式
基于事件流驱动,根据不同需求事件(检索,修改,删除等)去执行不同解析操作,不需要把整个XML 文档加载到内存中
public void pullTest(Context context) throws Exception {
XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
parser.setInput(context.getResources().openRawResource(R.raw.students), "utf-8");//设置数据源编码
int eventCode = parser.getEventType();//获取事件类型
Student student = null;
while (eventCode != XmlPullParser.END_DOCUMENT) {
switch (eventCode) {
case XmlPullParser.START_DOCUMENT://开始读取XML文档
break;
case XmlPullParser.START_TAG://开始读取标签
String name = parser.getName();
if ("student".equals(name)) {
student = new Student();
student.setId(Integer.parseInt(parser.getAttributeValue(null, "id")));
}
if ("name".equals(name) && student != null) {
student.setName(parser.nextText());
}
if ("age".equals(name) && student != null) {
student.setAge(Integer.parseInt(parser.nextText().trim()));
}
if ("sax".equals(name) && student != null) {
student.setSax(parser.nextText());
}
if ("course".equals(name) && student != null) {
Course course = new Course();
course.setName(parser.getAttributeValue(null, "name"));
course.setScore(Float.parseFloat(parser.getAttributeValue(null, "score")));
student.addCourse(course);
}
break;
case XmlPullParser.END_TAG://结束原始事件
if ("student".equals(parser.getName())) {
Log.i(TAG, "pullTest: student: " + student);
}
break;
}
eventCode = parser.next();
}
}