JDK提供的XML解析方式分為兩種:DOM方式和SAX方式
DOM:Document Object Model。需要讀取整個XML文檔,先需要在內存中構架代表整個DOM樹的Document對象,可以進行隨機訪問. 需要考慮內存.適合增刪改
SAX:Simple API for XML。采用事件驅動的方式解析XML文件,邊讀邊對文檔進行處理.適合讀取
其他的xml解析包:Dom4J, PullParser(安卓)
Dom4J實現類似SAX方式, API類似DOM方式
DOM @JDK
public class DomTest { // 解析xml獲取document對象 private Document getDocument() throws ParserConfigurationException, SAXException, IOException { // 1. 獲得工廠 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); // 2. 獲得 builder對象 DocumentBuilder builder = factory.newDocumentBuilder(); // 3. 解析xml得帶document對象 Document document = builder.parse("src/book.xml"); return document; } // 將內存中的document對象寫回xml文件中 private void writeBack2Xml(Document document) throws TransformerFactoryConfigurationError, TransformerConfigurationException, TransformerException { TransformerFactory factory = TransformerFactory.newInstance(); Transformer transformer = factory.newTransformer(); transformer.transform(new DOMSource(document), new StreamResult("src/book.xml")); } // 讀取節點文本 @Test public void testReadContent() throws Exception{ Document document = getDocument(); //根據標簽名獲得節點列表 NodeList nodeList = document.getElementsByTagName("書"); System.out.println("長度 : " + nodeList.getLength()); // 返回第一個節點 Node firstNode = nodeList.item(0); // 返回文本內容 String result = firstNode.getTextContent(); System.out.println(result); } // 讀取節點的屬性值 @Test public void testReadAttribute() throws Exception{ Document document = getDocument(); NodeList nodeList = document.getElementsByTagName("書"); // 確認本Node為元素節點后加強轉 Node node = nodeList.item(0); if (node instanceof Element) { Element firstElement = (Element) node; String result = firstElement.getAttribute("出版社"); System.out.println(result); } } // 添加節點 @Test public void testAddPrice() throws Exception, SAXException, IOException{ Document document = getDocument(); Node firstNode = document.getElementsByTagName("書").item(0); Element newElement = document.createElement("售價"); newElement.setTextContent("79.00元"); firstNode.appendChild(newElement); writeBack2Xml(document); //寫回 } // 刪除節點 @Test public void testDelete() throws Exception, SAXException, IOException{ Document document = getDocument(); NodeList priceNodeList = document.getElementsByTagName("售價"); for (int i = 0; i < priceNodeList.getLength(); i++) { Node node = priceNodeList.item(i); if("39.00元".equals(node.getTextContent())){ // 從父節點刪除子節點, 類似dom的api node.getParentNode().removeChild(node); } } writeBack2Xml(document); } // 打印所有元素節點的名稱 @Test public void testPrintAllElementsName() throws Exception, SAXException, IOException{ Document document = getDocument(); // 遞歸打印 printAllElementsName(document); } public void printAllElementsName(Node node){ // 打印本節點 if(Node.ELEMENT_NODE==node.getNodeType()){ System.out.println(node.getNodeName()); } // 處理子節點 NodeList childNodes = node.getChildNodes(); for (int i = 0; i < childNodes.getLength(); i++) { //遞歸出口: 循環完成 Node item = childNodes.item(i); printAllElementsName(item); } } }
SAX @JDK
public class SaxTest { public static void main(String[] args) throws Exception, SAXException { SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newSAXParser(); XMLReader reader = parser.getXMLReader(); reader.setContentHandler(new MyDefaultHandler()); reader.parse("src/book.xml"); } } class MyDefaultHandler extends DefaultHandler { // 作為被調用方, 流程不是這邊控制, 所以定義狀態位或計數器來標記流程進行的位置 private boolean isPrice = false; private int count =1; @Override public void startElement(String uri, String localName, String qName, // qName標簽名 Attributes attributes) throws SAXException { if ("售價".equals(qName)) { isPrice = true; count++; } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { if ("售價".equals(qName)) { isPrice = false; } } // 讀到文本了 @Override public void characters(char[] ch, int start, int length) throws SAXException { if (isPrice&&count==3) { System.out.println("文本: " + new String(ch, start, length)); } } }
Dom4J
public class Dom4JTest { private Document getDocument() throws DocumentException { // 獲得 代表 xml 文件的 document 對象 SAXReader reader = new SAXReader(); Document document = reader.read("src/book.xml"); return document; } private void wirteBack2Xml(Document document) throws UnsupportedEncodingException, FileNotFoundException, IOException { OutputFormat format = OutputFormat.createPrettyPrint(); format.setEncoding("UTF-8"); XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"), format); writer.write(document); writer.close(); } // 讀取節點的文本內容 // 由於 dom4j采用sax方式去解析的xml文檔, 所以dom4j不能直接獲得深層次的某個節點, 需要一級級獲得 @Test public void testReadContent() throws Exception{ Document document = getDocument(); Element rootElement = document.getRootElement(); Element firstLevelElement = rootElement.element("ele1"); Element secondLevelElement = firstLevelElement.element("ele2"); String value = secondLevelElement.getText(); System.out.println(value); } // 讀取屬性值 @Test public void testReadAttribute() throws Exception{ Document document = getDocument(); Element rootElement = document.getRootElement(); List<Element> list = rootElement.elements("書"); Element secondElement = list.get(1); Attribute attribute = secondElement.attribute("出版社"); String value = attribute.getValue(); System.out.println(value); } // 添加節點 @Test public void testAddPrice() throws Exception{ Document document = getDocument(); Element rootElement = document.getRootElement(); Element secondBookElement = (Element) rootElement.elements("書").get(1); // 創建新節點 secondBookElement.addElement("newEle").setText("this is new Element"); wirteBack2Xml(document); } // 刪除節點 @Test public void testDeletePrice() throws Exception{ Document document = getDocument(); Element rootElement = document.getRootElement(); Element secondBookElement = (Element) rootElement.elements("書").get(1); Element targetBookPrice = (Element) secondBookElement.elements("售價").get(0); // 拿到父節點, 然后刪除這個子節點 targetBookPrice.getParent().remove(targetBookPrice); wirteBack2Xml(document); } }