什么是 XML?
- XML 指可擴展標記語言(EXtensible Markup Language)
- XML 是一種標記語言,很類似 HTML
- XML 的設計宗旨是傳輸數據,而非顯示數據
- XML 標簽沒有被預定義。您需要自行定義標簽。
- XML 被設計為具有自我描述性。
- XML 是 W3C 的推薦標准
對於xml文件,沒有被定義好的標簽,所有的標簽都是用戶自己定義,在讀取解析的時候,根據標簽可以獲得想要的值
解析xml文件一共有四種方式,分別是:
- DOM
- SAX
- JDOM
- DOM4J
下面詳細的介紹這幾種方式:
一、DOM(Document Object Model)
Dom解析是將xml文件全部載入,組裝成一顆DOM樹(樹狀結構),然后通過節點以及節點之間的關系來解析xml文件,下面結合這個xml文件來進行dom解析。由於DOM這種在加載的時候需要把文件全部加載進內存才可以進行解析的方式,也帶來了問題,在xml文件小的情況下可以使用,當一個xml文件相當大的時候,對計算機資源的消耗也是一個不小的開銷
xml文件:
<school>
<student>
<no>1001</no>
<name>小明</name>
<score>20</score>
</student>
<student>
<no>1002</no>
<name>小紅</name>
<score>80</score>
</student>
</school>
實例:
package demo_xml;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
public class Dom {
public static void main(String[] args) {
try {
//創建解析器
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
//把xml文件加載進內存
Document document = db.parse("E:\\IntelliJ IDEA\\jvm\\src\\test.xml");
//獲取文件中的根節點
NodeList root = document.getChildNodes();
for (int i = 0; i < root.getLength(); i++) {
Node childNodes = root.item(i);
//通過根節點獲取子節點
NodeList childNodes1 = childNodes.getChildNodes();
for (int j = 0; j < childNodes1.getLength(); j++) {
Node node = childNodes1.item(j);
//獲取子節點的子節點
NodeList value = node.getChildNodes();
//遍歷各個節點的屬性值
for (int k = 0; k < value.getLength(); k++) {
if(value.item(k).getNodeName() != "#text") {
System.out.println(value.item(k).getNodeName()
+ ":" + value.item(k).getTextContent());
}
}
System.out.println();
}
}
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
二、SAX(Simple API for XML)
sax這種解析方式在官方的解釋是類似於流媒體的方式。我們可以簡單的總結為,sax方式可以做到一邊掃面文檔,一邊解析文檔,不用把文件加載到內存中,相比於DOM解析方式,SAX方式對於大型的文件是一種很好的解決辦法,減少了對內存的消耗。還有就是SAX解析方式是一種基於事件的方式,在解析xml文件的時候就是觸發了一系列的事件,當遇到用戶給定的標簽的時候,會停止解析,這樣在時間和空間上都是優於DOM解析的(DOM解析需要把文檔全部加載進內存才能開始解析)
要使用SAX解析首先要創建觸發器這個類,要創建這個類首先需要繼承DefaultHandler,重寫方法
xml文件被SAX解析器載入,由於SAX解析是按照xml文件的順序來解析,當最開始讀取xml文檔的時候,會調用startDocument()方法,當讀入<school>的時候,由於它是個ElementNode,所以會調用startElement(String uri, String localName, String qName, Attributes attributes) 方法,其中第二個參數就是節點的名稱,注意:由於有些環境不一樣,有時候第二個參數有可能為空,所以可以使用第三個參數,因此在解析前,先調用一下看哪個參數能用,第4個參數是這個節點的屬性。這里我們不需要這個節點,所以從<student>這個節點開始,當讀入時,調用startElement(....)方法,然后在no標簽的地方會調用characters(char[] ch, int start, int length)方法,Sax解析器會把它認為是一個TextNode。但是這個空白不是我們想要的數據,我們是想要<no>節點下的文本信息。這就要定義一個記錄當上一節點的名稱的TAG,在characters(.....)方法中,判斷當前節點是不是name,是再取值,才能取到值

代碼:
package demo_xml;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
public class Sax {
public static void parserXml(String fileName) {
SAXParserFactory saxfac = SAXParserFactory.newInstance();
try {
SAXParser saxparser = saxfac.newSAXParser();
InputStream is = new FileInputStream(fileName);
saxparser.parse(is, new MySaxHandler());
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Sax.parserXml("E:\\IntelliJ IDEA\\jvm\\src\\test.xml");
}
}
class MySaxHandler extends DefaultHandler {
boolean hasAttribute = false;
Attributes attributes = null;
@Override
public void startDocument() throws SAXException {
System.out.println("文檔解析");
}
@Override
public void endDocument() throws SAXException {
System.out.println("文檔結束");
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if (qName.equals("users")) {
return;
}
if (qName.equals("user")) {
return;
}
if (attributes.getLength() > 0) {
this.attributes = attributes;
this.hasAttribute = true;
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if (hasAttribute && (attributes != null)) {
for (int i = 0; i < attributes.getLength(); i++) {
System.out.print(attributes.getQName(0) + ":"
+ attributes.getValue(0));
}
}
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
System.out.print(new String(ch, start, length));
}
}
三、JDOM(Java-based Document Object Model)
JDOM也是將xml文件構建成一個樹狀結構,實現解析,所以代碼和DOM很像,但是 JDOM自身不包含解析器。它通常使用SAX2解析器來解析和驗證輸入XML文檔,所以可以說JDOM是DOM和SAX的一個結合體也差不多,把SAX和DOM的功能有效地結合起來。實現了解析xml文檔的功能。在代碼中我們可以看到SAX和DOM解析代碼的片段
package demo_xml;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import java.util.List;
public class Jdom {
public static void main(String[] args) throws Exception {
//構建加載器,加載xml文檔
SAXBuilder builder = new SAXBuilder();
Document document = builder.build("E:\\IntelliJ IDEA\\jvm\\src\\test.xml");
//獲取根節點
Element root = document.getRootElement();
//通過根節點獲取子節點的集合
List childList = root.getChildren("student");
//遍歷集合
for (int i = 0; i < childList.size(); i++) {
Element childs = (Element) childList.get(i);
//通過上一級節點獲取子節點
List child = childs.getChildren();
for (int j = 0; j < child.size(); j++) {
System.out.println(((Element) child.get(j)).getName()
+ ":" + ((Element) child.get(j)).getValue());
}
System.out.println();
}
}
}
四、DOM4J(Document Object Model for Java)
DOM4J是目前使用最廣泛的,hibernate框架使用的解析方式就是DOM4J,DOM4J使用接口和抽象基本類方法,在代碼上也容易理解(在使用DOM4J時需要下載jar包)
package demo_xml;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.File;
import java.net.MalformedURLException;
import java.util.Iterator;
public class Dom4j {
public static void main(String[] args) {
//加載解析器
File inputXml = new File("E:\\IntelliJ IDEA\\jvm\\src\\test.xml");
SAXReader saxReader = new SAXReader();
try {
//獲取文檔內容
Document document = saxReader.read(inputXml);
//獲取根節點
Element root = document.getRootElement();
for (Iterator i = root.elementIterator(); i.hasNext();) {
Element childList = (Element) i.next();
for (Iterator j = childList.elementIterator(); j.hasNext();) {
Element node = (Element) j.next();
System.out.println(node.getName() + ":" + node.getText());
}
System.out.println();
}
} catch (DocumentException e) {
System.out.println(e.getMessage());
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}
