閒聊下Java與XML互轉的N種實現方式

最近又用到XML,發現也有必要聊聊XML的幾種方式。

1,如果只是簡單生成或者解析,自己寫一個幫助類就行,下面這個是我前段時間用遞歸寫的,優勢方便可以擴展

複製代碼
import java.util.ArrayList;
import java.util.List;

/**
 * 
 * @author [email protected]
 * 
 *         TODO manage node and value.and format the node to xml file
 * 
 */
public class XMLSimpleNode implements SimpleNode {
    private String nodeName;
    private String value;
    List<SimpleNode> childs;
    private String header;

    public XMLSimpleNode(String nodeName) {
        this.nodeName = nodeName;
        childs = new ArrayList<SimpleNode>(2);
    }

    public String getNodeName() {
        return nodeName;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.benson.another.SimpleXMLFileUtil#setNodeName(java.lang.String)
     */
    public void setNodeName(String nodeName) {
        this.nodeName = nodeName;
    }

    public String getValue() {
        return value;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.benson.another.SimpleXMLFileUtil#setValue(java.lang.String)
     */
    public void setValue(String value) {
        this.value = value;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.benson.another.SimpleXMLFileUtil#addChild(org.benson.another.XMLItem)
     */
    public void addChild(SimpleNode node) {
        childs.add(node);
    }

    public String startTag() {
        StringBuffer tagSart = new StringBuffer("<");
        tagSart.append(nodeName);
        tagSart.append(">");
        return tagSart.toString();
    }

    public String endTag() {
        StringBuffer tagEnd = new StringBuffer("</");
        tagEnd.append(nodeName);
        tagEnd.append(">");
        return tagEnd.toString();
    }

    public String getHeader() {
        return header;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.benson.another.SimpleXMLFileUtil#setHeader(java.lang.String)
     */
    public void setHeader(String header) {
        this.header = header;
    }

    /**
     * ToDo format the node to xml file
     */
    public String formartXMLFile() {
        StringBuffer xmlFileBf = new StringBuffer();
        xmlFileBf.append(this.getHeader());
        return this.getNode(this, xmlFileBf).toString();
    }

    /**
     * 
     * @param node
     * @param xmlFileBf
     * @return get XML content by node
     */
    private StringBuffer getNode(SimpleNode node, StringBuffer xmlFileBf) {
        XMLSimpleNode xmlNode = (XMLSimpleNode) node;
        XMLSimpleNode xmlNodeItem = null;
        xmlFileBf.append(xmlNode.startTag());
        if (xmlNode.childs.size() != 0) {
            for (int i = 0; i < xmlNode.childs.size(); i++) {
                xmlNodeItem = (XMLSimpleNode) xmlNode.childs.get(i);
                getNode(xmlNodeItem, xmlFileBf);
            }
        }
        if (xmlNode.getValue() != null)
            xmlFileBf.append(xmlNode.getValue());
        xmlFileBf.append(xmlNode.endTag());
        return xmlFileBf;
    }

    public static void main(String[] args) {
        SimpleNode xmlNode = new XMLSimpleNode("root");
        xmlNode.setHeader("<?xml version=\"1.0\" encoding=\"UTF-8\" ?> ");
        SimpleNode chridNode1 = new XMLSimpleNode("chrid1");
        SimpleNode chridNode2 = new XMLSimpleNode("chrid2");
        SimpleNode chridNode3 = new XMLSimpleNode("chrid3");
        SimpleNode chridNode11 = new XMLSimpleNode("chrid11");
        SimpleNode chridNode12 = new XMLSimpleNode("chrid12");
        SimpleNode chridNode13 = new XMLSimpleNode("chrid13");
        chridNode11.setValue("chridNode11 Value");
        chridNode12.setValue("chridNode12 Value");
        chridNode13.setValue("chridNode13 Value");
        chridNode2.setValue("chridNode2 Value");
        chridNode3.setValue("chridNode3 value");
        chridNode1.addChild(chridNode11);
        chridNode1.addChild(chridNode12);
        chridNode1.addChild(chridNode13);
        xmlNode.addChild(chridNode1);
        xmlNode.addChild(chridNode2);
        xmlNode.addChild(chridNode3);
        System.out.println(xmlNode.formartXMLFile());
    }


}
複製代碼

 

輸出結果如下

<?xml version="1.0" encoding="UTF-8" ?> <root><chrid1><chrid11>chridNode11 Value</chrid11><chrid12>chridNode12 Value</chrid12><chrid13>chridNode13 Value</chrid13></chrid1><chrid2></chrid2><chrid3></chrid3></root>

其實個人感覺和jdom就有點類似了,擴展下就好了

 

2,用DOM,這個東西也是把XML組成樹,然後放進內存中,但是遵循了w3c的原則,方便移植,兼容性好,你可以切換各種實現方式如,Xerces,或者Crimon,再或者其它,修改jaxp.propertie,JDK默認是Xerces。

缺點也很明顯,一次性加載進內存,容易造成內存溢出,API也不好用,不支持接點的隨機訪問

順便說句,最近看源碼發現spring就是用這個做配置文件解析的 2. spring中IOC的實現源碼篇【analyze spring framework source】,所以當spring配置文件過多時也會報out memory了

 

注意:沒找到?因爲sun的JDK默認是不存在的,IBM的JDK存在,新建一個就行 ,

放在  ${JAVA_HOME}/lib/jaxp.properties,

修改成 javax.xml.parsers.SAXParserFactory=org.apache.xerces.jaxp.SAXParserFactoryImpl

常見IBM JDK兼容性錯誤,一般也是這個原因引起:

javax.xml.parsers.FactoryConfigurationError: Provider null could not be instantiated:         

java.lang.NullPointerException  

 

3.jdom ,這個也是基於DOM實現的,但其API比DOM好用,更靈活,不是標準W3C

4.SAX,這個是逐行解析和構建XML文件,優點就是不用把XML整個結構都加進內存,適用於大批量的XML文件導入導出,缺點:每次都要去讀文件,肯定沒有直接內存裏速度快了

附上:SAXP解析XML的筆記 挺詳細的

 

5.DOM4J,原來是JDOM的分支,現獨立開發,處於JDOM於SAX之間,即支持把XML放進內存,但可以讀取時選擇性刪除DOM節點減少內存使用,所以也可以處理大數據XML文件,傳說hibernate的配置文件也是基於dom4J(沒看hibernate源碼)

優點,提供讀取事件處理,提供Visitor處理,也可以處理大數據XML文件(每次讀完節點後刪除)當然處理大數據咋樣也不如SAX節省內存了,畢竟要讀完一個element纔會觸發

百度百科的介紹的不錯 http://baike.baidu.com/view/1460716.htm

 

show you the code. 下面就是分別用這4中方法讀寫XML

複製代碼
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.dom4j.ElementHandler;
import org.dom4j.ElementPath;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/**
 * 
 * @author Love Eat large meat bun
 * @TD use the SAX DOM JDOM to build and parser xml file
 * @email [email protected]
 */
public class Test4XML extends DefaultHandler implements ElementHandler {
    private String tagName = "";
    public static final String FILE_PATH = "D://saxText.xml";

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        System.out.println(tagName + "===SAX===>" + new String(ch, start, length));
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        tagName = qName;
    }

    public static void removeFile() {
        System.out.println("the file have be delete is " + new File(FILE_PATH).delete());
    }

    @Override
    public void onEnd(ElementPath paramElementPath) {
        // TODO print node 
        org.dom4j.Element ele=paramElementPath.getCurrent();
        System.out.println(ele.getName()+"===DOM4J====>"+ele.getText());
        ele.detach();//after read /root/user node .remove it from memory,avoid out of memory
    }

    @Override
    public void onStart(ElementPath paramElementPath) {
    }

    public void writeXMLByDOM() throws Exception {
        DocumentBuilderFactory buildFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder = buildFactory.newDocumentBuilder();
        Document doc = documentBuilder.newDocument();
        Element ele = doc.createElement("root");
        Element ele1 = doc.createElement("user");
        ele1.setTextContent("largeMeatBun");
        ele.appendChild(ele1);
        Element ele2 = doc.createElement("email");
        ele2.setTextContent("[email protected]");
        ele.appendChild(ele2);
        doc.appendChild(ele);
        DOMSource xmlSource = new DOMSource(doc);
        TransformerFactory transFactory = TransformerFactory.newInstance();
        Transformer transformer = transFactory.newTransformer();
        FileOutputStream outputTarget = new FileOutputStream(FILE_PATH);
        transformer.transform(xmlSource, new StreamResult(outputTarget));
        outputTarget.close();//the output steam can't auto to close
    }

    public void readerDOMParseXML() throws Exception {
        DocumentBuilderFactory buildFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder = buildFactory.newDocumentBuilder();
        FileInputStream file = new FileInputStream(FILE_PATH);
        Document document = documentBuilder.parse(file);
        file.close();//the xml data have load in memory
        Element node = document.getDocumentElement();
        NodeList nodelist = node.getChildNodes();
        for (int i = 0; i < nodelist.getLength(); i++)
            System.out.println(nodelist.item(i).getNodeName() + "===DOM===>" + nodelist.item(i).getTextContent());
    }

    public void writeXMLBySAX() throws Exception {
        //sax writer
        OutputStream SAXOut = new FileOutputStream(FILE_PATH);
        XMLStreamWriter xmlWrite = XMLOutputFactory.newInstance().createXMLStreamWriter(SAXOut);
        xmlWrite.writeStartDocument("utf-8", "1.0");
        xmlWrite.writeStartElement("root");
        xmlWrite.writeStartElement("user");
        xmlWrite.writeCharacters("largeMeatBun");
        xmlWrite.writeEndElement();
        xmlWrite.writeStartElement("email");
        xmlWrite.writeCharacters("[email protected]");
        xmlWrite.writeEndElement();
        xmlWrite.writeEndElement();
        xmlWrite.writeEndDocument();
        xmlWrite.close();
        SAXOut.close();
    }

    public void parseXMLbySAX() throws Exception {
        //sax parser
        InputStream SAXIn = new FileInputStream(FILE_PATH);
        SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
        saxParser.parse(SAXIn, this);
    }

    public org.jdom.Document readXMLByJDOM() throws Exception {
        FileInputStream JDOMInput = new FileInputStream(FILE_PATH);
        org.jdom.Document doc = new SAXBuilder().build(JDOMInput);
        org.jdom.Element eleRoot = doc.getRootElement();
        List<org.jdom.Element> eleJDOMList = eleRoot.getChildren();
        for (org.jdom.Element eleJDOM : eleJDOMList) {
            System.out.println(eleJDOM.getName() + "====JDOM===>" + eleJDOM.getText());
        }
        return doc;
    }

    public void writeXMLByJDOM(org.jdom.Document doc) throws Exception {
        FileOutputStream JDOMOut = new FileOutputStream(FILE_PATH);
        new XMLOutputter().output(doc, JDOMOut);
        JDOMOut.close();
    }

    public org.dom4j.Document readXMLByDOM4J() throws Exception {
        SAXReader saxReadernew =new SAXReader();
        saxReadernew.addHandler("/root/user", this);
        org.dom4j.Document docD4J = saxReadernew.read(FILE_PATH);
        org.dom4j.Element rootD4E = docD4J.getRootElement();
        Iterator<org.dom4j.Element> iterD4E = rootD4E.elementIterator();
        while (iterD4E.hasNext()) {
            org.dom4j.Element eleD4E = iterD4E.next();
            System.out.println(eleD4E.getName() + "===DOM4J===>" + eleD4E.getText());
        }
        return docD4J;
    }

    public void writeXMLByDOM4J(org.dom4j.Document docD4J) throws Exception {
        FileOutputStream DOM4JOut = new FileOutputStream(FILE_PATH);
        XMLWriter writer = new XMLWriter(DOM4JOut);
        writer.write(docD4J);
        DOM4JOut.close();
    }

    public static void main(String[] args) throws Exception {

        /**
         * dom you can change the implement class any one you like in jaxp.properties
         */
        //dom writer and parser
        Test4XML test4Xml = new Test4XML();
        test4Xml.writeXMLByDOM();
        test4Xml.readerDOMParseXML();

        /**
         * SAX help doc http://doc.java.sun.com/DocWeb/api/all/javax.xml.stream.XMLStreamWriter
         */
        removeFile();
        test4Xml.writeXMLBySAX();
        test4Xml.parseXMLbySAX();

        /**
         * @see http://www.jdom.org/ to find api on jdom web
         */
        org.jdom.Document doc = test4Xml.readXMLByJDOM();
        removeFile();
        test4Xml.writeXMLByJDOM(doc);

        /**
         * @see http://www.dom4j.org/
         */
        org.dom4j.Document docDOM4J = test4Xml.readXMLByDOM4J();
        test4Xml.writeXMLByDOM4J(docDOM4J);
//        removeFile();
    }

}
複製代碼

 

6.其它開源項目,比如xstream等

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