DOM解析:
DOM解析XML的概述:
DOM解析優點:
整個文檔樹在內存中,便於操作;
可以修改,刪除、重新排列XML;
可以隨機訪問任何一個節點,訪問效率高。
DOM解析的缺點:
佔用內存大,佔用資源多
解析速度慢
DOM解析適用場合:
需多次訪問這些數據;
對解析效率要求不高;
硬件資源充足(內存、CPU)。
DOM解析XML文件的步驟:
// 1、 獲取解析器類工廠
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// 2、根據解析器工廠獲得解析器
DocumentBuilder db = factory.newDocumentBuilder();
// 3、根據解析器獲得document對象
Document document = db.parse("dtd/books.xml");//根據自己的XML文件路徑填寫
得到了DOCUMENT對象document,就相當於得到了整個xml文件
接下來通過代碼進行實例的分析:
books.xml:
<?xml version="1.0" encoding="gbk" standalone="no"?><books>
<book language="zh">
<name>紅樓夢</name>
<author>曹雪芹</author>
<price>76</price>
</book>
<book language="en">
<name>西遊記</name>
<author>吳承恩</author>
<price>89</price>
</book>
</books>
DOM方式解析XML(通過簡單的獲取元素和屬性):
public class Demo1 {
@Test
public void Test() {
// 1、 獲取解析器類工廠
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// 2、根據解析器工廠獲得解析器
try {
DocumentBuilder db = factory.newDocumentBuilder();
// 3、根據解析器獲得document對象
Document document = db.parse("dtd/books.xml");
// 根據document對象獲得節點值
NodeList nodes1 = document.getElementsByTagName("book");// 根據節點的元素名獲取元素,返回的book節點可能不只一個,返回的是一個NodeList對象
System.out.println(nodes1.getLength());
for (int i = 0; i < nodes1.getLength(); i++) {
Node node = nodes1.item(i);// 根據元素獲取元素節點book
//根據節獲元素屬性
NamedNodeMap attributes = node.getAttributes();
for (int j = 0; j < attributes.getLength(); j++) {
Node item = attributes.item(j);
System.out.println(item.getNodeName());//得到屬性名
System.out.println(item.getNodeValue());//得到屬性值
}
System.out.println(node.getNodeName());// 得到book元素(可能不只一個book元素)
NodeList childNodes = node.getChildNodes();// 根據上一步獲得的book節點,獲取book節點下面的子節點
for (int j = 0; j < childNodes.getLength(); j++) {
Node text = childNodes.item(j);
// 根據節點名稱和xml文件中的元素名稱做比較equals的打印輸出
if (text.getNodeName().equals("name")) {
System.out.println(text.getTextContent());
}
if (text.getNodeName().equals("author")) {
System.out.println(text.getTextContent());
}
if (text.getNodeName().equals("price")) {
System.out.println(text.getTextContent());
}
}
}
} catch (ParserConfigurationException | SAXException | IOException e) {
e.printStackTrace();
}
}
}
接下來對XML文件進行簡單的增、刪、改操作:
增加元素和屬性操作:
在book後面添加 1997-12-15 節點:
1、添加的位置
2、將元素創建出來
// dom元素增加操作
@Test
public void Test1() throws UnsupportedEncodingException, FileNotFoundException {
// 1、獲取document對象
Document document = DomUtil.getDocument("xml/books.xml");
// 2、問題分析:book後面添加<data>1997-12-15</data>節點
// 2.1首先元素添加到那個位置
Node book = document.getElementsByTagName("book").item(0);
// 2.2元素要創建出來
Element data = document.createElement("data");
data.setTextContent("1997-12-15");
book.appendChild(data);
// 回寫操作
DomUtil.backWrite(document, "xml/books.xml");
}
@Test
// 添加元素的屬性
public void Test2() throws UnsupportedEncodingException, FileNotFoundException {
// 獲得document對象
Document document = DomUtil.getDocument("xml/books.xml");
Element book = (Element) document.getElementsByTagName("book").item(0);
book.setAttribute("language", "英文");
// 回寫操作
DomUtil.backWrite(document, "xml/books.xml");
}
刪除元素和屬性操作:
// dom刪除元素
@Test
public void Test6() throws UnsupportedEncodingException, FileNotFoundException {
// 獲取document對象
Document document = DomUtil.getDocument("xml/books.xml");
// 獲取book元素
Node data = document.getElementsByTagName("data").item(0);
data.getParentNode().removeChild(data);// 先獲取父節點,在根據父節點去刪除子節點
// 回寫操作
DomUtil.backWrite(document, "xml/books.xml");
}
@Test
// dom刪除元素的屬性
public void Test4() throws UnsupportedEncodingException, FileNotFoundException {
// 獲取document對象
Document document = DomUtil.getDocument("xml/books.xml");
// 獲取book元素
Element book = (Element) document.getElementsByTagName("book").item(0);
book.removeAttribute("language");
// 回寫操作
DomUtil.backWrite(document, "xml/books.xml");
}
修改元素和屬性操作:
@Test
// 修改元素內容 name中的內容
public void fun1() throws UnsupportedEncodingException, FileNotFoundException {
// 獲取document對象
Document document = DomUtil.getDocument("dtd/books.xml");
// 得到name元素對象
NodeList authors = document.getElementsByTagName("author");
Node author = authors.item(0);// 得到第一個元素爲author節點,假設知道
// 修改節點內容
author.setTextContent("小曹");
// 此時需要對author中的內容進行回寫操作
// 回寫操作
DomUtil.backWrite(document, "dtd/books.xml");
}
// 修改元素屬性
@Test
public void fun2() throws UnsupportedEncodingException, FileNotFoundException {
// 獲取document對象
Document document = DomUtil.getDocument("dtd/books.xml");
// 獲取需要修改的元素
// 獲取得到的元素是NodeList的返回值,.item(0)之後是Node的返回值,但是不能獲取單個屬性,查文檔發現Element是可以獲取得到單個屬性
Element en = (Element) document.getElementsByTagName("book").item(0);
en.setAttribute("language", "en");
// 回寫操作
DomUtil.backWrite(document, "dtd/books.xml");
}
將回寫操作和獲得document對象進行封裝:
//將獲得document對象進行封裝
public static Document getDocument(String uri) {
// 1、創建解析器類工廠
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// 2、根據解析器工廠生產解析器
try {
DocumentBuilder db = factory.newDocumentBuilder();
// 3、根據生產的解析器獲取document對象
Document document = db.parse(uri);
return document;
} catch (IOException | SAXException | ParserConfigurationException e) {
e.printStackTrace();
}
return null;
}
//將回寫操作進行封裝
public static void backWrite(Document document, String uri)
throws UnsupportedEncodingException, FileNotFoundException {
// 1、獲得修改器工廠
TransformerFactory factory = TransformerFactory.newInstance();
// 2、根據修改器工廠獲得修改器
try {
Transformer tf = factory.newTransformer();
// 3、根據修改器進行回寫操作
// tf.transform(new DOMSource(document), new StreamResult(new
// File("dtd/books.xml")));
//解決亂碼問題,出現問題的原因是:保存的XML文件的編碼和解析是的編碼不一致
tf.transform(new DOMSource(document),
new StreamResult(new OutputStreamWriter(new FileOutputStream(uri), "GBK")));// 解決亂碼問題
} catch (TransformerConfigurationException e) {
e.printStackTrace();
} catch (TransformerException e) {
e.printStackTrace();
}
}