XML的解析簡介: 在學習JavaScript時,我們用的DOM來解析HEML文檔,根據HTML的層級結構在記憶體中分配一個樹形結構,把HTML的標簽啊,屬性啊和文本之類的都封裝成對象。 比如:document對象,element對象,屬性對象,文本對象,Node結點對象 我們通常有兩種方式來解析XM ...
XML的解析簡介:
在學習JavaScript時,我們用的DOM來解析HEML文檔,根據HTML的層級結構在記憶體中分配一個樹形結構,把HTML的標簽啊,屬性啊和文本之類的都封裝成對象。
比如:document對象,element對象,屬性對象,文本對象,Node結點對象
我們通常有兩種方式來解析XML:DOM和SAX
DOM解析方式:
其實跟HTML差不多的,也是根據XML的層級結構在記憶體中分配一個樹形結構,把XML的標簽,屬性和文本都封裝成對象。
缺點:如果文件過大的話,就和造成記憶體溢出。
優點:可以很方便實現增刪改操作。
SAX解析方式:
採用事件驅動,從上到下,一行一行的解析,邊讀邊解析。解析到某一個對象時,返回對象名稱。
缺點:不能實現增刪改操作
優點:不會記憶體溢出,可以方便實現查詢操作。
解析器:
在解析XML時,需要解析器。針對DOM和SAX,不同的公司和組織向我們提供了不同的解析器。
SUN公司: jaxp
dom4j組織: dom4j
jdom組織 : jdom
在實際開發中,dom4j用的最多
jaxp:
jaxp解析器在JDK的javax.xml.parsers包裡面。針對dom和sax分別提供瞭解析器:
dom: DocumentBuilder: 解析器類
DocumentBuilderFactory: 解析器工廠類
sax: SAXParser: 解析器類
SAXParserFactory: 解析器工廠類
那麼我們具體獲得JAXP中的DOM解析器的方法如下:
調用DocumentBuilderFactory.newInstance()方法得到創建DOM解析器的工廠。
調用工廠對象的newDocumentBuilder()方法得到解析器對象。
調用解析器對象的parse()方法解析XML文檔,該方法的參數為XML文檔的URL或者封裝了XML路徑的文件對象。即:parse(String uri) parse(File f)
示例:
// 創建解析器工廠
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
// 獲得解析器
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
// 解析目標XML文件
Document document = documentBuilder.parse("src/OnePiece.xml");
通過上述步驟我們就能得到代表整個文檔的Document對象,就可以利用DOM特性對整個XML文檔進行操縱了。
Document介面中常用的方法:
NodeList getElementsByTagName(String tagname) 按文檔順序返回包含在文檔中且具有給定標記名稱的所Element的 NodeList。
Element createElement(String tagName) 創建指定類型的元素。
Text createTextNode(String data) 創建給定指定字元串的 Text 節點。
Document的父介面Node中常用的方法:
Node appendChild(Node newChild)
將節點 newChild 添加到此節點的子節點列表的末尾。
Node removeChild(Node oldChild)
從子節點列表中移除 oldChild 所指示的子節點,並將其返回。
Node getParentNode()
此節點的父節點。
String getTextContent()
此屬性返回此節點及其後代的文本內容。
void setTextContent(String textContent)
此屬性返回此節點及其後代的文本內容。
在得到的NodeList集合中有下列方法可以實現遍歷:
int getLength()
列表中的節點數。
Node item(int index)
返回集合中的第 index 個項。
在對Document對象進行更新操作時,都是在記憶體中進行的。如果想要更直觀地顯示在XML文檔中,需要進行回寫操作。即:把Document對象又重新寫入到XML文件中。
示例:
現有一個XML文檔內容如下:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<海賊王>
<草帽海賊團>
<船長>路飛</船長>
<廚師>山治</廚師>
<航海士>娜美</航海士>
<船醫>喬巴</船醫>
<音樂家>貝多芬</音樂家>
</草帽海賊團>
<草帽海賊團>
<副船長>索隆</副船長>
<考古學家>羅賓</考古學家>
<狙擊手>烏索普</狙擊手>
<船工>弗蘭奇</船工>
</草帽海賊團>
</海賊王>
需求:將第一個<草帽海賊團>下麵的<音樂家>內容貝多芬改為布魯克
代碼如下:
package com.alex;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/*
* 將第一個<草帽海賊團>下麵的<音樂家>內容貝多芬改為布魯克
*/
public class OnePieceTest3 {
public static void main(String[] args) throws Exception {
// 創建解析器
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
// 解析目標XML文件
Document document = documentBuilder.parse("src/OnePiece.xml");
// 獲得目標元素集合
NodeList list = document.getElementsByTagName("草帽海賊團");
Node node = list.item(0);
NodeList childNodes = node.getChildNodes();
for (int j = 0; j < childNodes.getLength(); j++) {
Node node2 = childNodes.item(j);
String nodeName = node2.getNodeName();
if (nodeName.equals("音樂家"))
node2.setTextContent("布魯克");
}
// 回寫
// 創建轉換器
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult("src/OnePiece.xml"));
}
}
修改後XML文檔內容如下:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<海賊王>
<草帽海賊團>
<船長>路飛</船長>
<廚師>山治</廚師>
<航海士>娜美</航海士>
<船醫>喬巴</船醫>
<音樂家>布魯克</音樂家>
</草帽海賊團>
<草帽海賊團>
<副船長>索隆</副船長>
<考古學家>羅賓</考古學家>
<狙擊手>烏索普</狙擊手>
<船工>弗蘭奇</船工>
</草帽海賊團>
</海賊王>
2019-04-05