XML的兩種解析方式


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);
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM