闲聊下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等

 

你可能感兴趣的:(java)