jaxp解析器用dom方式操作xml文件的總結
阿新 • • 發佈:2019-01-25
1. xml解析技術概述 |
解析xml文件一般有兩種技術:dom(Document Object Model)和sax(Simple API for XML)。dom即文件物件模型,是W3C組織推薦的處理xml的一種方式;sax不是官方標準,但它是xml社群事實上的標準,幾乎所有的xml解析器都支援它。
1.1 dom方式
dom方式會把文字解析成Document物件,把所有元素和文字也解析成一個物件:解析器將標籤解析為Element物件,對內容解析為Text物件,對屬性解析為Attribute。對所有的節點都可以用Node物件表示,當沒有合適的方法呼叫的時候,才把Node強制轉換成上面的具體型別,上面的類都是Node的子類。
使用dom方式對xml文件解析只需要得到document物件,就可以得到所有節點,因為在記憶體中會解析成樹結構圖。
- 優點:實現CURD特別方便,操作速度也比較快。
- 缺點:如果檔案比較大,對記憶體消耗就特別大,極易導致記憶體溢位,所以dom方式不是和操作大的xml文件。
1.2 sax方式
sax方式不是先將文字解析成整個物件,它是讀取一行解析一行。
- 優點:解析速度快,對記憶體佔用少,查詢資料特別方便。
- 缺點:只適合查詢資料,不適合CURD操作。
針對這兩種方式,有很多解析開發包,主要有jaxp和dom4j,這篇文章先介紹一下jaxp解析器如何用dom方式解析xml文件。
2. jaxp解析器用dom方式解析xml文件 |
jaxp開發包是j2se的一部分,它由
javax.xml
org.w3c.dom
、org.xml.sax
包及其子包組成。在javax.xml.parsers
包中,定義了幾個工廠類,程式設計師呼叫這些工廠類,可以得到對xml文件進行解析的dom和sax的解析器物件。javax.xml.parsers
包中的DocumentBuilderFactory用於建立dom模式的解析器物件,DocumentBuilderFactory是一個抽象工廠類,它不能直接例項化,但是該類提供了一個靜態的newInstance()
方法,這個方法會根據本地平臺預設安裝的解析器,自動建立一個工廠的物件並返回。 首先給出個book.xml文件,如下:
<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<book name="book1" password="123">
<price>59元</price>
<name>java神書1^^</name>
<author>倪升武</author>
</book>
<book name="book2" password="123456">
<price>69元</price>
<name>java神書2^^</name>
<author>倪升武</author>
</book>
</bookstore>
下面我們來使用jaxp具體解析這個book.xml文件:
2.1 得到節點的值
@Test
public void read() throws Exception{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();//獲取工廠
DocumentBuilder builder = factory.newDocumentBuilder();//產生解析器
Document document = builder.parse(new File("src/book.xml"));//解析xml文件,得到代表文件的document
NodeList list = document.getElementsByTagName("price");//返回所有price節點的集合
Node price = list.item(0); //拿到第一個price節點
String value = price.getTextContent();//獲取節點的值
System.out.println(value); //59元
}
2.2 修改節點的值
@Test
public void update() throws Exception{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new File("src/book.xml"));
Node price = document.getElementsByTagName("售價").item(0);
price.setTextContent("89元");
/*javax.xml.tranform包中的Transformer類用於把代表XML檔案的Document物件轉換為某種格式後進行輸出。
*例如把XML檔案應用樣式表後轉成一個HTML文件,利用這個物件,當然也可以把Document物件重新寫入到一個XML檔案中。
*Transformer類通過transform(Source xmlSource, Result outputTarget)方法完成轉換操作,該方法接受一個源和一個目的地。我們可以通過:
* javax.xml.transform.dom.DOMSource類來關聯要轉換的document物件,
* 用javax.xml.transform.stream.StreamResult物件來表示資料的目的地。
*Transformer抽象類,但是其物件通過TransformerFactory.newTransformer獲得。
*
*/
//得到轉換器工廠
TransformerFactory tf = TransformerFactory.newInstance();
//得到轉換器
Transformer ts = tf.newTransformer();
ts.transform(new DOMSource(document), new StreamResult(new File("src/book.xml"))); //將修改後的document物件(dom)轉換到book.xml
}
2.3 新增新的節點
@Test
public void addNode() throws Exception{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new File("src/book.xml"));
//建立需要增加的節點
Node price = document.createElement("price");
price.setTextContent("109元");
//得到需要增加的節點的父節點
Node parent = document.getElementsByTagName("book").item(0);//第一個book節點
//把需要增加的節點掛到父節點上
parent.appendChild(price);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer ts = tf.newTransformer();
ts.transform(new DOMSource(document), new StreamResult(new File("src/book.xml")));
}
2.4 向指定位置新增新的節點
@Test
public void addNodeWithIndex() throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new File("src/book.xml"));
Node node = document.createElement("price");
node.setTextContent("39元");
Node parent = document.getElementsByTagName("book").item(0);
parent.insertBefore(node, document.getElementsByTagName("name").item(0));//在書名前新增node
TransformerFactory tf = TransformerFactory.newInstance();
Transformer ts = tf.newTransformer();
ts.transform(new DOMSource(document), new StreamResult(new File("src/book.xml")));
}
2.5 刪除指定的節點
@Test
public void delete() throws Exception{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new File("src/book.xml"));
NodeList nodes = document.getElementsByTagName("price");//獲取所有售價節點
for(int i = 0; i <= nodes.getLength(); i++){
if(nodes.item(i).getTextContent().equals("109元")){
//自己不能刪自己,要讓它的父節點來刪
nodes.item(i).getParentNode().removeChild(nodes.item(i));//刪除所有售價為109元的節點
}
}
TransformerFactory tf = TransformerFactory.newInstance();
Transformer ts = tf.newTransformer();
ts.transform(new DOMSource(document), new StreamResult(new File("src/book.xml")));
}
2.6 操作文件的屬性
@Test
public void updateAttribute() throws Exception{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new File("src/book.xml"));
//操作XML文件元素時,一般都把元素當做Node對待,但是如果Node沒有合適的方法時,就得轉換成相應的型別
Node node = document.getElementsByTagName("book").item(0);
Element book = null;
if(node.getNodeType() == Node.ELEMENT_NODE)//在轉換之前,最好先判斷下型別
book = (Element)node;
book.setAttribute("name", "--book--");
book.setAttribute("password", "--123--");
TransformerFactory tf = TransformerFactory.newInstance();
Transformer ts = tf.newTransformer();
ts.transform(new DOMSource(document), new StreamResult(new File("src/book.xml")));
}
以上就是jaxp解析器使用dom方式對xml文件進行解析的總結,可以看出,如果只讀不寫,只要獲取解析器工廠–>獲取解析器–>將xml轉換成document,然後開始獲取想要獲取的資料。如果要向xml文件中寫資料,那麼要獲取轉換器工廠–>獲取轉換器–>將document轉換成xml。所以很明顯,這是兩個相反的過程。