我的GitHub | 我的博客 | 我的微信 | 我的郵箱 |
---|---|---|---|
baiqiantao | baiqiantao | bqt20094 | baiqiantao@sina.com |
目錄
目錄
XML 解析 總結 DOM SAX PULL MD
JDOM 倉庫地址
DOM4j 倉庫地址
XmlPull 倉庫地址
Android 中默認已經引入 XmlPull,如果需要自己引入,需要同時添加以下兩個jar包:
幾種解析方式簡介
- DOM 方式解析:將xml文件全部載入到內存,組裝成一棵dom樹,然后通過節點以及節點之間的關系來解析xml文件;理解較簡單,但是由於整個文檔都需要載入內存,不適用於文檔較大時。
- SAX 方式解析:基於事件驅動,逐條解析,適用於只處理xml數據;不易編碼,而且很難同時訪問同一個文檔中的多處不同數據。
- JDOM 方式解析:主要用來彌補 DOM 和 SAX 在實際應用當中的不足,比使用 DOM 實現更快,僅使用具體類而不使用接口,因此簡化了API,並且易於使用。
- DOM4j 方式解析:JDOM的一種智能分支,功能較強大,建議熟練使用。
- Pull 方式解析:Android提供的一種解析方式,與 SAX 解析器相似,基於事件驅動逐條解析,但需要使用
parser.next()
方法來提取它們。
Pull 解析和 Sax 解析比較
- Pull 解析和 Sax 解析在運行方式上具有相似性,Pull 解析器也提供了類似 SAX 的事件,開始文檔
START_DOCUMENT
和結束文檔END_DOCUMENT
,開始元素START_TAG
和結束元素END_TAG
等,但需要調用next()
方法提取它們(主動提取事件)。 - SAX 解析器的工作方式是自動將事件推入注冊的事件處理器進行處理,因此你不能控制事件的處理主動結束;而Pull解析器的工作方式為允許你的應用程序代碼主動從解析器中獲取事件,正因為是主動獲取事件,因此可以在滿足了需要的條件后不再獲取事件,結束解析。這是他們主要的區別。
- 即:SAX 解析會對整個文檔進行解析,而 Pull 解析可以在程序中控制解析到哪里就可以中途停止。
要解析的內容
<?xml version="1.0" encoding="utf-8"?>
<class>
<string name="user">包青天</string>
<string name="job" id="10086">Android開發</string>
<student id="10010">
<string name="user">白乾濤</string>
<string name="job" id="100">碼農</string>
</student>
</class>
DOM 解析
代碼
public static void domParseXml(String path) throws Exception {
System.out.println("-------------------- DOM解析 --------------------");
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(path);
NodeList stringList = document.getElementsByTagName("string");
domParseNode(stringList); //長度為4【user:包青天, null】【job:Android開發, 10086】【user:白乾濤, null】【job:碼農, 100】
NodeList studentList = document.getElementsByTagName("student");
System.out.println("【" + studentList.getLength() + "】");
for (int i = 0; i < studentList.getLength(); i++) {
NamedNodeMap map = studentList.item(i).getAttributes();
String id = map != null && map.getNamedItem("id") != null ? map.getNamedItem("id").getNodeValue() : null;
System.out.println("id = " + id);
NodeList childNodeList = studentList.item(i).getChildNodes();
domParseNode(childNodeList); //長度為5(而不是2)【user:白乾濤, null】【job:碼農, 100】
}
}
private static void domParseNode(@NotNull NodeList nodeList) {
System.out.println("【" + nodeList.getLength() + "】");
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i); //獲取第i個節點
if (node != null && node.getFirstChild() != null) {
NamedNodeMap map = node.getAttributes(); //獲取此節點的所有屬性
if (map != null) {
Node nameNode = map.getNamedItem("name"); //獲取名為name的屬性
String nameNodeValue = nameNode != null ? nameNode.getNodeValue() : null; //獲取屬性的屬性值,也可以使用getTextContent
String nodeValue = node.getFirstChild().getNodeValue(); //獲取節點的值
Node idNode = map.getNamedItem("id"); //獲取名為id的屬性
String idNodeValue = idNode != null ? idNode.getNodeValue() : null;
System.out.println(nameNodeValue + ":" + nodeValue + ", " + idNodeValue);
}
}
}
}
輸出
-------------------- DOM 解析 --------------------
【4】
user:包青天, null
job:Android開發, 10086
user:白乾濤, null
job:碼農, 100
【1】
id = 10010
【5】
user:白乾濤, null
job:碼農, 100
SAX 解析
代碼
System.out.println("-------------------- SAX解析 --------------------");
SAXParserFactory.newInstance().newSAXParser().parse(path, new SAXParseHandel());
SAXParseHandel
public class SAXParseHandel extends DefaultHandler {
@Override
public void startDocument() throws SAXException {
super.startDocument();
System.out.println("開始解析");
}
@Override
public void endDocument() throws SAXException {
super.endDocument();
System.out.println("結束解析");
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
//開始解析節點時調用此方法
System.out.println("開始解析" + qName);
for (int i = 0; i < attributes.getLength(); i++) {
System.out.println(" " + attributes.getQName(i) + ":" + attributes.getValue(i));//此案例中:getLocalName和getQName一致 ,getType的值為CDATA
}
switch (qName) {
case "student":
int index = attributes.getIndex("id");//當節點名為student時,獲取student的id屬性
System.out.println(" --" + attributes.getQName(index) + ":" + attributes.getValue(index));
break;
case "string":
System.out.print(" -" + attributes.getValue(attributes.getIndex("name")) + ":");
break;
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
//節點解析完畢時調用此方法
System.out.println("結束解析" + qName);
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
super.characters(ch, start, length);
//此方法用來獲取節點的值
String value = new String(ch, start, length).trim();
if (!value.equals("")) {
System.out.println(value);
}
}
}
輸出
-------------------- SAX 解析 --------------------
開始解析
開始解析class
開始解析string
name:user
-user:包青天
結束解析string
開始解析string
name:job
id:10086
-job:Android開發
結束解析string
開始解析student
id:10010
--id:10010
開始解析string
name:user
-user:白乾濤
結束解析string
開始解析string
name:job
id:100
-job:碼農
結束解析string
結束解析student
結束解析class
結束解析
JDOM 解析
代碼
public static void jdomParseXml(String path) throws Exception {
System.out.println("-------------------- JDOM解析 --------------------");
org.jdom2.Document document = new SAXBuilder().build(path);
List<org.jdom2.Element> elementList = document.getRootElement().getChildren();
for (org.jdom2.Element element : elementList) {
jdomParseNode(element);
//解析子節點
for (org.jdom2.Element chileElement : element.getChildren()) {
jdomParseNode(chileElement);
}
}
}
private static void jdomParseNode(@NotNull org.jdom2.Element element) {
System.out.println(element.getName() + ":" + element.getTextTrim());
//解析屬性
List<org.jdom2.Attribute> attributeList = element.getAttributes();
for (org.jdom2.Attribute attribute : attributeList) {
System.out.println(" " + attribute.getName() + ":" + attribute.getValue());
}
}
輸出
-------------------- JDOM 解析 --------------------
string:包青天
name:user
string:Android開發
name:job
id:10086
student:
id:10010
string:白乾濤
name:user
string:碼農
name:job
id:100
DOM4J 解析
代碼
public static void dom4JParseXml(String path) throws Exception {
System.out.println("-------------------- DOM4J解析 --------------------");
org.dom4j.Document document = new SAXReader().read(path);
Iterator iterator = document.getRootElement().elementIterator();
while (iterator.hasNext()) {
org.dom4j.Element element = (org.dom4j.Element) iterator.next();
dom4JParseNode(element);
//遍歷子節點
Iterator childIterator = element.elementIterator();
while (childIterator.hasNext()) {
dom4JParseNode((org.dom4j.Element) childIterator.next());
}
}
}
private static void dom4JParseNode(@NotNull org.dom4j.Element element) {
System.out.println(element.getName() + ":" + element.getTextTrim());
//解析屬性
for (Object object : element.attributes()) {
org.dom4j.Attribute attribute = (org.dom4j.Attribute) object;
System.out.println(" " + attribute.getName() + ":" + attribute.getValue());
}
}
輸出
-------------------- DOM4J 解析 --------------------
string:包青天
name:user
string:Android開發
name:job
id:10086
student:
id:10010
string:白乾濤
name:user
string:碼農
name:job
id:100
PULL 解析
代碼
public static void pullParseXml(String path) throws Exception {
System.out.println("-------------------- PULL解析 --------------------");
InputStream inputStream = new FileInputStream(path);
XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
parser.setInput(inputStream, "UTF-8");
int eventType = parser.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) { //文檔結束
switch (eventType) {
case XmlPullParser.START_TAG://開始標簽
String name = parser.getName();
System.out.println("開始解析 " + name + ", 行列:" + parser.getLineNumber() + "-" + parser.getColumnNumber() + ", 深度:" + parser.getDepth());
for (int i = 0; i < parser.getAttributeCount(); i++) {
//getAttributeType為【CDATA】,getAttributePrefix為【null】,getAttributeNamespace為空【】
System.out.println(" " + parser.getAttributeName(i) + ":" + parser.getAttributeValue(i));//屬性名及屬性值
}
if ("string".equals(name)) {
System.out.println(parser.nextText()); //獲取節點的值
}
break;
case XmlPullParser.END_TAG://結束標簽
System.out.println("結束解析" + parser.getName());
break;
}
eventType = parser.next();//這一步很重要,該方法返回一個事件碼,也是觸發下一個事件的方法
}
}
輸出
-------------------- PULL 解析 --------------------
開始解析 class, 行列:2-8, 深度:1
開始解析 string, 行列:3-23, 深度:2
name:user
包青天
開始解析 string, 行列:4-33, 深度:2
name:job
id:10086
Android開發
開始解析 student, 行列:5-23, 深度:2
id:10010
開始解析 string, 行列:6-25, 深度:3
name:user
白乾濤
開始解析 string, 行列:7-33, 深度:3
name:job
id:100
碼農
結束解析student
結束解析class
2019-11-23