1. 程式人生 > >XML文件解析:DOM解析與DOM的增刪改查

XML文件解析:DOM解析與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();
		}
	}