在Java中使用Sax解析xml
在Java中使用Dom解析xml
Dom解析功能強大,可增刪改查,操作時會將xml文檔對象的方式讀取到內存中,因此適用於小文檔
Sax解析是從頭到尾逐行逐個元素讀取內容,修改較為不便,但適用於只讀的大文檔
Sax采用事件驅動的方式解析文檔,簡單說,如同看電影一樣,從頭到尾看一遍就完了,不能回退(Dom可來來回回讀取)
在看電影的過程中,每遇到一個情節,一段淚水,一次擦肩,你都會調動大腦和神經去接收或處理這些信息
同樣,在Sax的解析過程中,讀取到文檔開頭、結尾,元素的開頭和結尾都會觸發一些回調方法,你可以在這些回調方法中進行相應事件處理
這四個方法是:startDocument() 、 endDocument()、 startElement()、 endElement
此外,光讀取到節點處是不夠的,我們還需要characters()方法來仔細處理元素內包含的內容
將這些回調方法集合起來,便形成了一個類,這個類也就是我們需要的觸發器
如上圖,在觸發器中,首先開始讀取文檔,然后開始逐個解析元素,每個元素中的內容會返回到characters()方法
接着結束元素讀取,所有元素讀取完后,結束文檔解析。
現在我們開始創建觸發器這個類,要創建這個類首先需要繼承DefaultHandler
創建SaxHandler類
1 import org.xml.sax.Attributes; 2 import org.xml.sax.SAXException; 3 import org.xml.sax.helpers.DefaultHandler; 4 5 6 public class SaxHandler extends DefaultHandler { 7 8 /* 此方法有三個參數 9 arg0是傳回來的字符數組,其包含元素內容 10 arg1和arg2分別是數組的開始位置和結束位置 */ 11 @Override 12 public void characters(char[] arg0, int arg1, int arg2) throws SAXException { 13 String content = new String(arg0, arg1, arg2); 14 System.out.println(content); 15 super.characters(arg0, arg1, arg2); 16 } 17 18 @Override 19 public void endDocument() throws SAXException { 20 System.out.println("\n…………結束解析文檔…………"); 21 super.endDocument(); 22 } 23 24 /* arg0是名稱空間 25 arg1是包含名稱空間的標簽,如果沒有名稱空間,則為空 26 arg2是不包含名稱空間的標簽 */ 27 @Override 28 public void endElement(String arg0, String arg1, String arg2) 29 throws SAXException { 30 System.out.println("結束解析元素 " + arg2); 31 super.endElement(arg0, arg1, arg2); 32 } 33 34 @Override 35 public void startDocument() throws SAXException { 36 System.out.println("…………開始解析文檔…………\n"); 37 super.startDocument(); 38 } 39 40 /*arg0是名稱空間 41 arg1是包含名稱空間的標簽,如果沒有名稱空間,則為空 42 arg2是不包含名稱空間的標簽 43 arg3很明顯是屬性的集合 */ 44 @Override 45 public void startElement(String arg0, String arg1, String arg2, 46 Attributes arg3) throws SAXException { 47 System.out.println("開始解析元素 " + arg2); 48 if (arg3 != null) { 49 for (int i = 0; i < arg3.getLength(); i++) { 50 // getQName()是獲取屬性名稱, 51 System.out.print(arg3.getQName(i) + "=\"" + arg3.getValue(i) + "\""); 52 } 53 } 54 System.out.print(arg2 + ":"); 55 super.startElement(arg0, arg1, arg2, arg3); 56 } 57 }
測試類:
1 public class TestDemo { 2 3 public static void main(String[] args) throws Exception { 4 // 1.實例化SAXParserFactory對象 5 SAXParserFactory factory = SAXParserFactory.newInstance(); 6 // 2.創建解析器 7 SAXParser parser = factory.newSAXParser(); 8 // 3.獲取需要解析的文檔,生成解析器,最后解析文檔 9 File f = new File("books.xml"); 10 SaxHandler dh = new SaxHandler(); 11 parser.parse(f, dh); 12 } 13 }
Dom解析:
1 public class Demo { 2 3 public static void main(String[] args) throws Exception { 4 //創建解析器工廠實例,並生成解析器 5 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 6 DocumentBuilder builder = factory.newDocumentBuilder(); 7 //創建需要解析的文檔對象 8 File f = new File("books.xml"); 9 //解析文檔,並返回一個Document對象,此時xml文檔已加載到內存中 10 //好吧,讓解析來得更猛烈些吧,其余的事就是獲取數據了 11 Document doc = builder.parse(f); 12 13 //獲取文檔根元素 14 //你問我為什么這么做?因為文檔對象本身就是樹形結構,這里就是樹根 15 //當然,你也可以直接找到元素集合,省略此步驟 16 Element root = doc.getDocumentElement(); 17 18 //上面找到了根節點,這里開始獲取根節點下的元素集合 19 NodeList list = root.getElementsByTagName("book"); 20 21 for (int i = 0; i < list.getLength(); i++) { 22 //通過item()方法找到集合中的節點,並向下轉型為Element對象 23 Element n = (Element) list.item(i); 24 //獲取對象中的屬性map,用for循環提取並打印 25 NamedNodeMap node = n.getAttributes(); 26 for (int x = 0; x < node.getLength(); x++) { 27 Node nn = node.item(x); 28 System.out.println(nn.getNodeName() + ": " + nn.getNodeValue()); 29 } 30 //打印元素內容,代碼很糾結,差不多是個固定格式 31 System.out.println("title: " +n.getElementsByTagName("title").item(0).getFirstChild().getNodeValue()); 32 System.out.println("author: " + n.getElementsByTagName("author").item(0).getFirstChild().getNodeValue()); 33 System.out.println(); 34 } 35 } 36 37 }