四种常见的XML解析方式

四种常见的XML解析方式
1.XML语言简介

XML即可扩展的标记语言,可以定义语义标记(标签),是元标记语言。XML不像超文本标记语言HTML,HTML只能使用规定的标记,对于XML,用户可以定义自己需要的标记。树状模型。
XML(eXtensible Markup Language)和HTML(Hyper Text Markup Language)师出同门。
使用XML的原因:不同软件之间(订票和支付)、不同平台(Mac和Windows)之间的数据通信、不同平台间的数据共享(网站和手机APP),用相同的XML文件将不同的东西联系起来。
2.XML文件解析的四种方式

2.1 DOM解析

DOM,Document Object Model,文档对象模型。DOM是html和xml文档的编程接口规范,和平台、语言是无关的。利用DOM规范,能够实现DOM 文档和xml之间的相互转换,遍历、操作相应DOM文档的内容。DOM规范的核心就是树模型。全部读取之后再解析

2.2 JDOM解析

JDOM是Java和DOM的结合体。JDOM 致力于建立一个完整的基于 Java 平台的、通过 Java 代码来访问、操作并输出 XML 数据。JDOM是用Java语言读、写、操作XML的新API函数。简单、高效、优化。
2.3 SAX解析
SAX,Simple API For XML。非W3C官方所提供的标准,“民间”的事实标准。SAX在概念上与DOM完全不同。非文档驱动,是事件驱动的。事件驱动:一种基于回调机制的程序运行方法。由外至内一层一层解析。

2.4 DOM4j解析

dom4j是一个Java的XML API,类似于jdom,用来读写XML文件的。性能优异功能强大简单易用开放源代码。

2.5 目的

获取XML文件中的所有数据。
节点类型 NodeType Named Content nodeName返回值 nodeValue的返回值
Element 1 ELEMENT_NODE Element name null
Attr 2 ATTRIBUTE_NODE 属性名称 属性值
Text 3 TEXT_NODE #text 节点内容

3.XML解析具体实例

3.1 DOM解析实例

1.创建一个DocumentBuilderFactory的对象
2.创建一个DocumentBuilder对象,处理异常
3.通过DocumentBuilder的parse(String fileName)方法解析xml文件
4.返回一个返回org.w3c.dom.Document的对象
5.通过getElementsByTagName获取xml中所有book节点->Booklist
6.通过nodelist的getLength方法获取book节点的个数
7.遍历每一个book节点{
通过nodelist的item方法获取每一个节点
获取每一个节点的所有属性值
遍历所有属性值
}
8.或者通过ELement直接获取属性值,前提是知道属性名

解析获取属性值
见代码:code-1
解析获取子节点
见代码:code-2

3.2 JDOM解析实例(非JAVA官方的解析)
1.JDOM需要导入相应的jar包
2.创建一个SAXBuilder对象
3.创建一个输入流,将books.xml文件加载到输入流中
4.通过saxBuilder的build方法将输入流加载到saxBuilder中
5.通过Document的getRootElement获取xml文件的根节点
6.通过root的getChildren获取根节点的子节点的list集合

解析获取属性和子节点
见代码:code-4

用JDOM解析时的乱码问题:
首先修改XML文件的编码方式encoding=“UTF-8”
不修改XML文件,修正编码问题:使用InputStreamReader输入流
InputStreamReader isr = new InputStreamReader(in,”UTF-8”);
3.3 SAX解析实例
handler–startElement–endElement
通过SAXParserFactory的静态newInstance方法创建factory实例
通过factory的newSAXParser()方法创建parse实例
创建一个类继承自DefaultHandler重写方法进行业务处理并创建实例
将实例传入方法中

解析获取属性和子节点
见代码:code-3

3.4 DOM4j解析实例
1.DOM4j是非官方的解析方式要导入jar包
2.创建SAXReader对象
3.通过reader的read方法加载books.xml文件
4.获取根节点
5.获取子节点
6.获取子节点的属性和属性值
7.获取子节点的节点和节点值

代码见Code-5

4.四种XML解析方式比较
基础方法:DOM和SAX,无需导入jar包
DOM:和平台无关,解析开始将XML 文件全部读入内存
SAX:基于事件驱动的解析方式,遇到XML的内容触发方法解析
扩展方法:JDOM和DOM4j,需导入jar包,基于java平台

DOM优点:形成树结构,直观,容易理解,代码容易编写
解析过程中树结构保留在内存中,便于修改
DOM缺点:XML文件较大时,对内存耗费较大,容易影响解析性能内存溢出
SAX优点:采用事件驱动模式,对内存耗费小,适用于只需XML中数据情况
SAX缺点:编码不易,很难同时访问同一个XML文件的多处数据

Code-1:DOM解析XML获取属性值(两种方法)
DOMTest.java
package com;

import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class DOMTest {
    public static void main(String[] args) {
        /**
         * @author Stella
         */
        //创建一个DocumentBuilderFactory的对象
        DocumentBuilderFactory bdf = DocumentBuilderFactory.newInstance();
        //创建一个DocumentBuilder对象,处理异常
        try {
            DocumentBuilder bd = bdf.newDocumentBuilder();
            //通过DocumentBuilder的parse(String fileName)方法解析xml文件
            //返回org.w3c.dom.Document的对象
            Document doc = bd.parse("web/books.xml");
            //通过getElementsByTagName获取xml中所有book节点->Booklist
            NodeList booklist = doc.getElementsByTagName("book");
            //通过nodelist的getLength方法获取book节点的个数
            System.out.println("一共有"+booklist.getLength()+"本书");
            //遍历每一个book节点
            for (int i = 0;i < booklist.getLength(); i++){
                //通过nodelist的item方法获取每一个节点
                Node node = booklist.item(i);
                //获取每一个节点的所有属性值
                NamedNodeMap attr = node.getAttributes();
                //遍历所有属性值
                System.out.println("第"+(i+1)+"本书有"+attr.getLength()+"个属性");
                for (int j = 0; j < attr.getLength(); j++){
                    //通过item方法获取节点属性,可以看到返回值依然是节点
                    //Element、attr、Text都是节点
                    Node att = attr.item(j);
                    String name = att.getNodeName();
                    String value = att.getNodeValue();
                    System.out.println("属性名:"+name+"----属性值:"+value);
                }
                //通过ELement直接获取属性值,前提是知道属性名
                Element attrELe = (Element) booklist.item(i);
                String eleValue = attrELe.getAttribute("id");
                System.out.println("属性ID的属性值为:"+eleValue);
                Element attrELe1 = (Element) booklist.item(i);
                String eleValue1 = attrELe1.getAttribute("id");
                System.out.println("属性name的属性值为:"+eleValue1);
            }
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        }catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}


Code-2:java解析XML获取节点名和节点值
DOMTest .java 
package com;

import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class DOMTest {
    public static void main(String[] args) {
        //创建一个DocumentBuilderFactory
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        try {
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = db.parse("web/books.xml");
            NodeList booklist = doc.getElementsByTagName("book");
            //遍历每一个book子节点
            for (int i = 0; i < booklist.getLength(); i++){
                Node book = booklist.item(i);
                NodeList childNodes = book.getChildNodes();
                System.out.println("第"+(i+1)+"本书的子节点个数为:"+childNodes.getLength());
                for (int j = 0; j < childNodes.getLength(); j++){
                    Node child = childNodes.item(j);
                    if(child.getNodeType()==Node.ELEMENT_NODE){
                        //获取ELement类型的类型名
                        String name = child.getNodeName();
                        //Element类型的getNodeValue返回值是null
                        String value =  child.getTextContent();
                        System.out.println("子节点名称:"+name+"      子节点的值:"+value);
                        //也可以通过获取子节点的第一个节点来
                        String valueContent = child.getFirstChild().getNodeValue();
                        System.out.println("子节点名称:"+name+"      子节点的值:"+valueContent);

                    }
                }
            }

        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        }catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }   
    }
}


Code-3:SAX解析XML获取属性名、节点名和节点值
SAXTest.java
package com;

import java.io.IOException;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.SAXException;

import com.sun.handler.SAXParseHandler;

public class SAXTest {
    public static void main(String[] args) {
        //1首先获取一个SAXFactory的实例factory
        SAXParserFactory factory = SAXParserFactory.newInstance();
        //2通过factory获取SAXParser的实例
        //2创建一个SAXParseHandler的实例
        SAXParseHandler phandler = new SAXParseHandler();
        try {
            SAXParser parser = factory.newSAXParser();
            parser.parse("web/books.xml", phandler);
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}


SAXParseHandler.java

package com.sun.handler;

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

public class SAXParseHandler extends DefaultHandler{
    int bookIndex = 0;
    //重写遍历xml文件的开始标签方法//解析xml元素
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        //调用父类DefaultHandler的startElement方法
        super.startElement(uri, localName, qName, attributes);
        if(qName.equals("book")){
            /**
             *  已知属性名称,根据属性名称获取属性值
             * String value = attributes.getValue("id");
             * System.out.println("book的属性值是:"+value);
             */
            bookIndex++;
            System.out.println("第" + bookIndex + "本书遍历开始");
            //不知道属性名称和个数,通过attribute的方法来得到
            for (int i = 0; i < attributes.getLength(); i++){
                String name = attributes.getQName(i);
                String value = attributes.getValue(i);
                System.out.println("第" + ( i + 1 ) + "属性名称:" + name + "属性值" + value);
            }
        }else if(!(qName.equals("book")||qName.equals("bookstore"))){
            System.out.print("节点名:" + qName);
        }
    }
    //重写遍历xml文件的结束标签方法
    public void endElement(String uri, String localName, String qName) throws SAXException {
        super.endElement(uri, localName, qName);
        //判断是否针对一本书已经结束
        if(qName.equals("book")){
            System.out.println("第" + bookIndex + "本书遍历结束");
        }
    }
    //重写标识xml文件解析开始方法
    public void startDocument() throws SAXException {
        super.startDocument();
        System.out.println("SAX解析开始");
    }
    //重写标识xml文件解析结束方法
    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);
        //ch是整个books.xml的的内容
        String value = new String(ch, start, length);
        if(!value.trim().equals("")){
            System.out.println("节点值:" + value.trim());
        }
    }
}


通过java类实现解析xml文件的时候保留xml文件的树结构:
创建Book.java
package com.sun.handler;

public class Book {
    private String id;
    private String name;
    private String author;
    private String year;
    private String price;
    private String language;
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getAuthor() {
        return author;
    }
    public void setAuthor(String author) {
        this.author = author;
    }
    public String getYear() {
        return year;
    }
    public void setYear(String year) {
        this.year = year;
    }
    public String getPrice() {
        return price;
    }
    public void setPrice(String price) {
        this.price = price;
    }
    public String getLanguage() {
        return language;
    }
    public void setLanguage(String language) {
        this.language = language;
    }
    public String toString() {
        return super.toString();
    }
}
在SAXParseHandler添加内容
SAXParseHandler.java
package com.sun.handler;

import java.util.ArrayList;

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

public class SAXParseHandler extends DefaultHandler{
    int bookIndex = 0;
    String value = new String();
    Book book = null;
    private ArrayList<Book> booklist = new ArrayList<Book>();
    public ArrayList<Book> getBooklist() {
        return booklist;
    }
    //重写遍历xml文件的开始标签方法//解析xml元素
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        //调用父类DefaultHandler的startElement方法
        super.startElement(uri, localName, qName, attributes);
        if(qName.equals("book")){
            book = new Book();
            /**
             *  已知属性名称,根据属性名称获取属性值
             * String value = attributes.getValue("id");
             * System.out.println("book的属性值是:"+value);
             */
            bookIndex++;
            System.out.println("第" + bookIndex + "本书遍历开始");
            //不知道属性名称和个数,通过attribute的方法来得到
            for (int i = 0; i < attributes.getLength(); i++){
                String name = attributes.getQName(i);
                String value = attributes.getValue(i);
                System.out.println("第" + ( i + 1 ) + "属性名称:" + name + "属性值" + value);
                if(attributes.getQName(i).equals("id")){
                    book.setId(value);
                }
            }
        }else if(!(qName.equals("book")||qName.equals("bookstore"))){
            System.out.print("节点名:" + qName);
        }
    }
    //重写遍历xml文件的结束标签方法
    public void endElement(String uri, String localName, String qName) throws SAXException {
        super.endElement(uri, localName, qName);
        //判断是否针对一本书已经结束
        if(qName.equals("book")){
        //结束上一个book节点,清空全局book的内容,便于对下一个book进行记录
        //如何保存上一个book的内容??
        //用arraylist全局保存
        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("language")){
            book.setLanguage(value);
        }else if(qName.equals("price")){
            book.setPrice(value);
        }else if(qName.equals("id")){
            book.setId(value);
        }

    }
    //重写标识xml文件解析开始方法
    public void startDocument() throws SAXException {
        super.startDocument();
        System.out.println("SAX解析开始");
    }
    //重写标识xml文件解析结束方法
    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);
        //ch是整个books.xml的的内容
        value = new String(ch, start, length);
        if(!value.trim().equals("")){
            System.out.println("----节点值:" + value.trim());
        }
    }
}


Code-4package com.JDOMtest;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.AttributedCharacterIterator.Attribute;
import java.util.List;

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

public class JDOMTest {
    public static void main(String[] args) {
        //1.创建一个SAXBuilder对象
        SAXBuilder saxBuilder = new SAXBuilder();
        File file = new File("web/books.xml");
        try {
            if(!file.exists()){
                file.createNewFile();
            }
            //2.创建一个输入流,将books.xml文件加载到输入流中
            FileInputStream in = new FileInputStream(file);
            //3.通过saxBuilder的build方法将输入流加载到saxBuilder中
            Document doc = saxBuilder.build(in);
            //4.通过Document的getRootElement获取xml文件的根节点
            Element root = doc.getRootElement();
            //5.通过root的getChildren获取根节点的子节点
            List<Element> bookList = root.getChildren();
            System.out.println("一共有" + bookList.size() + "本书");
            //获取book的属性
            for (int i = 0; i < bookList.size(); i++){
                Element book = bookList.get(i);
                List<org.jdom2.Attribute> attr = book.getAttributes();
                System.out.println("第" + (i + 1) +"本书" + attr.size() + "个属性");
                for (int j = 0 ;j < attr.size(); j++){
                    System.out.print("属性名为:" + attr.get(j).getName());
                    System.out.println("----属性值为:" + attr.get(j).getValue());
                }
            }   
            //获取book的节点和节点值
            for (int i = 0; i < bookList.size(); i++){
                Element book = bookList.get(i);
                List<Element> bookElement = book.getChildren();
                System.out.println("第" + (i + 1) + "本书有" + bookElement.size() + "个节点");
                for (int j = 0; j < bookElement.size(); j++){
                    String name = bookElement.get(j).getName();
                    String value = bookElement.get(j).getValue();
                    System.out.print("  第" + (j+1) + "个----节点名:" + name);
                    System.out.println("----节点值:" + value);

                }
            }
            //foreach循环解析
            for (Element book:bookList){
                System.out.println("\n----开始解析第" + (bookList.indexOf(book) + 1) + "本书");
                List<org.jdom2.Attribute> attrs = book.getAttributes();
                for (org.jdom2.Attribute attr:attrs){
                    //获取属性名和属性值
                    String name = attr.getName();
                    String value = attr.getValue();
                    System.out.print("  第" + (attrs.indexOf(attr) + 1) + "个----属性名:" + name);
                    System.out.println("----节点值:" + value);
                }
                List<Element> ele = book.getChildren();
                for (Element o:ele){
                    String name = o.getName();
                    String value = o.getValue();
                    System.out.print("  第" + (ele.indexOf(o) + 1) + "个----节点名:" + name);
                    System.out.println("----节点值:" + value);
                }
                System.out.println("\n----结束解析第" + (bookList.indexOf(book) + 1) + "本书");
            }
        } catch (JDOMException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


Code-5:
package com.DOM4j;

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

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

public class DOM4jTest {
    public static void main(String[] args) {
        //1.DOM4j是非官方的解析方式要导入jar包
        //2.创建SAXReader对象
        SAXReader reader= new SAXReader();
        try {
            //通过reader的read方法加载books.xml文件
            Document doc = reader.read(new File("web/books.xml"));
            Element root = doc.getRootElement();
            List<Element> books = root.elements();
            int bookSize = books.size();
            System.out.println("一共有" + bookSize + "本书");
            for (Element book:books){
                System.out.println("第" + (books.indexOf(book) + 1) + "本书解析开始");
                //获取所有属性
                List<Attribute> attrs = book.attributes();
                int attrSize = attrs.size();
                System.out.println("\t一共有" + attrSize + "个属性:");
                for (Attribute attr:attrs){
                    String name = attr.getName();
                    String value = attr.getValue();
                    System.out.println("\t第" + (attrs.indexOf(attr)+1)+"个属性的属性名:" + name + "-----属性值:" + value);
                }
                //获取所有节点
                List<Element> bookEles = book.elements();
                int bookEleSize = bookEles.size();
                System.out.println("\t一共有" + bookEleSize + "个节点:");
                for (Element ele:bookEles){
                    String name = ele.getName();
                    String value = ele.getStringValue();
                    System.out.println("\t第" + (bookEles.indexOf(ele)+1)+"个节点的节点名:" + name + "-----节点值:" + value);
                }
                System.out.println("第" + (books.indexOf(book) + 1) + "解析结束");
            }
            //通过迭代器来获取所有的book
            Iterator<Element> it = root.elementIterator();
            while(it.hasNext()){                
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }
}


Code-5package com.DOM4j;

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

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

public class DOM4jTest {
    public static void main(String[] args) {
        //1.DOM4j是非官方的解析方式要导入jar包
        //2.创建SAXReader对象
        SAXReader reader= new SAXReader();
        try {
            //通过reader的read方法加载books.xml文件
            Document doc = reader.read(new File("web/books.xml"));
            Element root = doc.getRootElement();
            List<Element> books = root.elements();
            int bookSize = books.size();
            System.out.println("一共有" + bookSize + "本书");
            for (Element book:books){
                System.out.println("第" + (books.indexOf(book) + 1) + "本书解析开始");
                //获取所有属性
                List<Attribute> attrs = book.attributes();
                int attrSize = attrs.size();
                System.out.println("\t一共有" + attrSize + "个属性:");
                for (Attribute attr:attrs){
                    String name = attr.getName();
                    String value = attr.getValue();
                    System.out.println("\t第" + (attrs.indexOf(attr)+1)+"个属性的属性名:" + name + "-----属性值:" + value);
                }
                //获取所有节点
                List<Element> bookEles = book.elements();
                int bookEleSize = bookEles.size();
                System.out.println("\t一共有" + bookEleSize + "个节点:");
                for (Element ele:bookEles){
                    String name = ele.getName();
                    String value = ele.getStringValue();
                    System.out.println("\t第" + (bookEles.indexOf(ele)+1)+"个节点的节点名:" + name + "-----节点值:" + value);
                }
                System.out.println("第" + (books.indexOf(book) + 1) + "解析结束");
            }
            //通过迭代器来获取所有的book
            Iterator<Element> it = root.elementIterator();
            while(it.hasNext()){                
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }
}

  • 1
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值