XML的四种解析方式

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了XML的四种解析方式相关的知识,希望对你有一定的参考价值。

基础方法: DOM、SAX

DOM:与平台无关的官方解析方式

技术分享

SAX:基于事件驱动的解析方式

技术分享
扩展方法:JDOM、DOM4J(在基础的方法上扩展的,只有Java能够使用的解析方式)


DOM: 一次性解析完毕!

import java.io.FileOutputStream;

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;
/**
 * 第六章 简答题1-4
 * @author Xuas
 *
 */
public class Demo_DOM {
    Document doc = null;
    /**
     * 加载DOM树
     */
    public void loadDocument() throws Exception {
        //得到DOM解析器的工厂实例
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        //从DOM工厂获得DOM解析器
        DocumentBuilder db = dbf.newDocumentBuilder();
        //解析XML文档,得到一个Document对象,即DOM树
        doc = db.parse("src/com/chapter6/zy/学生信息.xml");
    }
    /**
     * 显示信息
     */
    public void showInfo(){
        //获取所有student节点集合
        NodeList studentList = doc.getElementsByTagName("student");
        System.out.println("*******一共有"+studentList.getLength()+"个学生*******");
        //遍历每一个student节点
        for(int i=0;i<studentList.getLength();i++){
            System.out.println("第"+(i+1)+"名学生信息:");
            /**
             * 不确定属性个数时:
             */
            /*//获取第i个student节点
            Node studentNode = studentList.item(i);
            //获取student节点所有属性集合
            NamedNodeMap attrs = studentNode.getAttributes();
            System.out.println("第"+(i+1)+"个学生共有"+attrs.getLength()+"个属性");
            //遍历student的属性
            for(int j=0;j<attrs.getLength();j++){
                //通过item(index)获取student节点的某一个属性
                Node attr = attrs.item(j);
                //获取属性名
                System.out.print("属性名:"+attr.getNodeName());
                //获取属性值
                System.out.println("==>属性值:"+attr.getNodeValue());
            }*/
            /**
             * 确定student节点有且只有一个id属性:
             */
            //将student节点进行强制类型转换,转换成Element类型
            Element student = (Element)studentList.item(i);
            //通过getAttribute("id")方法获取属性值
            String attrValue = student.getAttribute("id");
            System.out.println("id属性:"+attrValue);
            //解析student节点的子节点
            NodeList stuChildNodes = student.getChildNodes();
            //遍历stuChildNodes获取每个节点名和节点值
            System.out.println("第"+(i+1)+"个学生共有"+stuChildNodes.getLength()+"个子节点");
            for(int k=0;k<stuChildNodes.getLength();k++){
                //区分出text类型的node以及element类型的node
                if(stuChildNodes.item(k).getNodeType() == Node.ELEMENT_NODE){
                    //获取element类型节点的节点名
                    System.out.print(stuChildNodes.item(k).getNodeName());
                    //获取element类型节点的节点值(两种方式)
                    /**
                     * 
                     */
                    //System.out.println(":"+stuChildNodes.item(k).getFirstChild().getNodeValue());
                    System.out.println(":"+stuChildNodes.item(k).getTextContent());
                }
            }
            System.out.println("***************************************************");
        }
        
    }
    /**
     * 删除ID为1的成绩
     */
    public void delete() throws Exception{
        NodeList stuList = doc.getElementsByTagName("student");
        //找到删除的节点
        for(int i=0;i<stuList.getLength();i++){
            Element stuEle = (Element)stuList.item(i);
            //找到ID=1的student节点的成绩子节点
            if(stuEle.getAttribute("id").equals("1")){
                NodeList childNodes = stuEle.getChildNodes();
                for(int j=0;j<childNodes.getLength();j++){
                    if(childNodes.item(j).getNodeName().equals("score")){
                        childNodes.item(j).getParentNode().removeChild(childNodes.item(j));
                    }
                }
            }
        }
        //保存XML文件
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        DOMSource domSource = new DOMSource(doc);
        // 设置编码格式
        transformer.setOutputProperty(OutputKeys.ENCODING, "gb2312");
        StreamResult result = new StreamResult(new FileOutputStream("src/com/chapter6/zy/学生信息(删除ID为1).xml"));
        // 把DOM树转换为XML文件
        transformer.transform(domSource, result);
    }
    /**
     * 修改ID为2的成绩为60
     */
    public void modify() throws Exception{
        NodeList stuList = doc.getElementsByTagName("student");
        //找到要修改的student节点
        for(int i=0;i<stuList.getLength();i++){
            Element stuEle = (Element)stuList.item(i);
            //找到ID为2的student节点
            if(stuEle.getAttribute("id").equals("2")){
                //遍历ID为2的student节点的子节点找到score节点
                NodeList childNodes = stuEle.getChildNodes();
                for(int j=0;j<childNodes.getLength();j++){
                    if(childNodes.item(j).getNodeName().equals("score")){
                        childNodes.item(j).setTextContent("60");
                    }
                }
            }
        }
        //保存XML文件
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        DOMSource domSource = new DOMSource(doc);
        // 设置编码格式
        transformer.setOutputProperty(OutputKeys.ENCODING, "gb2312");
        StreamResult result = new StreamResult(new FileOutputStream("src/com/chapter6/zy/学生信息(修改ID为2成绩为60).xml"));
        // 把DOM树转换为XML文件
        transformer.transform(domSource, result);
    }
    /**
     * 添加一个学生信息(ID为3)
     */
    public void add() throws Exception {
        //创建student节点
        Element stuEle = doc.createElement("student");
        stuEle.setAttribute("id", "3");
        //创建name节点
        Element nameEle = doc.createElement("name");
        nameEle.setTextContent("王五");
        //创建course节点
        Element courseEle = doc.createElement("course");
        courseEle.setTextContent("英语");
        //创建score节点
        Element scoreEle = doc.createElement("score");
        scoreEle.setTextContent("77");
        //添加父子关系
        stuEle.appendChild(nameEle);
        stuEle.appendChild(courseEle);
        stuEle.appendChild(scoreEle);
        Element scoresEle = (Element)doc.getElementsByTagName("scores").item(0);
        scoresEle.appendChild(stuEle);
        //保存XML文件
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        DOMSource domSource = new DOMSource(doc);
        //设置编码格式
        transformer.setOutputProperty(OutputKeys.ENCODING, "gb2312");
        StreamResult result = new StreamResult(new FileOutputStream("src/com/chapter6/zy/学生信息(添加ID为3学生).xml"));
        //把DOM树转换为XML文件
        transformer.transform(domSource, result);
    }
    /**
     * 测试方法
     */
    public static void main(String[] args) throws Exception{
        Demo_DOM demo = new Demo_DOM();
        demo.loadDocument();
        //demo.delete();
        demo.modify();
        demo.add();
        demo.showInfo();
    }
}

 

SAX:逐步解析(一个标签一个标签的解析!)

import java.util.ArrayList;

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

import com.SAX方式解析XML.entity.Book;

public class SAXParserHandler extends DefaultHandler {
    String value = null;
    Book book = null;
    private ArrayList<Book> bookList = new ArrayList<Book>();
    public ArrayList<Book> getBookList() {
        return bookList;
    }
    int bookIndex = 0;
    /**
     * 用来遍历xml文件的开始标签
     */
    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {
        //调用DefaultHandler类的startElement方法
        super.startElement(uri, localName, qName, attributes);
        //开始解析book元素的属性
        if(qName.equals("book")){
            //创建一个Book对象
            book = new Book();
            bookIndex++;
            //已知book元素下属性名称,根据属性名获取属性值
            System.out.println("***********开始遍历第"+bookIndex+"本书的内容***********");
            /*String value = attributes.getValue("id");
            System.out.println("book的属性值是:"+value);*/
            int num = attributes.getLength();
            for(int i=0;i<num;i++){
                System.out.print("book元素的第"+(i+1)+"属性名是:"+attributes.getQName(i));
                System.out.println("==>属性值是:"+attributes.getValue(i));
                if(attributes.getQName(i).equals("id")){
                    book.setId(attributes.getValue(i));
                }
            }
        }else if(!qName.equals("book") && !qName.equals("bookstore")){
            System.out.print("节点名是:"+qName+"==>");
        }    
    }
    /**
     * 用来遍历xml文件的结束标签
     */
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        //调用DefaultHandler类的endElement方法
        super.endElement(uri, localName, qName);
        //判断是否针对一本书已经遍历结束
        if(qName.equals("book")){
            bookList.add(book);
            book = null;
            System.out.println("***********结束遍历第"+bookIndex+"本书的内容***********");
        }else if(qName.equals("name")){
            book.setName(value);
        }else if(qName.equals("author")){
            book.setAuthor(value);
        }else if(qName.equals("year")){
            book.setYear(value);
        }else if(qName.equals("price")){
            book.setPrice(value);
        }else if(qName.equals("language")){
            book.setLanguage(value);
        }
    }
    /**
     * 用来标识解析开始
     */
    public void startDocument() throws SAXException {
        super.startDocument();
        System.out.println("SAX解析开始");
    }
    /**
     * 用来标识解析结束
     */
    public void endDocument() throws SAXException {
        super.endDocument();
        System.out.println("SAX解析结束");
    }
    /**
     * 
     */
    public void characters(char[] ch, int start, int length)
            throws SAXException {
        super.characters(ch, start, length);
        value = new String(ch, start, length);
        if(!value.trim().equals("")){
            System.out.println("节点值是:"+value);
        }
    }
}
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import com.SAX方式解析XML.entity.Book;
import com.SAX方式解析XML.handler.SAXParserHandler;

public class Demo {
    public static void main(String[] args) throws Exception{
        //获取一个SAXParserFactory的实例
        SAXParserFactory factory = SAXParserFactory.newInstance();
        //通过factory获取SAXParser实例
        SAXParser parser = factory.newSAXParser();
        //创建SAXParserHandler对象
        SAXParserHandler handler = new SAXParserHandler();
        parser.parse("books.xml", handler);
        System.out.println("共有"+handler.getBookList().size()+"本书!");
        for (Book book : handler.getBookList()) {
            System.out.println(book.getId());
            System.out.println(book.getName());
            System.out.println(book.getAuthor());
            System.out.println(book.getYear());
            System.out.println(book.getPrice());
            System.out.println(book.getLanguage());
            System.out.println("--------------finish---------------");
        }
    }
}

 


选择DOM还是SAX??

DOM---优点:
1.形成了树结构,直观好理解,代码更易编写!
2.解析过程中树结构保留在内存中,方便修改!
DOM---缺点:
当xml文件较大时,对内存耗费比较大,容易影响解析性能并造成内存溢出!(内存装不下DOM树了!)

SAX---优点:
1.采用事件驱动模式,对内存耗费比较小!
2.适用于只需要处理xml中数据的情况!
SAX---优点:
1.不易编码!
2.很难同时访问同一个xml中的多处不同数据!

JDOM与DOM、DOM4J

JDOM:
1.仅使用具体类而不使用接口!
2.API大量使用了Collections类!

import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import org.jdom2.Attribute;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;

import com.JDOM方式解析XML.entity.Book;


public class Demo {
    private static ArrayList<Book> booksList = new ArrayList<Book>();
    public static void main(String[] args) throws Exception{
        // 进行对books.xml文件的解析
        // 1.创建一个SAXBuilder的对象
        SAXBuilder saxBuilder = new SAXBuilder();
        // 2.创建一个输入流,将xml加载到输入流里来
        InputStream in = new FileInputStream("src/res/books.xml");
        //处理解析过程中的乱码问题
        InputStreamReader isr = new InputStreamReader(in, "UTF-8");
        // 3.通过saxBuilder的build()方法,将输入流加载到saxBilder中
        Document doc = saxBuilder.build(in);
        // 4.通过document对象获取xml文件的根节点
        Element rootEle = doc.getRootElement();
        // 5.获取根节点下的子节点的List集合
        List<Element> bookList = rootEle.getChildren();
        // 继续进行解析
        for (Element book : bookList) {
            Book bookEntity = new Book();
            System.out.println("开始解析第"+(bookList.indexOf(book)+1)+"本书");
            // 解析book的属性集合
            List<Attribute> attrList = book.getAttributes();
            // 知道节点下属性名称时,获取节点值
            //book.getAttributeValue("id");
            // 遍历attrList(针对不清楚book节点下属性的名字及数量)
            for (Attribute attr : attrList) {
                System.out.println("属性名:"+attr.getName()+"==>属性值:"+attr.getValue());
                if(attr.getName().equals("id")){
                    bookEntity.setId(attr.getValue());
                }
            }
            // 对book节点的子节点的节点名 节点值进行遍历
            List<Element> bookChilds = book.getChildren();
            for (Element child : bookChilds) {
                System.out.println("节点名:"+child.getName()+"==>节点值:"+child.getValue());
                if(child.getName().equals("name")){
                    bookEntity.setName(child.getValue());
                }else if(child.getName().equals("author")){
                    bookEntity.setAuthor(child.getValue());
                }else if(child.getName().equals("year")){
                    bookEntity.setYear(child.getValue());
                }else if(child.getName().equals("price")){
                    bookEntity.setPrice(child.getValue());
                }else if(child.getName().equals("language")){
                    bookEntity.setLanguage(child.getValue());
                }
            }
            System.out.println("结束解析第"+(bookList.indexOf(book)+1)+"本书");
            booksList.add(bookEntity);
            bookEntity = null;
            /*
             * 测试是否存储到Book对象中
             */
            //System.out.println(booksList.size());
            //System.out.println(booksList.get(0).getName());
        }
    }
}

 

DOM4J:(在性能上比JDOM高!)
1.JDOM的一种智能分支,它合并了许多超出基本XML文档表示的功能!
2.DOM4J使用接口和抽象基本类方法,是一个优秀的Java XML API!
3.具有性能优异、灵活性好、功能强大和极端易使用的特点!
4.是一个开放源代码的软件!

import java.io.File;
import java.util.Iterator;
import java.util.List;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class Demo {
    public static void main(String[] args) throws Exception {
        // 解析books.xml文件
        // 创建SAXReader的对象reader
        SAXReader reader = new SAXReader();
        // 通过reader对象的read()方法加载xml文件,获取document对象
        Document doc = reader.read(new File("books.xml"));
        // 通过document对象获取根节点bookstore
        Element bookStore = doc.getRootElement();
        // 通过element对象的elementIterator()方法获取迭代器
        Iterator bookStoreIt = bookStore.elementIterator();
        // 遍历迭代器,获取根节点中的信息(book)
        while(bookStoreIt.hasNext()){
            System.out.println("=========开始遍历某一本书=========");
            Element book = (Element)bookStoreIt.next();
            List<Attribute> attrs = book.attributes();
            for (Attribute attr : attrs) {
                System.out.println("属性名:"+attr.getName()+"==>属性值:"+attr.getValue());
            }
            Iterator bookIt = book.elementIterator();
            while(bookIt.hasNext()){
                Element bookChild = (Element)bookIt.next();
                System.out.println("节点名:"+bookChild.getName()+"==>节点值:"+bookChild.getStringValue());
            }
            System.out.println("=========结束遍历某一本书=========");
        }
    }
}

 

























以上是关于XML的四种解析方式的主要内容,如果未能解决你的问题,请参考以下文章

XML的四种解析方式

XML解析——Java中XML的四种解析方式

XML--Java中的四种常见解析方式--dom

Java中XML的四种解析方式

XML数据如何进行解析呢,方式有哪些?

XML--Java中的四种常见解析方式--jdom与dom4j