XML的几种解析器

XML优点:平台无关性,语言无关性,系统无关性

XML在不同的语言里解析方式都是一样的,只不过实现的语法不同而已。基本的解析方式有两种,一种叫SAX,另一种叫DOM。SAX是基于事件流的解析,DOM是基于XML文档树结构的解析.假设我们XML的内容和结构如下:

<?xml version="1.0" encoding="UTF-8"?>
<employees>
	<employee>
		<name>Darren</name>
		<sex>man</sex>
		<age>25</age>
	</employee>
</employees>
下面是解析XMl常用的Dom和Sex方法:
package com.darren.test.xml;


public interface XmlParse {

    void createXml(String path);

    void parseXml(String path);
}

1、DOM生成和解析XML文档

为 XML 文档的已解析版本定义了一组接口。解析器读入整个文档,然后构建一个驻留内存的树结构,然后代码就可以使用 DOM 接口来操作这个树结构。

优点:整个文档树在内存中,便于操作;支持删除、修改、重新排列等多种功能;

缺点:将整个文档调入内存(包括无用的节点),浪费时间和空间;使用场合:一旦解析了文档还需多次访问这些数据;硬件资源充足(内存、CPU)。

package com.darren.test.xml;

import java.io.FileOutputStream;
import java.io.PrintWriter;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class DomParse implements XmlParse {
    private static DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

    @Override
    public void createXml(String path) {
        try {
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder.newDocument();
            // 创建根节点
            Element root = document.createElement("employees");
            // 添加根节点
            document.appendChild(root);

            // 创建一级子节点
            Element employee = document.createElement("employee");

            // 操作一
            // 创建二级子节点
            Element name = document.createElement("name");
            // 为二级子节点添加值
            name.appendChild(document.createTextNode("Darren"));
            // 把二级子节点放到一级子节点下
            employee.appendChild(name);

            // 同操作一
            Element sex = document.createElement("sex");
            sex.appendChild(document.createTextNode("man"));
            employee.appendChild(sex);

            // 同操作一
            Element age = document.createElement("age");
            age.appendChild(document.createTextNode("25"));
            employee.appendChild(age);

            // 把一级子节点添加到根节点下
            root.appendChild(employee);

            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            DOMSource source = new DOMSource(document);
            transformer.setOutputProperty(OutputKeys.ENCODING,"UTF-8");
            transformer.setOutputProperty(OutputKeys.INDENT,"yes");
            PrintWriter pw = new PrintWriter(new FileOutputStream(path));
            StreamResult result = new StreamResult(pw);
            transformer.transform(source,result);
            System.out.println("生成XML文件成功!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void parseXml(String path) {
        try {
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder.parse(path);
            Element root = document.getDocumentElement();
            NodeList employee = root.getChildNodes();
            outPut(employee);
            System.out.println("解析XML文件成功!");
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private void outPut(NodeList nodeList) {
        int length = nodeList.getLength();
        for (int i = 0; i < length; i++) {
            Node node = nodeList.item(i);
            // 叶子节点
            if (node.getChildNodes().getLength() == 1) {
                String nodeName = node.getNodeName();
                String nodeValue = node.getTextContent();
                System.out.println(nodeName + ":" + nodeValue);
            }
            // 非叶子节点
            if (node.getChildNodes().getLength() > 1) {
                NodeList subList = node.getChildNodes();
                outPut(subList);
            }
        }
    }
}

打印结果:

生成XML文件成功!
name:Darren
sex:man
age:25
解析XML文件成功!

2、SAX生成和解析XML文档

为解决DOM的问题,出现了SAX。SAX ,事件驱动。当解析器发现元素开始、元素结束、文本、文档的开始或结束等时,发送事件,程序员编写响应这些事件的代码,保存数据。

优点:不用事先调入整个文档,占用资源少;SAX解析器代码比DOM解析器代码小,适于Applet,下载。

缺点:不是持久的;事件过后,若没保存数据,那么数据就丢了;无状态性;从事件中只能得到文本,但不知该文本属于哪个元素;使用场合:Applet;只需XML文档的少量内容,很少回头访问;机器内存少;

package com.darren.test.xml;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class MySAXHandler extends DefaultHandler {

    // 一般将正式解析前的一些初始化工作放到这里面
    public void startDocument() throws SAXException {
        System.out.println("文档开始打印了");
    }

    // 收尾工作放在endDocument中
    public void endDocument() throws SAXException {
        System.out.println("文档打印结束了");
    }

    // XML解析器遇到XML里面的tag时就会调用这个函数。经常在这个函数内是通过qName俩进行判断而操作一些数据
    public void startElement(String uri,String localName,String qName,Attributes attributes) throws SAXException {
        if (qName.equals("employees")) {
            return;
        }
        if (qName.equals("employee")) {
            return;
        }
        System.out.print(qName + ":");
    }

    // 这个方法与startElement()相对应,解析完一个tag节点后,执行这个方法
    public void endElement(String uri,String qName) throws SAXException {

    }

    // 回调方法。解析器执行完startElement()后,解析完节点的内容后就会执行这个方法,并且参数ch[]就是节点的内容
    public void characters(char[] ch,int start,int length) throws SAXException {
        String value = new String(ch,start,length);
        if (value.startsWith("\n")) {
            return;
        }

        System.out.println(value);
    }
}
package com.darren.test.xml;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Transformer;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;

import org.xml.sax.helpers.AttributesImpl;

public class SaxParse implements XmlParse {

    @Override
    public void createXml(String path) {
        try {
            SAXTransformerFactory sff = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
            TransformerHandler th = sff.newTransformerHandler();
            Result resultXml = new StreamResult(new FileOutputStream(path));
            th.setResult(resultXml);

            Transformer transformer = th.getTransformer();
            transformer.setOutputProperty(OutputKeys.ENCODING,"UTF-8"); // 编码格式是UTF-8
            transformer.setOutputProperty(OutputKeys.INDENT,"yes"); // 换行
            th.startDocument(); // 开始xml文档
            AttributesImpl attr = new AttributesImpl();
            th.startElement("","","employees",attr); // 定义employees节点
            th.startElement("","employee",attr); // 定义employee节点

            th.startElement("","name",attr); // 定义name节点
            th.characters("Darren".toCharArray(),"Darren".length());
            th.endElement("","name"); // 结束name节点

            th.startElement("","sex",attr); // 定义sex节点
            th.characters("man".toCharArray(),"man".length());
            th.endElement("","sex"); // 结束gender节点

            th.startElement("","age",attr); // 定义age节点
            th.characters("25".toCharArray(),"25".length());
            th.endElement("","age"); // 结束age节点

            th.endElement("","employee"); // 结束employee节点
            th.endElement("","employees"); // 结束employees节点
            th.endDocument(); // 结束xml文档

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Override
    public void parseXml(String path) {
        SAXParserFactory saxfac = SAXParserFactory.newInstance();
        try {
            SAXParser saxparser = saxfac.newSAXParser();
            InputStream is = new FileInputStream(path);
            saxparser.parse(is,new MySAXHandler());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

打印结果:

文档开始打印了
name:Darren
sex:man
age:25
文档打印结束了

3、DOM4J生成和解析XML文档

DOM4J 是一个非常非常优秀的Java XML API,具有性能优异、功能强大和极端易用使用的特点,同时它也是一个开放源代码的软件。如今你可以看到越来越多的 Java 软件都在使用 DOM4J 来读写 XML,特别值得一提的是连 Sun 的 JAXM 也在用 DOM4J

需要引入dom4j包

package com.darren.test.xml;

import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
import java.util.Iterator;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

public class Dom4jParse implements XmlParse {

    @Override
    public void createXml(String path) {
        try {
            Document document = DocumentHelper.createDocument();
            Element employees = document.addElement("employees");
            Element employee = employees.addElement("employee");
            Element name = employee.addElement("name");
            name.setText("Darren");
            Element sex = employee.addElement("sex");
            sex.setText("man");
            Element age = employee.addElement("age");
            age.setText("25");
            Writer fileWriter = new FileWriter(path);
            XMLWriter xmlWriter = new XMLWriter(fileWriter);
            xmlWriter.write(document);
            xmlWriter.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Override
    @SuppressWarnings("unchecked")
    public void parseXml(String path) {
        try {
            File inputXml = new File(path);
            SAXReader saxReader = new SAXReader();

            Document document = saxReader.read(inputXml);
            Element employees = document.getRootElement();
            Iterator<Element> employeeElements = employees.elementIterator();
            while (employeeElements.hasNext()) {
                Element employee = (Element) employeeElements.next();

                Iterator<Element> nodeElements = employee.elementIterator();
                while (nodeElements.hasNext()) {
                    Element node = (Element) nodeElements.next();
                    System.out.println(node.getName() + ":" + node.getText());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}
打印结果:
name:Darren
sex:man
age:25

4、JDOM生成和解析XML

为减少DOM、SAX的编码量,出现了JDOM;

优点:20-80原则,极大减少了代码量。使用场合:要实现的功能简单,如解析、创建等,但在底层,JDOM还是使用SAX(最常用)、DOM、Xanan文档
需要引入jdom包

package com.darren.test.xml;

import java.io.FileOutputStream;
import java.util.List;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;

public class JDomParse implements XmlParse {

    @Override
    public void createXml(String path) {
        try {
            Element root = new Element("employees");
            Document document = new Document(root);
            Element employee = new Element("employee");
            root.addContent(employee);
            Element name = new Element("name");
            name.setText("Darren");
            employee.addContent(name);
            Element sex = new Element("sex");
            sex.setText("man");
            employee.addContent(sex);
            Element age = new Element("age");
            age.setText("25");
            employee.addContent(age);
            XMLOutputter XMLOut = new XMLOutputter();
            XMLOut.output(document,new FileOutputStream(path));
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Override
    @SuppressWarnings("unchecked")
    public void parseXml(String path) {
        try {
            SAXBuilder builder = new SAXBuilder(false);
            Document document = builder.build(path);
            Element root = document.getRootElement();
            List<Element> employeeList = root.getChildren("employee");
            for (Element employee : employeeList) {
                List<Element> employeeInfo = employee.getChildren();
                for (Element info : employeeInfo) {
                    System.out.println(info.getName() + ":" + info.getValue());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}
打印结果:
name:Darren
sex:man
age:25
测试类:
package com.darren.test.xml;

public class XmlParseTest {

    public static void main(String[] args) {
        // DomParse domParse = new DomParse();
        // domParse.createXml("F:\\employee.xml");
        // domParse.parseXml("F:\\employee.xml");

        // SaxParse saxParse = new SaxParse();
        // saxParse.createXml("F:\\employee.xml");
        // saxParse.parseXml("F:\\employee.xml");

        // Dom4jParse dom4jParse = new Dom4jParse();
        // dom4jParse.createXml("F:\\employee.xml");
        // dom4jParse.parseXml("F:\\employee.xml");

        JDomParse jdomParse = new JDomParse();
        jdomParse.createXml("F:\\employee.xml");
        jdomParse.parseXml("F:\\employee.xml");
    }

}

相关文章

php输出xml格式字符串
J2ME Mobile 3D入门教程系列文章之一
XML轻松学习手册
XML入门的常见问题(一)
XML入门的常见问题(三)
XML轻松学习手册(2)XML概念