java解析XML之DOM解析和SAX解析(包含CDATA的問題)
阿新 • • 發佈:2019-01-26
Dom解析功能強大,可增刪改查,操作時會將XML文件讀到記憶體,因此適用於小文件;
SAX解析是從頭到尾逐行逐個元素解析,修改較為不便,但適用於只讀的大文件;SAX採用事件驅動的方式解析XML。如同在電影院看電影一樣,從頭到尾看一遍,不能回退(Dom可來來回回讀取),在看電影的過程中,每遇到一個情節,都會呼叫大腦去接收處理這些資訊。SAX也是相同的原理,每遇到一個元素節點,都會呼叫相應的方法來處理。在SAX的解析過程中,讀取到文件開頭、文件結尾,元素的開頭和元素結尾都會呼叫相應方法,我們可以在這些方法中進行相應事件處理。
github專案地址:https://github.com/Snailclimb/XML
Students.xml
<?xml version="1.0" encoding="utf-8"?>
<Students>
<Student num="001">
<name>小明</name>
<age>20</age>
<subject><![CDATA[數學&英語]]></subject>
<sport>籃球</sport>
</Student>
<Student num="002">
<name>小紅</name>
<age>21</age>
<subject><![CDATA[數學&英語]]></subject>
<sport>籃球</sport>
</Student>
<Student num="003">
<name>小藍</name>
<age>23</age>
<subject ><![CDATA[數學&英語]]></subject>
<sport>籃球</sport>
</Student>
<Student num="004">
<name>小白</name>
<age>19</age>
<subject><![CDATA[數學&英語]]></subject>
<sport>籃球</sport>
</Student>
<Student num="005">
<name>小林子</name>
<age>18</age>
<subject><![CDATA[數學&英語]]></subject>
<sport>籃球</sport>
</Student>
<Student num="006">
<name>小東子</name>
<age>20</age>
<subject><![CDATA[數學&英語]]></subject>
<sport>籃球</sport>
</Student>
<Student num="007">
<name>小左子</name>
<age>21</age>
<subject><![CDATA[數學&英語]]></subject>
<sport>籃球</sport>
</Student>
<Student num="008">
<name>小張</name>
<age>22</age>
<subject><![CDATA[數學&英語]]></subject>
</Student>
<Student num="009">
<name>小明</name>
<age>23</age>
<subject><![CDATA[數學&英語]]></subject>
<sport>籃球</sport>
</Student>
<Student num="010">
<name>小明</name>
<age>20</age>
<subject><![CDATA[數學&英語]]></subject>
<sport>籃球</sport>
</Student>
</Students>
DOM解析
package cn.yangtze.domtext;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class DomPractice {
public static void main(String[] args) {
// TODO Auto-generated method stub
// 建立一個DocumentBuilderFactory的物件
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
// 建立一個DocumentBuilder的物件
try {
// 建立DocumentBuilder物件
DocumentBuilder db = dbf.newDocumentBuilder();
// 通過DocumentBuilder物件的parser方法載入books.xml檔案到當前專案下
Document document = db.parse("Students.xml");
// 獲取所有Student節點的集合
NodeList StudentList = document.getElementsByTagName("Student");
// 通過nodelist的getLength()方法可以獲取StudentList的長度
System.out.println("DOM解析開始...");
// 遍歷每一個Student節點
for (int i = 0; i < StudentList.getLength(); i++) {
System.out.println("開始解析第" + (i + 1) + "個學生");
// 通過 item(i)方法 獲取一個Student節點,nodelist的索引值從0開始
Node book = StudentList.item(i);
// 獲取Student節點的所有屬性集合
NamedNodeMap attrs = book.getAttributes();
// 遍歷Student的屬性
for (int j = 0; j < attrs.getLength(); j++) {
// 通過item(index)方法獲取Student節點的某一個屬性
Node attr = attrs.item(j);
// 輸出學生的屬性名和屬性值
System.out.println(attr.getNodeName() + ":" + attr.getNodeValue());
}
NodeList childNodes = book.getChildNodes();
// 遍歷childNodes獲取每個節點的節點名和節點值
for (int k = 0; k < childNodes.getLength(); k++) {
// 區分出text型別的node以及element型別的node
if (childNodes.item(k).getNodeType() == Node.ELEMENT_NODE) {
// 輸出子節點的屬性名和屬性值
System.out.println(childNodes.item(k).getNodeName() + ":"
+ childNodes.item(k).getFirstChild().getNodeValue());
}
}
}
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("DOM解析結束...");
}
}
SAX解析
SAXParserHandler.java
package cn.yangtze.saxtext;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class SAXParserHandler extends DefaultHandler {
private int StudentIndex = 0;
// 解析開始的標誌
@Override
public void startDocument() throws SAXException {
System.out.println("SAX解析開始...");
}
// 解析結束的標誌
@Override
public void endDocument() throws SAXException {
System.out.println("SAX解析結束...");
}
// 用來遍歷XML檔案的開始標籤
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
// 呼叫DefaultHandler類的startElement方法
super.startElement(uri, localName, qName, attributes);
// 開始解析Student元素節點
if (qName.equals("Student")) {
++StudentIndex;
System.out.println("開始解析第" + StudentIndex + "個學生");
//輸出XML屬性,也就是XML檔案中的num屬性,注意在因使用屬性而引起的一些問題:
/*1 ,屬性無法包含多重的值(元素可以)
2,屬性無法描述樹結構(元素可以)
3,屬性不易擴充套件(為未來的變化)
4,屬性難以閱讀和維護
5,請儘量使用元素來描述資料。而僅僅使用屬性來提供與資料無關的資訊。*/
for (int i = 0; i < attributes.getLength(); ++i) {
System.out.println(attributes.getQName(i) + ":" + attributes.getValue(i));
}
} else if (!qName.equals("Students")) {
System.out.print(qName + ":");//輸出元素值
}
}
// 用來遍歷XML檔案的結束標籤
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
// 判斷一個學生是否解析完
if (qName.equals("Student")) {
System.out.println("結束解析第" + StudentIndex + "個學生");
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
super.characters(ch, start, length);
String text = new String(ch, start, length);
if (!text.trim().equals("")) {
System.out.println(text);
} // if
}
}
SAXDemo.java
//SAX解析XML
package cn.yangtze.saxtext;
import java.io.File;
import java.io.IOException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.SAXException;
public class SAXDemo {
public static void main(String[] args) {
File file =new File("Students.xml");
try {
// 通過SAXParserFactory的靜態方法newInstance()方法獲取SAXParserFactory例項物件factory
SAXParserFactory factory = SAXParserFactory.newInstance();
// 通過SAXParserFactory例項的newSAXParser()方法返回SAXParser例項parser
SAXParser saxParser = factory.newSAXParser();
// 定義SAXParserHandler物件
SAXParserHandler handler = new SAXParserHandler();
// 解析XML文件
saxParser.parse(file, handler);
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}