| 解析方式 | 簡(jiǎn)介 | 優(yōu)點(diǎn) | 缺點(diǎn) |
|---|---|---|---|
| DOM | Document Object Model文檔對(duì)象模型,把整個(gè)XML文檔先加載到內(nèi)存中,形成樹狀結(jié)構(gòu) | 節(jié)點(diǎn)與節(jié)點(diǎn)之間有關(guān)系,進(jìn)行增刪改非常方便 | 如果文檔非常大,加載到內(nèi)存中容易產(chǎn)生內(nèi)存溢出的問題 |
| SAX | Simple API for XML 基于事件驅(qū)動(dòng)的,邊讀邊解析 | 文檔大也不會(huì)有內(nèi)存溢出的問題,查找非常方便 | 不能進(jìn)行增刪改的操作 |
| 解析開發(fā)包 | 簡(jiǎn)介 |
|---|---|
| JAXP | javaSE的一部分,想做增刪改,只能用DOM方式。如果SAx,只能做查詢 |
| Dom4j | 企業(yè)都在用,DOM4J提供。增刪改查都可以做 |
JAXP解析
| 解析方式 | 解析器工廠類 | 解析器對(duì)象 |
|---|---|---|
| DOM | DocumentBuilderFactory | DocumentBuilder |
| SAX | SAXParserFactory | SAXParser |
JAXP的DOM解析
- 由解析器工廠類獲取解析器工廠
- 解析器工廠產(chǎn)生一個(gè)解析器
- 解析XML,獲得一個(gè)Document對(duì)象。Document parse(String uri)
- 回寫
a 獲取回寫的工廠類TransformerFactory
b 獲取回寫類transformer
c transform(new DOMSource(document), new StreamResult("src/book2.xml"));
//獲取作者的文本內(nèi)容
public static void run1() throws ParserConfigurationException, SAXException, IOException{
//獲取解析器工廠類
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
//獲取解析器對(duì)象
DocumentBuilder builder = factory.newDocumentBuilder();
//解析XML的文檔,返回document對(duì)象
Document document = builder.parse("src/book2.xml");
//獲取作者元素對(duì)象的集合,返回NodeList
NodeList nodelist = document.getElementsByTagName("作者");
//循環(huán)遍歷,獲得每一個(gè)作者,打印文本的內(nèi)容
for(int i = 0; i < nodelist.getLength(); i++){
Node node = nodelist.item(i);
System.out.println(node.getTextContent());
}
}
//在第二本下,在末尾添加子節(jié)點(diǎn),需要回寫類
public static void run2() throws Exception{
//獲取工廠類
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
//獲取解析類
DocumentBuilder builder = factory.newDocumentBuilder();
//解析XML,返回Document對(duì)象
Document document = builder.parse("src/book2.xml");
//獲取第二本書
Node book2 = document.getElementsByTagName("書").item(1);
//創(chuàng)建元素對(duì)象
Element cat = document.createElement("毛");
//設(shè)置文本內(nèi)容
cat.setTextContent("我是貓");
//把元素對(duì)象添加到第二本書下
book2.appendChild(cat);
//回寫
//創(chuàng)建回寫類的工廠
TransformerFactory transFactory = TransformerFactory.newInstance();
//獲取回寫類
Transformer transformer = transFactory.newTransformer();
//調(diào)用回寫的方法
transformer.transform(new DOMSource(document), new StreamResult("src/book2.xml"));
}
/**
* 獲取第一本書的屬性值
* @throws Exception
*/
public static void run3() throws Exception{
//獲取工廠類
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
//解析器
DocumentBuilder builder = factory.newDocumentBuilder();
//解析
Document document = builder.parse("src/book2.xml");
//獲取作者,再獲取第二本書
Node book1 = document.getElementsByTagName("書").item(0);
//鄉(xiāng)下轉(zhuǎn)型
Element book = (Element)book1;
System.out.println(book.getAttribute("編號(hào)"));
}
/**
* 在作者標(biāo)簽之前,添加團(tuán)購(gòu)價(jià)標(biāo)簽
* @throws Exception
*/
public static void run1() throws Exception{
//獲取工廠類
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
//解析器
DocumentBuilder builder = factory.newDocumentBuilder();
//解析
Document document = builder.parse("src/book2.xml");
//獲取作者,再獲取第二本書
Node author = document.getElementsByTagName("作者").item(1);
Node book2 = author.getParentNode();
//創(chuàng)建元素
Element tuan = document.createElement("團(tuán)購(gòu)價(jià)");
//設(shè)置文本
tuan.setTextContent("很便宜");
//加入到作者之前
book2.insertBefore(tuan, author);
//回寫
TransformerFactory factory2 = TransformerFactory.newInstance();
Transformer transformer = factory2.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult("src/book2.xml"));
}
JAXP 的 DOM 封裝
public class JaxpDomUtil {
/**
* 通過path獲取document對(duì)象
* @throws Exception
*/
public static Document getDocument(String path) throws Exception{
//獲取工廠類
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
//獲取解析器對(duì)象
DocumentBuilder builder = factory.newDocumentBuilder();
//解析XML
Document document = builder.parse(path);
return document;
}
public static void writeXML(Document document,String path) throws Exception{
//獲得回寫類工廠
TransformerFactory factory = TransformerFactory.newInstance();
//獲得回寫類
Transformer transformer = factory.newTransformer();
//回寫
transformer.transform(new DOMSource(document), new StreamResult(path));
}
public static void delete() throws Exception{
//獲取文檔對(duì)象
Document document = getDocument("src/book2.xml");
//獲取貓
Node cat = document.getElementsByTagName("毛").item(0);
//獲取書(貓的父節(jié)點(diǎn))
Node book = cat.getParentNode();
//通過書刪除貓
book.removeChild(cat);
//回寫
writeXML(document,"src/boo2.xml");
}
public static void main(String[] args) throws Exception {
delete();
}
}
JAXP的SAX解析 只能查詢
由于SAX是基于時(shí)間驅(qū)動(dòng)的,所以要有 解析器 和 事件處理器
解析器
- 獲得解析器的工廠
- 獲取解析器對(duì)象
- 解析XML (XML文件地址,事件處理器)
解析器采用SAX方式在解析某個(gè)XML文檔時(shí),它只要解析到XML文檔的一個(gè)組成部分,都會(huì)去調(diào)用事件處理器的一個(gè)方法,解析器在調(diào)用事件處理器的方法時(shí),會(huì)把當(dāng)前解析到的xml文件內(nèi)容作為方法的參數(shù)傳遞給事件處理器。
事件處理器由程序員編寫,程序員通過事件處理器中方法的參數(shù),就可以很輕松地得到sax解析器解析到的數(shù)據(jù),從而可以決定如何對(duì)數(shù)據(jù)進(jìn)行處理。
事件處理器
- 自己編寫類,繼承DefaultHandler,重寫三個(gè)方法
- startDocument()
- startElement() 重寫
- characters() 重寫
- endElement() 重寫
- endDocument()
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* SAX的入門
* @author limaoquan
*
*/
public class JaxpSaxTest {
public static void main(String[] args) {
}
/**
* 獲取所有解析的內(nèi)容
* @throws Exception
* @throws ParserConfigurationException
*/
public static void run1() throws ParserConfigurationException, Exception{
//獲取Sax的解析器工廠
SAXParserFactory factory = SAXParserFactory.newInstance();
//獲取解析器
SAXParser parser = factory.newSAXParser();
//解析
parser.parse("src/book2.xml", new MyHandler());
}
}
/**
* 獲取標(biāo)簽作者的文本內(nèi)容
* @author limaoquan
*
*/
class MyHandler2 extends DefaultHandler{
private boolean flag = false;
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if("作者".equals(qName)){
flag = true;
}
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
String str = new String(ch, start, length);
if(flag){
System.out.println(str);
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
flag = false;
}
}
class MyHandler extends DefaultHandler{
/**
* 只要一解析到開始標(biāo)簽的時(shí)候,默認(rèn)調(diào)用該方法
*/
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
System.out.println("開始標(biāo)簽:"+ qName);
}
/**
* 只要解析到文本內(nèi)容,默認(rèn)調(diào)用該方法
*/
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
System.out.println("結(jié)束標(biāo)簽:"+qName);
}
/**
* 解析到結(jié)束標(biāo)簽的時(shí)候,默認(rèn)調(diào)用該方法
*/
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
String str = new String(ch, start, length);
System.out.println(str);
}
}
Dom4j
Dom4j是一個(gè)簡(jiǎn)單、靈活的開放源代碼的庫(kù)
使用Dom4j需要下載dom4j相應(yīng)的jar包
- 查找標(biāo)簽文本
- 創(chuàng)建解析器 new SAXReader()
- 解析xml read()
- 獲取根節(jié)點(diǎn) root = getRootElement()
- 獲取所有指定標(biāo)簽的集合 root.elements(標(biāo)簽名)
- 返回List集合,可以遍歷,或者getIndex() 獲取Element對(duì)象
- 獲取文本內(nèi)容 getText()
- 添加子節(jié)點(diǎn)
- 創(chuàng)建解析器 new SAXReader()
- 解析xml read()
- 獲取根節(jié)點(diǎn) root = getRootElement()
- 獲取所有指定標(biāo)簽的集合 root.elements(標(biāo)簽名)
- 直接調(diào)用addElement()設(shè)置子節(jié)點(diǎn)
- 使用setTest()設(shè)置文本
- 回寫xml文件
- 在指定位置添加子節(jié)點(diǎn)
- 創(chuàng)建元素標(biāo)簽節(jié)點(diǎn) DocumentHelper.createElement()
- 設(shè)置文本 setText()
- 獲取所有指定標(biāo)簽的集合 root.elements(標(biāo)簽名), 返回list
- 通過list.add(index, element), 在內(nèi)存中加入子元素
- 回寫xml文件
- 修改節(jié)點(diǎn)文本
- 找到指定的節(jié)點(diǎn)
- 修改文本內(nèi)容 setText()
- 刪除節(jié)點(diǎn)
- 找到要?jiǎng)h除的節(jié)點(diǎn)
- 通過父節(jié)點(diǎn)調(diào)用remove()方法刪除
/**
* 獲取作者的文本內(nèi)容
* @throws Exception
*/
public static void run1() throws Exception{
//獲取解析器對(duì)象
SAXReader reader = new SAXReader();
//解析XML,返回Document對(duì)象
Document document = reader.read("src/book2.xml");
//獲取根節(jié)點(diǎn)(書架標(biāo)簽)
Element root = document.getRootElement();
//獲取書的節(jié)點(diǎn),獲取第二本書
List<Element> books = root.elements("書");
Element book2 = books.get(1);
//獲取作者的標(biāo)簽
Element author = book2.element("作者");
//獲取文本內(nèi)容
String str = author.getText();
}
/**
* 在第二本書下添加子節(jié)點(diǎn)
* @throws Exception
*/
public static void run2() throws Exception{
//獲取解析器對(duì)象
SAXReader reader = new SAXReader();
//解析XML 反回Document對(duì)象
Document document = reader.read("src/book2.xml");
//獲取根節(jié)點(diǎn)
Element root = document.getRootElement();
//獲取第二本書
Element book2 = (Element)root.elements("書").get(1);
// 可以直接在第二本書下添加節(jié)點(diǎn),設(shè)置文本內(nèi)容
book2.addElement("貓").setText("你是貓");
//創(chuàng)建漂亮的格式
OutputFormat format = OutputFormat.createPrettyPrint();
//回寫
XMLWriter writer = new XMLWriter(new FileOutputStream("src/book2.xml"),format);
writer.write(document);
writer.close();
}
/**
* 在第二本書的作者標(biāo)簽之前添加團(tuán)購(gòu)價(jià)的標(biāo)簽
* @throws Exception
*/
public static void run3() throws Exception{
//獲取解析器對(duì)象
SAXReader reader = new SAXReader();
//解析XML 反回Document對(duì)象
Document document = reader.read("src/book2.xml");
//獲取根節(jié)點(diǎn)
Element root = document.getRootElement();
//獲取第二本書
Element book2 = (Element)root.elements("書").get(1);
//獲取書下的所有子節(jié)點(diǎn),返回list集合
List<Element> list = book2.elements();
//創(chuàng)建元素對(duì)象 DocumentHelper類
Element dog = DocumentHelper.createElement("狗");
dog.setText("dagoudagou");
//list.add(index,Element);
list.add(1,dog);
//回寫
XMLWriter writer = new XMLWriter(new FileOutputStream("src/book2.xml"));
writer.write(document);
writer.close();
}
/**
* 刪除子節(jié)點(diǎn)
* 刪除第二本書下的錨節(jié)點(diǎn)
*/
public static void run4() throws Exception{
//獲取解析器對(duì)象
SAXReader reader = new SAXReader();
//解析XML 反回Document對(duì)象
Document document = reader.read("src/book2.xml");
//獲取根節(jié)點(diǎn)
Element root = document.getRootElement();
//獲取貓
Element book2 = (Element)root.elements("書").get(1);
Element cat = book2.element("貓");
//通過貓的父節(jié)點(diǎn)刪除貓
book2.remove(cat);
//回寫
XMLWriter writer = new XMLWriter(new FileOutputStream("src/book2.xml"));
writer.write(document);
writer.close();
}
Dom4j獲得Document對(duì)象的三種方式:
讀取xml文檔
SAXReader reader = new SAXReader();
Document document = reader.read(new File("input.xml"));解析XML形式的文本
String text = "<members></members>";
Document document = DocumentHelper.parseText(text);主動(dòng)創(chuàng)建document對(duì)象
Document document = DocumentHelper.createDocument();
//創(chuàng)建根節(jié)點(diǎn)
Element root = document.addElement("members");
節(jié)點(diǎn)對(duì)象
獲取文檔的根節(jié)點(diǎn)
Element root = document.getRootElement();取得某個(gè)節(jié)點(diǎn)的子節(jié)點(diǎn)
Element element = node.element("標(biāo)簽名")獲取節(jié)點(diǎn)的文字
String text = node.getText();設(shè)置節(jié)點(diǎn)文字
element.setText();取得某個(gè)節(jié)點(diǎn)下所有名為member的子節(jié)點(diǎn),并遍歷
List nodes = rootElm.elements("member");
for(iterator it = nodes.iterator();it.hasNext(); ){
Element elem = (Element)it.next();
//do something ...
}對(duì)某節(jié)點(diǎn)下的所有子節(jié)點(diǎn)進(jìn)行遍歷
for(iterator it = root.elementiterator();it.hasNext(); ){
Element elem = (Element)it.next();
//do something ...
}
在某個(gè)節(jié)點(diǎn)下添加子節(jié)點(diǎn)
Element ageElm = newMemberElm.addElement("age");刪除某節(jié)點(diǎn)
parentElm.remove(childElm);添加一個(gè)CDATA節(jié)點(diǎn)
Element contenElm = infoElm.addElement("content");
contentElm.addCDATA(diary.getContent());
節(jié)點(diǎn)對(duì)象的屬性
取得某節(jié)點(diǎn)下的某屬性
Element root = document.getRootElement();
//屬性名name
Attribute attribute = root.attribute("size");取得屬性的文字
String text = attribute.getText();刪除某屬性
Attribute attribute = root.attribute("size");
root.remove(attribute);遍歷某節(jié)點(diǎn)的所有屬性
Element root = document.getRootElement();
for(Iterator it = root.attributeIterator(); it.hasNext();){
Attribute attribute = (Attribute)it.next();
String text = attribute.getText();
System.out.println(text);
}設(shè)置某節(jié)點(diǎn)的屬性和文字
newMemberElm.addAttribute("name","sitinspring");設(shè)置屬性的文字
attribute.setText("sitinspring");
將文檔寫入XML文件
文檔中全為英文,不設(shè)置編碼,直接寫入
XMLWriter writer = new XMLWriter(new FileWriter("output.xml"));
writer.write(document); //此document為之前建立的Document對(duì)象
writer.close();文檔中有中文,設(shè)置編碼格式
OutputFormat format = OutputFormat.createPrettyPrint();
//指定XML編碼
format.setEncoding("GBK");
XMLWriter writer = new XMLWriter(new FileWriter("output.xml"),format);
writer.write(document); //此document為之前建立的Document對(duì)象
writer.close();
Dom4j在指定位置插入節(jié)點(diǎn)
Step:
- 得到插入位置的節(jié)點(diǎn)列表(list)
- 調(diào)用list.add(index,element), 由index決定element的插入位置
- Element元素可以通過DocumentHelpler對(duì)象得到
Element aaa = DocumentHelper.createElement("aaa");
aaa.setText("aaa");
List list = root.element("書").elements();
list.add(1,aaa);
//更新document
字符串與XML的轉(zhuǎn)換
字符串轉(zhuǎn)化為XML
String text = "<members><member>setinsping</member></members>";
Document document = DocumentHelper.parseText(text);將文檔或節(jié)點(diǎn)的XML轉(zhuǎn)化為字符串
SAXReader reader = new SAXReader();
Document document = reader.read(new File("input.xml"));
Element root = document.getRootElement();
String docXmlText = document.asXML();
String rootXmlText = root.asXML();
Element memberElm = root.element("member");
String memberXmlText = memberElm.asXML();
Dom4j對(duì)XPATH的支持
導(dǎo)入包 jaxen-1.1-beta-6.jar
只能使用Node中的兩個(gè)方法:
- selectNodes()
- selectNode()
Xpath的語(yǔ)法
- /AAA/BBB/CCC 獲取的CCC的節(jié)點(diǎn)
- //BBB 無(wú)論層級(jí)關(guān)系,所有的BBB都找到
- //DDD/BBB 所有DDD下的BBB元素
- /AAA/CCC/* CCC下的所有元素
- /*/*/*/BBB 所有有3個(gè)祖元素的BBB元素
- //* 所有元素
- /AAA/BBB[1] AAA下的第一個(gè)BBB
- /AAA/BBB[last()] AAA下最后一個(gè)BBB
- //@id id屬性
- //BBB[@name] 選擇有name屬性的BBB元素
- //BBB[@*] 選擇有任意屬性的BBB元素
- //BBB[note(@*)] 選擇沒有屬性的BBB元素