XML的4種解析方式比較

XML 指可擴展標記語言(EXtensible Markup Language),常用於簡化數據的存儲和共享。

  • xml用途

1.XML 把數據從 HTML 分離

如果您需要在 HTML 文檔中顯示動態數據,那麼每當數據改變時將花費大量的時間來編輯 HTML。

2.XML 簡化數據共享

在真實的世界中,計算機系統和數據使用不兼容的格式來存儲數據,XML 數據以純文本格式進行存儲,

因此提供了一種獨立於軟件和硬件的數據存儲方法。

3.XML 簡化數據傳輸

在互聯網上的不兼容系統之間交換數據;由於可以通過各種不兼容的應用程序來讀取數據,

以 XML 交換數據降低了這種複雜性。

4.XML 簡化平臺變更

升級到新的系統(硬件或軟件平臺),總是非常費時的。必須轉換大量的數據,不兼容的數據經常會丟失。

XML 數據以文本格式存儲。這使得 XML 在不損失數據的情況下,更容易擴展或升級到新的操作系統、

新的應用程序或新的瀏覽器。

  • XML的解析方式

1、DOM解析;

2、SAX解析;

3、JDOM解析;

4、DOM4J解析。

其中前兩種屬於基礎方法,是官方提供的平臺無關的解析方式;後兩種屬於擴展方法,

它們是在基礎的方法上擴展出來的,只適用於java平臺。

1、DOM解析

        DOM(Document Object Model),也即文檔對象模型,DOM 是以層次結構組織的節點或信息片斷的集合。

這個層次結構允許開發人員在樹中尋找特定信息。分析該結構通常需要加載整個文檔和構造層次結構,

然後才能做任何工作。由於它是基於信息層次的,因而 DOM 被認爲是基於樹或基於對象的。

優點:

    ①、整個 Dom 樹都加載到內存中了,所以允許隨機讀取訪問數據。

    ②、允許隨機的對文檔結構進行增刪。

  缺點:

    ①、整個 XML 文檔必須一次性解析完,耗時。

    ②、整個 Dom 樹都要加載到內存中,佔內存。

  適用於:文檔較小,且需要修改文檔內容

public class XmlByDOM {

    private static DocumentBuilderFactory bbf = null;
    private static DocumentBuilder builder = null;
    private static List<Userinfo> userinfos = new ArrayList<Userinfo>();

    static {
        bbf = DocumentBuilderFactory.newInstance();
        try {
            builder = bbf.newDocumentBuilder();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        }
    }

    private Logger logger = Logger.getLogger(this.getClass());

    public static void main(String[] args) {
        String path = XmlByDOM.class.getClassLoader().getResource("dom.xml").getPath();
        System.out.println(path);
        Userinfo userinfo = new Userinfo();
        userinfo.setId("7");
        userinfo.setEmail("[email protected]");
        userinfo.setPhone("12365412301");
        userinfo.setName("田七");
        userinfo.setAddress("高新西區恆大");
        //new XmlByDOM().addNode(userinfo);
        new XmlByDOM().removeNode("7");
        new XmlByDOM().getAll();
    }

    /**
     * <p>
     * 解析xml所有數據
     * </p>
     */
    protected void getAll() {
        try {
            InputStream inputStream = getInputStream();
            Document document = builder.parse(inputStream);
            logger.info("-----> xml " + document.getXmlVersion() + " >> " + document.getXmlEncoding());
            //解析根元素
            Element element = document.getDocumentElement();
            String tagName = element.getTagName();
            logger.info("-----> tagName " + tagName);
            //解析userinfo節點
            NodeList nodeList = element.getElementsByTagName("userinfo");
            if (nodeList != null) {
                for (int i = 0; i < nodeList.getLength(); i++) {
                    Element node = (Element) nodeList.item(i);
                    //獲取userinfo的id屬性
                    String id = node.getAttribute("id");
                    Element name = (Element) node.getElementsByTagName("name").item(0);
                    Element address = (Element) node.getElementsByTagName("address").item(0);
                    Element email = (Element) node.getElementsByTagName("email").item(0);
                    Element phone = (Element) node.getElementsByTagName("phone").item(0);
                    //獲取節點值
                    String nameNodeValue = name.getTextContent();
                    String addressNodeValue = address.getTextContent();
                    String emailNodeValue = email.getTextContent();
                    String phoneNodeValue = phone.getTextContent();
                    logger.info("-----> id " + id + " >> name " + nameNodeValue + " >> address " + addressNodeValue + " >> email " + emailNodeValue + " >> phone " + phoneNodeValue);
                    Userinfo userinfo = new Userinfo();
                    userinfo.setAddress(addressNodeValue);
                    userinfo.setName(nameNodeValue);
                    userinfo.setPhone(phoneNodeValue);
                    userinfo.setEmail(emailNodeValue);
                    userinfos.add(userinfo);
                }
                logger.info(userinfos);
            }
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 根據節點id屬性獲取節點信息
     * @param id
     * @return
     */
    protected Userinfo getById(String id){
        try {
            InputStream inputStream = getInputStream();
            Document document = builder.parse(inputStream);
            logger.info("-----> xml " + document.getXmlVersion() + " >> " + document.getXmlEncoding());
            //解析根元素
            Element element = document.getDocumentElement();
            String tagName = element.getTagName();
            logger.info("-----> tagName " + tagName);
            //解析userinfo節點
            NodeList nodeList = element.getElementsByTagName("userinfo");
            if (nodeList != null) {
                for (int i = 0; i < nodeList.getLength(); i++) {
                    Element node = (Element) nodeList.item(i);
                    //獲取userinfo的id屬性
                    String nodeId = node.getAttribute("id");
                    if(nodeId.equals(id)){
                        Element name = (Element) node.getElementsByTagName("name").item(0);
                        Element address = (Element) node.getElementsByTagName("address").item(0);
                        Element email = (Element) node.getElementsByTagName("email").item(0);
                        Element phone = (Element) node.getElementsByTagName("phone").item(0);
                        //獲取節點值
                        String nameNodeValue = name.getTextContent();
                        String addressNodeValue = address.getTextContent();
                        String emailNodeValue = email.getTextContent();
                        String phoneNodeValue = phone.getTextContent();
                        logger.info("-----> id " + id + " >> name " + nameNodeValue + " >> address " + addressNodeValue + " >> email " + emailNodeValue + " >> phone " + phoneNodeValue);
                        Userinfo userinfo = new Userinfo();
                        userinfo.setAddress(addressNodeValue);
                        userinfo.setName(nameNodeValue);
                        userinfo.setPhone(phoneNodeValue);
                        userinfo.setEmail(emailNodeValue);
                        logger.info(userinfo);
                        userinfos.add(userinfo);
                        return userinfo;
                    }
                }
            }
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    protected void removeNode(String id){
        try {
            InputStream inputStream = getInputStream();
            Document document = builder.parse(inputStream);
            logger.info("-----> xml " + document.getXmlVersion() + " >> " + document.getXmlEncoding());
            //解析根元素
            Element element = document.getDocumentElement();
            String tagName = element.getTagName();
            logger.info("-----> tagName " + tagName);
            //解析userinfo節點
            NodeList nodeList = element.getElementsByTagName("userinfo");
            if (nodeList != null) {
                for (int i = 0; i < nodeList.getLength(); i++) {
                    Element node = (Element) nodeList.item(i);
                    //獲取userinfo的id屬性
                    String nodeId = node.getAttribute("id");
                    if(nodeId.equals(id)){
                        element.removeChild(node);
                        // 同步
                        TransformerFactory.newInstance().newTransformer().transform(new DOMSource(document),
                                new StreamResult("src/main/resources/dom.xml"));
                        logger.info("-----> delete node success !");
                    }
                }
            }
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TransformerConfigurationException e) {
            e.printStackTrace();
        } catch (TransformerException e) {
            e.printStackTrace();
        }
    }

    protected void addNode(Userinfo userinfo){
        try {
            InputStream inputStream = getInputStream();
            Document document = builder.parse(inputStream);
            logger.info("-----> xml " + document.getXmlVersion() + " >> " + document.getXmlEncoding());
            //解析根元素
            Element root = document.getDocumentElement();
            //創建節點
            Element element = document.createElement("userinfo");
            element.setAttribute("id",userinfo.getId());
            root.appendChild(element);
            //創建節點屬性
            Element name = document.createElement("name");
            Element address = document.createElement("address");
            Element email = document.createElement("email");
            Element phone = document.createElement("phone");
            name.setTextContent(userinfo.getName());
            address.setTextContent(userinfo.getAddress());
            email.setTextContent(userinfo.getEmail());
            phone.setTextContent(userinfo.getPhone());
            element.appendChild(name);
            element.appendChild(address);
            element.appendChild(email);
            element.appendChild(phone);
            //將xml樹寫入文件
            TransformerFactory factory = TransformerFactory.newInstance();
            Transformer transformer = factory.newTransformer();
            URL url = this.getClass().getClassLoader().getResource("dom.xml");
            File  file = new File(url.getFile());
            logger.info("-----> file name "+file.getName() +" >> size >>" +file.length());
            //同步數據
            transformer.transform(new DOMSource(document),new StreamResult("src/main/resources/dom.xml"));
            logger.info("-----> add node success");
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TransformerConfigurationException e) {
            e.printStackTrace();
        } catch (TransformerException e) {
            e.printStackTrace();
        }
    }

    protected void updateNode(Userinfo userinfo) throws IOException, SAXException, TransformerException {
        InputStream inputStream = getInputStream();
        Document document = builder.parse(inputStream);
        logger.info("-----> xml " + document.getXmlVersion() + " >> " + document.getXmlEncoding());
        //解析根元素
        Element root = document.getDocumentElement();
        //解析userinfo節點
        NodeList nodeList = root.getElementsByTagName("userinfo");
        if (nodeList != null) {
            for (int i = 0; i < nodeList.getLength(); i++) {
                Element node = (Element) nodeList.item(i);
                //獲取userinfo的id屬性
                String id = node.getAttribute("id");
                if(id.equals(userinfo.getId())){
                    node.getElementsByTagName("name").item(0).setTextContent(userinfo.getName());
                    node.getElementsByTagName("address").item(0).setTextContent(userinfo.getAddress());
                    node.getElementsByTagName("email").item(0).setTextContent(userinfo.getEmail());
                    node.getElementsByTagName("phone").item(0).setTextContent(userinfo.getPhone());
                    //將xml樹寫入文件
                    TransformerFactory factory = TransformerFactory.newInstance();
                    Transformer transformer = factory.newTransformer();
                    URL url = this.getClass().getClassLoader().getResource("dom.xml");
                    File  file = new File(url.getFile());
                    logger.info("-----> file name "+file.getName() +" >> size >>" +file.length());
                    transformer.transform(new DOMSource(document),new StreamResult("src/main/resources/dom.xml"));
                }
            }
        }

    }

    private InputStream getInputStream() {
        return this.getClass().getClassLoader().getResourceAsStream("dom.xml");
    }
}

2、SAX解析

        SAX的全稱是Simple APIs for XML,也即XML簡單應用程序接口。SAX處理的特點是基於事件流的。分析能夠立即開始,而不是等待所有的數據被處理。而且,由於應用程序只是在讀取數據時檢查數據,因此不需要將數據存儲在內存中。這對於大型文檔來說是個巨大的優點。事實上,應用程序甚至不必解析整個文檔;它可以在某個條件得到滿足時停止解析。sax分析器在對xml文檔進行分析時,觸發一系列的事件,應用程序通過事件處理函數實現對xml文檔的訪問,因爲事件觸發是有時序性的,所以sax分析器提供的是一種對xml文檔的順序訪問機制,對於已經分析過的部分,不能再重新倒回去處理。

優點:

    ①、訪問能夠立即進行,不需要等待所有數據被加載。

    ②、只在讀取數據時檢查數據,不需要保存在內存中

    ③、不需要將整個數據都加載到內存中,佔用內存少

    ④、允許註冊多個Handler,可以用來解析文檔內容,DTD約束等等。

  缺點:

    ①、需要應用程序自己負責TAG的處理邏輯(例如維護父/子關係等),文檔越複雜程序就越複雜。

    ②、單向導航,無法定位文檔層次,很難同時訪問同一文檔的不同部分數據,不支持XPath。

    ③、不能隨機訪問 xml 文檔,不支持原地修改xml。

  適用於:文檔較大,只需要讀取文檔數據。

public class XmlBySAX {
private static SAXTransformerFactory saxTransformerFactory = null;
private static List<Userinfo> userinfos = new ArrayList<Userinfo>();

static {
    saxTransformerFactory = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
}

private Logger logger = Logger.getLogger(this.getClass());

public static void main(String[] args) throws IOException, SAXException, TransformerConfigurationException, ParserConfigurationException {
    new XmlBySAX().createXml("src/main/resources/sax.xml");
    new XmlBySAX().new ParseSAX().analysisXml();
}

/**
 * <p>創建xml</p>
 *
 * @param path
 * @throws TransformerConfigurationException
 * @throws FileNotFoundException
 * @throws SAXException
 */
protected void createXml(String path) throws TransformerConfigurationException, FileNotFoundException, SAXException {
    // 創建一個TransformerHandler實例
    TransformerHandler handler = saxTransformerFactory.newTransformerHandler();

    // 創建一個handler轉換器
    Transformer transformer = handler.getTransformer();
    // 換行
    transformer.setOutputProperty(OutputKeys.INDENT, "yes");
    // 字符集
    transformer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
    // 創建一個Result實例連接到XML文件
    Result result = new StreamResult(path);
    handler.setResult(result);
    // 創建一個屬性實例, addAttribute(String uri, String localName, String qName, String type, String value)
    AttributesImpl attr = new AttributesImpl();
    // 打開doc對象
    handler.startDocument();
    logger.info("----->根節點開始");
    // 創建根元素: handler.startElement(uri, 命名空間, 元素名, 屬性列表);//沒有則填null
    handler.startElement(null, null, "root", attr);
    logger.info("----->第一個子節點開始");
    // 每次創建節點前,先清空屬性,放置一些屬性錯誤
    attr.clear();
    // 設置屬性
    attr.addAttribute("", "", "id", "", "1");
    //第一個子節點開始
    handler.startElement("", "", "userinfo", attr);
    attr.clear();
    // 第一個子節點的第一個子節點people
    handler.startElement("", "", "name", attr);
    handler.characters("one name".toCharArray(), 0, "one name".length());
    handler.endElement("", "", "name");
    // 第一個子節點的第二個子節點people
    attr.clear();
    handler.startElement("", "", "address", attr);
    handler.characters("one address".toCharArray(), 0, "one address".length());
    handler.endElement("", "", "address");
    handler.endElement("", "", "userinfo");
    logger.info("----->第一個子節點結束");
    logger.info("----->第二個子節點開始");
    // 每次創建節點前,先清空屬性,放置一些屬性錯誤
    attr.clear();
    // 設置屬性
    attr.addAttribute("", "", "id", "", "2");
    //第一個子節點開始
    handler.startElement("", "", "userinfo", attr);
    attr.clear();
    // 第一個子節點的第一個子節點people
    handler.startElement("", "", "name", attr);
    handler.characters("two name".toCharArray(), 0, "one name".length());
    handler.endElement("", "", "name");
    // 第一個子節點的第二個子節點people
    attr.clear();
    handler.startElement("", "", "address", attr);
    handler.characters("two address".toCharArray(), 0, "one address".length());
    handler.endElement("", "", "address");
    handler.endElement("", "", "userinfo");
    logger.info("----->第一個子節點結束");
    //根節點結束
    handler.endElement(null, null, "root");
    logger.info("----->根節點結束");
    // 關閉doc對象
    handler.endDocument();
    logger.info("sax success !!!");
}

class ParseSAX extends DefaultHandler {
    //存放遍歷集合
    private List<Userinfo> userinfos;
    //構建Student對象
    private Userinfo userinfo;
    //用來存放每次遍歷後的元素名稱(節點名稱)
    private String tagName;

    public List<Userinfo> getUserinfos() {
        return userinfos;
    }

    public void setUserinfos(List<Userinfo> userinfos) {
        this.userinfos = userinfos;
    }

    protected void analysisXml() throws ParserConfigurationException, SAXException, IOException {
        // 創建一個SAX解析工廠
        SAXParserFactory factory = SAXParserFactory.newInstance();
        // 創建一個SAX轉換工具
        SAXParser saxParser = factory.newSAXParser();
        //實例化  DefaultHandler對象
        // 解析XML
        ParseSAX parseSAX = new ParseSAX();
        saxParser.parse(getInputStream(), parseSAX);
        List<Userinfo> userinfos = parseSAX.getUserinfos();
        for (Userinfo userinfo : userinfos) {
            System.out.println("----->" + userinfo);
        }
    }

    //解析根節點 初始化list集合
    @Override
    public void startDocument() throws SAXException {
        userinfos = new ArrayList<Userinfo>();
    }

    //解析根節點下面的子節點開始
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        logger.info("<" + qName + ">");
        if (qName.equals("userinfo")) {
            userinfo = new Userinfo();
            //獲取userinfo節點上的id屬性值
            userinfo.setId(attributes.getValue(0));
        }
        this.tagName = qName;
    }

    //解析根節點下面的子節點結束
    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        logger.info("</" + qName + ">");
        if (qName.equals("userinfo")) {
            this.userinfos.add(this.userinfo);
        }
        this.tagName = null;
    }

    //解析根節點結束
    @Override
    public void endDocument() throws SAXException {
    }

    //解析子節點下面的子節點屬性
    @Override
    public void characters(char ch[], int start, int length) throws SAXException {
        String str = new String(ch, start, length);
        if (!"\n".equals(str)) {
            logger.info(str);
        }
        if (this.tagName != null) {
            String date = new String(ch, start, length);
            if (this.tagName.equals("name")) {
                this.userinfo.setName(date);
            } else if (this.tagName.equals("address")) {
                this.userinfo.setAddress(date);
            }
        }
    }

    private InputStream getInputStream() {
        return this.getClass().getClassLoader().getResourceAsStream("sax.xml");
    }
}

3、JDOM(Java-based Document Object Model)

        JDOM 是一種使用 XML 的獨特 Java 工具包,用於快速開發 XML 應用程序。它基於樹型結構,利用純JAVA的技術對XML文檔實現解析、生成、序列化以及多種操作。JDOM 直接爲JAVA編程服務。它利用更爲強有力的JAVA語言的諸多特性(方法重載、集合概念以及映射),把SAX和DOM的功能有效地結合起來。同時JDOM也是用Java語言讀、寫、操作XML的新API函數,在簡單和高效的前提下,這些API函數被最大限度的優化,以彌補DOM及SAX在實際應用當中的不足之處。在 JDOM 中,XML 元素就是 Element 的實例,XML 屬性就是 Attribute 的實例,XML 文檔本身就是 Document 的實例。因此創建一個新 JDOM 對象就如在 Java 語言中使用 new 操作符一樣容易。

優點:

    ①、使用具體類而不是接口,簡化了DOM的API。

    ②、大量使用了Java集合類,方便了Java開發人員。

  缺點:

    ①、不能處理大於內存的文檔.

    ②、API 簡單,沒有較好的靈活性

 

  需要導入額外包依賴

<dependency>
    <groupId>org.jdom</groupId>
    <artifactId>jdom</artifactId>
    <version>2.0.2</version>
</dependency>
public class XmlByJDOM {

    private Logger logger = Logger.getLogger(this.getClass());

    public static void main(String[] args) throws IOException, JDOMException {
        new XmlByJDOM().createJDOM("src/main/resources/jdom.xml");
        new XmlByJDOM().analysisXml("src/main/resources/jdom.xml");
    }


    protected void analysisXml(String path) throws IOException, JDOMException {
        // 創建一個SAXBuilder對象
        SAXBuilder sab = new SAXBuilder();
        // 調用Build方法,創建Document對象
        Document doc = sab.build(new FileInputStream(path));
        //獲取根節點
        Element root = doc.getRootElement();
        //獲取根下面的子節點
        List<Element> elementList = root.getChildren();
        //遍歷子節點
        if (elementList != null && !elementList.isEmpty()) {
            for (int i = 0; i < elementList.size(); i++) {
                Element element = elementList.get(i);
                //遍歷屬性
                List<Attribute> attributes = element.getAttributes();
                for (Attribute attribute : attributes) {
                    logger.info("節點屬性:" + attribute.getName() + ">>>" + attribute.getValue());
                }
                //遍歷子節點下面的節點屬性(名稱+值)
                List<Element> subBook = element.getChildren();
                for (Element subElement : subBook) {
                    logger.info("子節點屬性:" + subElement.getName() + ">>>" + subElement.getValue());
                }
            }
        }
    }

    protected void createJDOM(String path) throws IOException {
        // 創建一個根節點
        Element rootElement = new Element("root");
        Document doc = new Document(rootElement);

        // 在根節點下創建第一個子節點
        Element rootOneElement = new Element("person");
        rootOneElement.setAttribute(new Attribute("attr", "root one"));

        // 在第一個子節點下創建第一個子節點
        Element childOneElement = new Element("people");
        childOneElement.setAttribute(new Attribute("attr", "child one"));
        childOneElement.setText("person child one");

        // 在第一個子節點下創建第二個子節點
        Element childTwoElement = new Element("people");
        childTwoElement.setAttribute(new Attribute("attr", "child two"));
        childTwoElement.setText("person child two");

        // 在根節點下創建第二個子節點
        Element rootTwoElement = new Element("person");
        rootTwoElement.setAttribute(new Attribute("attr", "root two"));

        // 在第一個子節點下創建第一個子節點
        Element oneChildOneElement = new Element("people");
        oneChildOneElement.setAttribute(new Attribute("attr", "child one"));
        oneChildOneElement.setText("person child one");

        // 在第一個子節點下創建第二個子節點
        Element twoChildTwoElement = new Element("people");
        twoChildTwoElement.setAttribute(new Attribute("attr", "child two"));
        twoChildTwoElement.setText("person child two");

        rootOneElement.addContent(childOneElement);
        rootOneElement.addContent(childTwoElement);

        rootTwoElement.addContent(oneChildOneElement);
        rootTwoElement.addContent(twoChildTwoElement);

        doc.getRootElement().addContent(rootOneElement);
        doc.getRootElement().addContent(rootTwoElement);

        // 創建xml輸出流操作類
        XMLOutputter xmlOutput = new XMLOutputter();

        // 設置xml格式化的屬性
        Format f = Format.getRawFormat();
        f.setIndent("  "); // 文本縮進
        f.setTextMode(Format.TextMode.TRIM_FULL_WHITE);
        xmlOutput.setFormat(f);

        // 把xml文件輸出到指定的位置
        xmlOutput.output(doc, new FileOutputStream(new File(path)));
    }
}

4、DOM4J(Document Object Model for Java)

Dom4j是一個易用的、開源的庫,用於XML、XPath和XSLT。它應用於Java平臺,採用了Java集合框架並完全支持DOM、SAX和JAXP。在Java開發社區裏,DOM4J的使用最爲廣泛。JDOM的操作非常簡單,但是在處理大XML文件時性能表現不佳,解析10M文檔時就會內存溢出。而DOM4J是一個非常優秀的Java XML API,具有性能優異、功能強大和易於使用的特點,同時它也是一個開放源代碼的軟件,DOM4J使用大量的接口,這也是它被認爲比JDOM靈活的原因。如今我們可以看到越來越多的Java軟件都在使用DOM4J來讀寫XML。DOM4J的官方地址是“http://www.dom4j.org/”,由於在實際項目開發中,採用DOM4J的佔主流。

優點:

    ①、大量使用了Java集合類,方便Java開發人員,同時提供一些提高性能的替代方法。

    ②、支持XPath。查找節點特別快

    ③、靈活性高。

  缺點:

    ①、大量的使用了接口,API複雜,理解難。

    ②、移植性差。

 注:XPath是一門在 XML 文檔中查找信息的語言。

導入額外的maven依賴

<dependency>
    <groupId>dom4j</groupId>
    <artifactId>dom4j</artifactId>
    <version>1.6.1</version>
</dependency>
public class XmlByDOM4J {

    private static String path = "src/main/resources/dom4j.xml";

    private Logger logger = Logger.getLogger(this.getClass());

    public static void main(String[] args) throws Exception {
        new XmlByDOM4J().add();
        new XmlByDOM4J().update();
        new XmlByDOM4J().delete();
        new XmlByDOM4J().read();
    }

    protected void add() throws DocumentException, IOException {
        SAXReader reader = new SAXReader();
        Document document = reader.read(new File(path));
        //獲取根節點並添加子節點
        Element student = document.getRootElement().element("student");
        student.addElement("schoolName").setText("南充");
        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding("utf-8");

        XMLWriter writer = new XMLWriter(new FileOutputStream(path), format);
        writer.write(document);
        writer.close();
    }

    public void update() throws Exception {
        SAXReader reader = new SAXReader();
        Document document = reader.read(new File(path));

        Element student = (Element) document.getRootElement().elements("student").get(0);
        student.element("schoolName").setText("湖南1");

        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding("utf-8");

        XMLWriter writer = new XMLWriter(new FileOutputStream(path), format);
        writer.write(document);
        writer.close();
    }

    public void delete() throws Exception {
        SAXReader reader = new SAXReader();
        Document document = reader.read(new File(path));

        Element student = document.getRootElement().element("student");
        Element schoolName = student.element("schoolName");
        schoolName.getParent().remove(schoolName);

        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding("utf-8");

        XMLWriter writer = new XMLWriter(new FileOutputStream(path), format);
        writer.write(document);
        writer.close();
    }

    public void read() throws Exception {
        SAXReader reader = new SAXReader();
        Document document = reader.read(new File(path));

        //得到根節點
        Element root = document.getRootElement();
        //遍歷已知<student><student>節點
        //List<Element> students = root.elements("student");
        //遍歷未知節點
        List<Element> students = root.elements();
        for (Element student : students) {
            //未知屬性名情況下
            List<Attribute> attributeList = student.attributes();
            for (Attribute attr : attributeList) {
                logger.info("未知屬性名 >>> " + attr.getName() + ": " + attr.getValue());
            }
            //已知屬性名情況下
            logger.info("已知屬性名>>> " + student.attributeValue("attr"));
            //未知子元素名
            List<Element> elements = student.elements();
            for (Element element : elements) {
                logger.info("未知子元素名 >>> " + element.getName() + ": " + element.getText());
            }
            //已知子元素名
            Element people = student.element("people");
            //獲取<name><name>中間的值
            String text = people.getText();
            //獲取<name sex="xxx"><name>中間的sex值
            String attr = people.attributeValue("attr");
            logger.info(text + " 已知子元素名 >>> " + text + " : " + attr);
        }
    }
}
  • 解析方式對比

DOM4J性能最好,連Sun的JAXM也在用DOM4J。目前許多開源項目中大量採用DOM4J,例如大名鼎鼎的Hibernate也用DOM4J來讀取XML配置文件。如果不考慮可移植性,那就採用DOM4J。

JDOM和DOM在性能測試時表現不佳,在測試10M文檔時內存溢出,但可移植。在小文檔情況下還值得考慮使用DOM和JDOM.雖然JDOM的開發者已經說明他們期望在正式發行版前專注性能問題,但是從性能觀點來看,它確實沒有值得推薦之處。另外,DOM仍是一個非常好的選擇。DOM實現廣泛應用於多種編程語言。它還是許多其它與XML相關的標準的基礎,因爲它正式獲得W3C推薦(與基於非標準的Java模型相對),所以在某些類型的項目中可能也需要它(如在JavaScript中使用DOM)。

SAX表現較好,這要依賴於它特定的解析方式-事件驅動。一個SAX檢測即將到來的XML流,但並沒有載入到內存(當然當XML流被讀入時,會有部分文檔暫時隱藏在內存中)。

總結:如果XML文檔較大且不考慮移植性問題建議採用DOM4J;如果XML文檔較小則建議採用JDOM;如果需要及時處理而不需要保存數據則考慮SAX。

附上源碼gitee地址

參考:https://cloud.tencent.com/developer/article/1012671

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章