17.JAVA-Dom、Sax解析XML詳解
在JAVA中,解析有三種方式:
- Dom解析(支援改刪,耗記憶體)、
- Sax解析(不支援改刪,不耗記憶體)、
- Pull解析(在Android中推薦使用的一種解析XML的方式,在下章學習)、
1.支援Dom與Sax解析的開發包
分為兩種.
- JAXP: 由sun公司推出的解析標準實現(本章只學習該包的解析方法)
- Dom4j: 一種開源的解析開發包.
jaxp是java api中自帶的一個包,而dom4j需要我們加入jar檔案才能使用
2.JAXP使用
JAXP(Java API for XMLProcessing)主要由下面幾個包組成:
- org.w3c.dom: 定義DOM解析器的標準介面
- org.w3c.sax: 定義SAX解析器的標準介面
- javax.xml:提供解析xml文件的類
- javax.xml.parsers:提供了用來獲取DOM和SAX解析器物件的工廠類,比如:DocumentBuilderFactory(建立DOM解析器物件)、SAXParserFactory,如下圖所示:
3.使用JAXP進行DOM解析
會將XML文件全部內容都讀入記憶體中,並且將文件裡的每個資料都建立為一個個物件,所以方便增刪改.並且遍歷簡單。
DOM的缺點主要表現在:效率低,解析速度慢,記憶體佔用量過高,對於大檔案來說幾乎不可能使用。
3.1 persons.xml示例如下:
<?xml version="1.0" encoding="UTF-8"?> <persons> <person> <姓名>張三</姓名> <性別>男</性別> <年齡>22</年齡> </person> <person> <姓名>李四</姓名> <性別>男</性別> <年齡>17</年齡> </person> </persons>
3.2 DOM讀取xml步驟
1.通過DocumentBuilderFactory.newInstance()靜態方法得到建立 DOM 解析器的工廠物件(DocumentBuilderFactory)
2.通過工廠物件的newDocumentBuilder()方法得到 DocumentBuilder解析器物件
3.然後通過DocumentBuilder解析器物件的parse(filename)方法來得到解析xml文件的Document物件
4.通過Document物件的成員方法來獲取XML文件的元素資訊,比如getElementsByTagName("person")方法來獲取xml檔案中的person元素(返回的類為NodeList,儲存person所有的集合,比如list.item(0). getTextContent()列印第一個元素的內容)
具體實現方法如下:
@Test public void DomReadXml() throws Exception{ //獲取工廠例項 DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); //建立builder DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); //解析xml Document document = documentBuilder.parse("src//persons.xml"); //讀出元素內容 System.out.println("第一個姓名:"+document.getElementsByTagName("姓名").item(0).getTextContent()); //讀出元素內容 System.out.println("第二個姓名:"+document.getElementsByTagName("姓名").item(1).getTextContent()); }
列印:
3.3 DOM修改xml步驟
1.先將xml資訊讀取到Document物件中
2.然後通過getElementsByTagName("person")方法來獲取xml檔案中的person元素(返回的類為NodeList),然後通過NodeList.item(i).setTextContent("text")來修改節點內容
3.修改完成後通過Transformer類的transform(Source , Result )方法來將改過的Document物件寫入XML檔案
具體實現方法如下:
@Test public void DomWriteXml() throws Exception{ DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); //1.先將xml資訊讀取到Document物件中 Document document = documentBuilder.parse("src//persons.xml"); //2.修改第一個節點內容為99 document.getElementsByTagName("年齡").item(0).setTextContent("99"); //3.通過transform(Source , Result )方法來將改過的Document物件寫入XML檔案 Transformer transformer = TransformerFactory.newInstance().newTransformer(); Source xmlSource = new DOMSource(document); Result outputTarget = new StreamResult("src//persons.xml"); transformer.transform(xmlSource, outputTarget); }
4.使用JAXP進行SAX解析
sax解析的優點是邊讀邊解析,佔用記憶體少,解析速度快,缺點是不能對XML檔案改刪,並且不支援向後遍歷,只能從頭到尾讀取.
4.1 SAX讀取XML步驟
1.獲取SAXParser物件,該物件通過SAXParserFactory構造
2.通過SAXParser.getXMLReader()獲取XMLReder物件
3.實現一個ContentHandler的子類(PersonHandler),其實就是構造一個DefaultHandler的子類(因為contentHandler介面太多方法沒實現),如下圖所示:
然後重寫startElement()等方法(用來實現具體的XML讀取)
4.再呼叫XMLReder物件的setContentHandler(new PersonHandler())來設定我們要解析的具體handler
5.最後呼叫XMLReder物件的parse(file),開始進行解析
4.2 Myhandler需要重寫的方法有以下幾個
startDocument(); //當文件開始解析時,觸發該方法 endDocument(); //當文件解析完成時,觸發該方法 startElement(String uri, String localName, String qName, Attributes attributes) //解析到開始元素時,觸發該方法 endElement(String uri, String localName, String qName) //解析到結束元素時,觸發該方法 //uri:名稱空間URI,如果元素沒有名稱空間,沒有則為空字串。 //localName:本地名稱(不帶字首),沒有則為空字串。 //qName:元素名(帶有字首),如果元素名不可用則為空字串。 //attributes:該元素的所有屬性。如果沒有屬性,則為空物件. characters(char[] ch, int start, int length) //接收字元內容時,觸發該方法,比如"<姓名>李四</姓名>",當解析到"李四"時,會呼叫到該方法,並將"李四"作為引數傳遞進來.
4.3 persons.xml示例如下:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <persons> <person> <姓名>張三</姓名> <性別>男</性別> <年齡>99</年齡> </person> <person> <姓名>李四</姓名> <性別>男</性別> <年齡>17</年齡> </person> </persons>
4.4 Person類如下所示:
public class Person { private String name; private String sex; private String age; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } @Override public String toString() { return "Person [name=" + name + ", sex=" + sex + ", age=" + age + "]"; } }
4.5 SaxParseTest類如下所示:
package com.my.xmlparser; import java.util.ArrayList; import java.util.List; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.junit.Test; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.DefaultHandler; import com.my.bean.Person; class PersonHandler extends DefaultHandler{ private String status=null; private ArrayList<Person> persons=null; private Person person=null; @Override public void startDocument() throws SAXException { persons = new ArrayList<Person>(); person = new Person(); } @Override public void endDocument() throws SAXException { for(Person person1:persons){ //列印所有資訊 System.out.println(person1); } } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { status = qName; } @Override public void endElement(String uri, String localName, String qName) throws SAXException { status =null; if("person".equals(qName)) //新增一個person { persons.add(person); person = new Person(); } } @Override public void characters(char[] ch, int start, int length) throws SAXException { String text = new String(ch,start,length); if(status == null) return; else if("姓名".equals(status)) { person.setName(text); } else if("性別".equals(status)) { person.setSex(text); } else if("年齡".equals(status)) { person.setAge(text); } } } public class SaxParseTest { @Test public void SaxParse() throws Exception{ //1.獲取SAXParser物件,該物件通過SAXParserFactory構造 SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); SAXParser saxParser = saxParserFactory.newSAXParser(); //2.通過SAXParser.getXMLReader()獲取XMLReder物件 XMLReader reader = saxParser.getXMLReader(); //3~4:實現一個ContentHandler的子類(Myhandler),然後來設定我們要解析的具體handler reader.setContentHandler(new PersonHandler()); //5.最後呼叫XMLReder物件的parse(file),開始進行解析 reader.parse("src//persons.xml"); } }
測試執行:
未完待續,下章學習pull