XML文件可以用來作為一種小型數據庫存在,但更多時候在項目中都是用來當成配置文件用的,也就避免不了對XML文件的增上改查操作。
在java中,解析XML文件的方式大致分為兩種:DOM解析,SAX解析
先來說DOM解析方式:xml解析器一次性把整個xml文檔加載進內存,然后在內存中構建一顆Document的對象樹,通過Document對象,得到樹上的節點對象,通過節點對象訪問(操作)到xml文檔的內容。
用的較為多的是Dom4j工具(非官方)解析,簡單介紹下Dom4j的使用,具體API文檔請下載
Dom4j讀取xml文件
SAXReader reader = new SAXReader(); //1.創建一個xml解析器對象 Document doc = reader.read(new File("xxx.xml"));//2.讀取xml文檔,返回Document對象 獲取節點: Iterator<Node> doc.nodeIterator(); //獲取當前標簽節點下的所有子節點 獲取標簽: Element elem = doc.getRootElement(); //獲取xml文檔的根標簽(一般創建doc對象后回先調用此方法得到根標簽) Element e = elem.element("標簽名") //指定名稱的第一個子標簽 Iterator<Element> iterator = elem.elementIterator("標簽名");// 指定名稱的所有子標簽 List<Element> list = elem.elements(); //獲取所有子標簽 獲取屬性: String sttrValue = elem.attributeValue("屬性名") //獲取指定名稱的屬性值 Attribute attr = Element.attribute("屬性名");//獲取指定名稱的屬性對象 attr.getName() //獲取屬性名稱 attr.getValue() //獲取屬性值 List<Attribute> elem.attributes(); //獲取所有屬性對象 Iterator<Attribute> elem.attributeIterator(); //獲取所有屬性對象 獲取文本: elem.getText(); //獲取當前標簽的文本 elem.elementText("標簽名") //獲取當前標簽的指定名稱的子標簽的文本內容
Dom4j修改xml文件
增加: DocumentHelper.createDocument() 增加文檔 addElement("名稱") 增加標簽 addAttribute("名稱",“值”) 增加屬性 修改: Attribute.setValue("值") 修改屬性值 Element.addAtribute("同名的屬性名","值") 修改同名的屬性值 Element.setText("內容") 修改文本內容 刪除 Element.detach(); 刪除標簽 Attribute.detach(); 刪除屬性 寫出文件 XMLWriter writer = new XMLWriter(OutputStream, OutputForamt) wirter.write(Document);
簡單代碼操作步驟:
1 //1、讀取文件
2 Document doc = new SAXReader().read(new File("xxx.xml")); 3
4 //2、修改文件 5
6 //3、寫出文件
7 FileOutputStream out = new FileOutputStream("f:/xxx.xml");//指定文件輸出的位置 8 //指定寫出的格式
9 OutputFormat format = OutputFormat.createCompactFormat(); //緊湊的格式.去除空格換行. 10 //OutputFormat format = OutputFormat.createPrettyPrint(); //格式好的格式.有空格和換行.
11 format.setEncoding("utf-8");//2.指定生成的xml文檔的編碼
12 XMLWriter writer = new XMLWriter(out,format);//創建寫出對象
13 writer.write(doc);//寫出對象
14 writer.close();//關閉流
值得注意的是Dom4j還支持xPath,這讓我們獲取標簽得到極大的方便。基本就需要記住兩個方法,一句代碼,便可以獲取所有想獲取到的元素
導入xPath支持jar包 jaxen-1.1-beta-6.jar,上面給的文檔有。
List<Node> selectNodes("xpath表達式"); // 查詢多個節點對象 Node selectSingleNode("xpath表達式"); // 查詢一個節點對象
例子:假設有如下這段xml,想要獲取 二班趙六 的學生的姓名
1 <?xml version="1.0" encoding="UTF-8"?>
2 <root>
3 <class id="001">
4 <student id="001">
5 <name>一班--張三</name>
6 <age>20</age>
7 </student>
8 <student id="002">
9 <name>一班--李四</name>
10 <age>20</age>
11 </student>
12 </class>
13 <class id="002">
14 <student id="001">
15 <name>二班--王五</name>
16 <age>20</age>
17 </student>
18 <student id="002">
19 <name>二班--趙六</name>
20 <age>20</age>
21 </student>
22 </class>
23 </root>
普通方式獲取標簽與xpath方式獲取標簽比較
1 public static void main(String[] args) throws Exception { 2 SAXReader reader = new SAXReader(); 3 Document read = reader.read("./src/NewFile.xml"); 4 Element rootElement = read.getRootElement(); 5
6 //普通方式
7 List<Element> elements = rootElement.elements(); 8 for (Element element : elements) { 9 if("002".equals(element.attributeValue("id"))){ 10 List<Element> elem = element.elements(); 11 for (Element e : elem) { 12 if("002".equals(e.attributeValue("id"))){ 13 Element nameElement = e.element("name"); 14 System.out.println("普通方式: "+nameElement.getText()); 15 } 16 } 17 } 18 } 19 //xpath方式
20 Element nameElement = (Element)rootElement.selectSingleNode("/root/class[@id='002']/student[@id='002']/name"); 21 System.out.println("xpath方式: "+nameElement.getText()); 22 }
執行結果:
普通方式: 二班--趙六
xpath方式: 二班--趙六
可見支持xpath對操作xml文檔有多么方便
簡單介紹xpath的語法,具體請參照:,http://www.w3cschool.cn/index-14.html,附實例文檔
/ 絕對路徑 表示從xml的根位置開始或子元素(一個層次結構) // 相對路徑 表示不分任何層次結構的選擇元素。 * 通配符 表示匹配所有元素 [] 條件 表示選擇什么條件下的元素 @ 屬性 表示選擇屬性節點 and 關系 表示條件的與關系(等價於&&) text() 文本 表示選擇文本內容
SAX解析(官方):
這種解析方式原理是一邊加載,一邊處理,類似於事件的處理機制,適合xml文件較大的情況
核心API:
SAXParser類: 用於讀取和解析xml文件對象
parse(File f, DefaultHandler dh)//解析xml文件 參數一: File,讀取的xml文件。參數二: DefaultHandler,SAX事件處理程序。
簡單代碼實現:詳細請查閱api文檔
1 public class MyDefaultHandler extends DefaultHandler { 2
3 /**
4 * 開始文檔時調用 5 */
6 @Override 7 public void startDocument() throws SAXException { 8 System.out.println("MyDefaultHandler.startDocument()"); 9 } 10
11 /**
12 * 開始標簽時調用 13 * @param qName: 表示開始標簽的標簽名 14 * @param attributes: 表示開始標簽內包含的屬性列表 15 */
16 @Override 17 public void startElement(String uri, String localName, String qName, 18 Attributes attributes) throws SAXException { 19 System.out.println("MyDefaultHandler.startElement()-->"+qName); 20 } 21
22 /**
23 * 結束標簽時調用 24 * @param qName: 結束標簽的標簽名稱 25 */
26 @Override 27 public void endElement(String uri, String localName, String qName) 28 throws SAXException { 29 System.out.println("MyDefaultHandler.endElement()-->"+qName); 30 } 31
32 /**
33 * 讀到文本內容的時調用 34 * @param ch: 表示當前讀完的所有文本內容 35 * @param start: 表示當前文本內容的開始位置 36 * @param length: 表示當前文本內容的長度 37 */
38 @Override 39 public void characters(char[] ch, int start, int length) 40 throws SAXException { 41 //得到當前文本內容
42 String content = new String(ch,start,length); 43 System.out.println("MyDefaultHandler.characters()-->"+content); 44 } 45
46 /**
47 * 結束文檔時調用 48 */
49 @Override 50 public void endDocument() throws SAXException { 51 System.out.println("MyDefaultHandler.endDocument()"); 52 } 53
54 } 55 public class Demo1 { 56 public static void main(String[] args) throws Exception{ 57 //1.創建SAXParser對象
58 SAXParser parser = SAXParserFactory.newInstance().newSAXParser(); 59 //2.調用parse方法
60 /**
61 * 參數一: xml文檔 62 * 參數二: DefaultHandler的子類 63 */
64 parser.parse(new File("./src/contact.xml"), new MyDefaultHandler()); 65 } 66 }
