加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

XML解析的三种方式(dom,sax,dom4j)

发布时间:2020-12-16 08:39:18 所属栏目:百科 来源:网络整理
导读:1.Dom解析: 要解析的xml文件内容: ?xml version="1.0" encoding="utf-8" standalone="no"? class stu id = "1" name 小灰灰 / name age 23 / age insto 好学生 / insto / stu stu id = "2" sex = "女" name 小红 / name age 20 / age insto 学生 / insto /

1.Dom解析:

要解析的xml文件内容:

<?xml version="1.0" encoding="utf-8" standalone="no"?><class>
    <stu id="1">
        <name>小灰灰</name>
        <age>23</age>
        <insto>好学生</insto>
    </stu>
    <stu id="2" sex="女">
        <name>小红</name>
        <age>20</age>
        <insto>学生</insto>
    </stu>
    <stu>
        <name>小晖</name>
        <age>20</age>
        <insto>三好学生</insto>
    </stu>
</class>

java解析代码:

package com.huihui.dom;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
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;

//使用DOM技术对xml文件进行crud操作
public class DomXml1 {

    public static void main(String[] args) throws Exception {
        // 创建一个DocumentBuilderFactory
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        // 通过DocumentBuilderFactory得到一个DocumentBuilder对象
        DocumentBuilder dBuilder = dbf.newDocumentBuilder();
        // 指定解析哪个xml文件
        Document document = dBuilder.parse("src/myclass.xml");
        // System.out.println(document);
        // 遍历该xml文件
        //list(document);

        //read(document);

        //add(document);

        //delete(document);

        //update(document);

        System.out.println("OK");
    }

    // 更新xml文件
    private static void updateXML(Document doc)
            throws TransformerFactoryConfigurationError,TransformerConfigurationException,TransformerException {
        // 得到TransformerFactory对象
        TransformerFactory tff = TransformerFactory.newInstance();
        // 通过TransformerFactory得到一个转化器
        Transformer tf = tff.newTransformer();
        // 将doc的整个在内存中的节点树写出到外部的文件中
        tf.transform(new DOMSource(doc),new StreamResult("src/myclass.xml"));
    }

    // 遍历xml节点(也就是遍历树)
    public static void list(Node node) {

        // 如果该节点类型是node节点(而不是文本节点)
        if (node.getNodeType() == node.ELEMENT_NODE) {
            System.out.println("名字:" + node.getNodeName());
        }

        // 取出node的子节点
        NodeList nodeList = node.getChildNodes();
        for (int i = 0; i < nodeList.getLength(); i++) {
            // 取出节点
            Node n = nodeList.item(i);
            // 运用递归,再去显示(节点的子节点)
            list(n);
        }
    }

    // 具体查询某个学生的信息(显示第一个学生的所有信息)
    public static void read(Document doc) {
        NodeList nl = doc.getElementsByTagName("stu");// 在document的级别层级上往下获取元素
        // 取出第一个学生
        Element stu = (Element) nl.item(0);
        Element name = (Element) stu.getElementsByTagName("name").item(0);
        System.out.println("学生的姓名是:" + name.getTextContent());// 取出name的值
        System.out.println("学生的性别是:" + stu.getAttribute("sex"));// 取出stu的属性值
    }

    // 添加一个stu到xml文件中去
    public static void add(Document doc) throws Exception {
        // 创建一个新的学生节点
        Element newstu = doc.createElement("stu");
        Element newstu_name = doc.createElement("name");
        newstu_name.setTextContent("小晖");
        Element newstu_age = doc.createElement("age");
        newstu_age.setTextContent("20");
        Element newstu_insto = doc.createElement("insto");
        newstu_insto.setTextContent("三好学生");

        newstu.appendChild(newstu_name);
        newstu.appendChild(newstu_age);
        newstu.appendChild(newstu_insto);

        // 把新的学生节点添加到根元素下(虽然这也添加进取了,但是查看xml文件,会发现xml文件没有任何的变化,原因是现在的整个document是解析xml文件出来的、在内存中的。所以你只是改变的是内存中的内容,并没有对文件本身产生影响)
        doc.getDocumentElement().appendChild(newstu);

        // 更新xml文件
        updateXML(doc);

    }

    // 删除一个节点或者一个节点的属性(删除第一个学生或者第一个学生的性别属性)
    public static void delete(Document doc) throws Exception {
        // 删除第一个学生
        // Node node = doc.getElementsByTagName("stu").item(0);
        // node.getParentNode().removeChild(node);//获取到该节点的父节点后,从父节点中删除这个元素(也只是在内存的dom树中进行了删除,并不会影响xml文件的内容)

        // 删除第一个学生的sex属性
        Element node = (Element) doc.getElementsByTagName("stu").item(0);
        node.removeAttribute("sex");

        // 更新xml文件
        updateXML(doc);

    }

    // 更新节点的内容(把第一个学生的名字改成小灰灰)
    public static void update(Document doc) throws Exception {
        Element node = (Element) doc.getElementsByTagName("stu").item(0);
        Element node_name = (Element) node.getElementsByTagName("name").item(0);
        node_name.setTextContent("小灰灰");

        // 更新xml文件
        updateXML(doc);
    }

}

2.SAX解析:

要解析的xml文件内容:

<?xml version="1.0" encoding="UTF-8"?>
<class>
    <stu id="1" sex="男">
        <name>小灰灰</name>
        <age>23</age>
        <insto>好学生</insto>
    </stu>
    <stu id="2" sex="女">
        <name>小红</name>
        <age>20</age>
        <insto>学生</insto>
    </stu>
    <stu>
        <name>小晖</name>
        <age>20</age>
        <insto>三好学生</insto>
    </stu>
</class>

java解析代码:

package com.huihui.sax;

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

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

public class SaxXml1 {

    // 使用sax技术解析XML文件
    public static void main(String[] args) throws Exception {
        // 1.使用SAXParserFactory创建SAX解析工厂
        SAXParserFactory spf = SAXParserFactory.newInstance();
        // 2.通过SAX解析工厂得到解析器对象
        SAXParser saxParser = spf.newSAXParser();
        // 3.解析器将解析对象和事件处理对象关联
        saxParser.parse("src/myclass2.xml",new MyDefaultHandler1());

    }

}

// 定义第二个事件处理类(如何只显示stu的name和age)
class MyDefaultHandler1 extends DefaultHandler {
    private boolean isName = false;
    private boolean isAge = false;

    @Override
    public void characters(char[] ch,int start,int length) throws SAXException {
        String con = new String(ch,start,length);
        if(!"".equals(con.trim())&&(isName||isAge)){
            System.out.println(con);
        }
        isName = false;
        isAge = false;
    }

    @Override
    public void endDocument() throws SAXException {
    }

    @Override
    public void endElement(String uri,String localName,String qName) throws SAXException {
    }

    @Override
    public void startDocument() throws SAXException {
    }

    @Override
    public void startElement(String uri,String qName,Attributes attributes) throws SAXException {
        if("name".equals(qName)){
            isName = true;
        }else if("age".equals(qName)){
            isAge = true;
        }
    }

}

// 定义事件处理类(显示stu的所有信息)
class MyDefaultHandler extends DefaultHandler {

    @Override
    // 发现文档开始
    public void startDocument() throws SAXException {
        System.out.println("startDocument()方法");
    }

    @Override
    // 发现xml文件中的一个元素
    public void startElement(String uri,Attributes attributes) throws SAXException {
        System.out.println("属性名称:" + qName);
    }

    @Override
    // 发现xml文件中的文本
    public void characters(char[] ch,length);
        // 显示文本内容
        if (!con.trim().equals("")) {
            System.out.println(con);
        }
    }

    @Override
    // 发现xml文件中的一个元素结束
    public void endElement(String uri,String qName) throws SAXException {
        super.endElement(uri,localName,qName);
    }

    @Override
    // 发现文档结束
    public void endDocument() throws SAXException {
        System.out.println("endDocument()方法");
    }

}

3.DOM4J解析:

要解析的xml文件内容:

<?xml version="1.0" encoding="utf-8"?>

<class> 
  <student> 
    <name myname="xiaohong">小红</name>  
    <sex>girl</sex>  
    <age>15</age> 
  </student>  
  <student> 
    <name myname="xiaoming">小明</name>  
    <sex>boy</sex>  
    <age>13</age> 
  </student> 
</class>

java解析代码:

package com.huihui.dom4j;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.List;

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

//使用Dom4j对xml文件进行crud操作
public class MyDom4jTest1 {

    public static void main(String[] args) throws Exception {
        // 得到解析器
        SAXReader saxReader = new SAXReader();
        // 指定解析哪个xml文件
        Document document = saxReader.read(new File("src/class.xml"));

        // 获取xml文件的根元素
        Element root = document.getRootElement();
        // list(root);

        // read(document);

        // add(document);

        //delete(document);

        //update(document);

        addByIndex(document);

    }




    // 遍历xml文件
    public static void list(Element element) {

        System.out.println(element.getName());// 打印元素名称
        System.out.println(element.getTextTrim());// 打印元素中的文本内容

        Iterator iterator = element.elementIterator();

        while (iterator.hasNext()) {
            Element e = (Element) iterator.next();
            // 递归
            list(e);
        }
    }

    // 指定读取某个元素(eg:读取第一个学生的信息)
    public static void read(Document document) {

        Element root = document.getRootElement();// 获取根元素
        // root.element("student"):表示取出root元素下的一个student元素
        // root.elements("student"):表示取出根元素下的所有student元素
        // root.elements("student").get(0):表示取出根元素下的第一个student元素
        Element e = (Element) root.elements("student").get(1);
        // 取出元素下的内容值
        System.out.println(e.element("name").getText());
        // 取出元素中的属性值
        System.out.println(e.element("name").attributeValue("myname"));

        /** * 测试能否跨层去取出元素 测试结果:IndexOutOfBoundsException 结果:不能跨层取出元素,除非使用xPath技术 */
        // Element e1 = (Element) root.elements("name").get(0);

        // 从正常的数据中取出后

    }

    // 添加元素(eg:添加一个student元素到xml文件中去)
    public static void add(Document document) throws Exception {
        // 创建一个student元素对象
        Element newStu = DocumentHelper.createElement("student");
        Element newStu_name = DocumentHelper.createElement("name");
        newStu_name.addAttribute("myname","xiaofang");// 给元素添加属性
        newStu_name.setText("小芳");// 给元素添加内容
        Element newStu_sex = DocumentHelper.createElement("sex");
        Element newStu_age = DocumentHelper.createElement("age");
        // 把三个子元素挂载到newStu下
        newStu.add(newStu_name);
        newStu.add(newStu_sex);
        newStu.add(newStu_age);
        // 再把newStu元素加到根元素下
        document.getRootElement().add(newStu);

        // 把xml文件更新一下

        updateXML(document);
    }


    // 删除元素(eg:删除第一个student元素)
    public static void delete(Document document) throws Exception {
        // 找到第一个student元素
        Element e = (Element) document.getRootElement().elements("student").get(0);
        // 删除找到的student元素
        // e.getParent().remove(e);

        // 删除某元素的某个属性(删除name元素的myname属性)
        Element e_name = (Element) e.elements("name").get(0);
        e_name.remove(e_name.attribute("myname"));

        updateXML(document);
    }

    // 更新元素(eg:把所有student元素的age都加3)
    public static void update(Document document) throws Exception {
        // 得到所有student的age
        List<Element> elements = document.getRootElement().elements("student");
        for (Element e1 : elements) {
            // 从student中取出age元素
            Element age = e1.element("age");
            age.setText(Integer.parseInt(age.getText()) + 3 + "");//修改age元素的内容文本

            //从student中取出name元素
            Element name = e1.element("name");
            name.addAttribute("myname","haha");//修改name元素的myname属性

        }

        updateXML(document);

    }

    //添加一个元素到指定的位置(添加一个student,在每个name为小红的student元素之后,在小明之前)
    public static void addByIndex(Document document) throws Exception{
        //创建一个student元素
        Element newStu = DocumentHelper.createElement("student");
        Element newStu_name = DocumentHelper.createElement("name");
        newStu_name.setText("小华");
        Element newStu_sex = DocumentHelper.createElement("sex");
        newStu_sex.setText("男");
        Element newStu_age = DocumentHelper.createElement("age");
        newStu_age.setText("30");
        //将name,sex,age元素挂载到student元素下面
        newStu.add(newStu_name);
        newStu.add(newStu_sex);
        newStu.add(newStu_age);


        //得到所有student元素的List(循环遍历的目的是如果有多个name是小红的student元素,那么就要在每个name为小红的student元素之后添加新的student元素)
        List<Element> elements = document.getRootElement().elements("student");
        for (int i = 0; i < elements.size(); i++) {
            //取出各个student的name元素
            Element name = elements.get(i).element("name");
            if("小红".equals(name.getText())){
                elements.add(i+1,newStu);//在位置1(也就是xml文档中的第二个位置)添加元素
            }
        }

        //更新xml文档
        updateXML(document);
    }

    //更新xml文档
        private static void updateXML(Document document)
                throws UnsupportedEncodingException,FileNotFoundException,IOException {
            // 如果元素名称为中文,直接输出就会出现中文乱码问题,使用OutputFormat解决中文乱码的问题
            OutputFormat format = OutputFormat.createPrettyPrint();
            format.setEncoding("utf-8");
            XMLWriter xmlWriter = new XMLWriter(new FileOutputStream(new File("src/class.xml")),format);

            xmlWriter.write(document);
            xmlWriter.close();
        }


}

DOM4J补充说明:

XPath:

为什么使用XPath?
1.为了我们更方便的访问某个节点,我们可以使用xpath技术,当使用xpath之后,就可以非常方便的读取到指定的节点了(可以跨层取出元素).
2.xpath往往是结合DOM4J搭配一起使用
3.注意:要引入jaxen-1.1-beta-6.jar包

Dom4j结合xpath一起使用的案例:
要解析的xml文件:

<?xml version="1.0" encoding="utf-8"?>

<class> 
  <student> 
    <name myname="xiaohong">小红</name>  
    <sex>girl</sex>  
    <age>15</age> 
  </student>  
  <student> 
    <name myname="xiaoming">小明</name>  
    <sex>boy</sex>  
    <age>13</age> 
  </student> 
</class>

java解析代码:

package com.huihui.dom4j;

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

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

//dom4j配合xpath使用的案例
public class Dom4jAndXpath {
    public static void main(String[] args) {

        try {
            //1.得到SAXReader解析器
            SAXReader saxReader = new SAXReader();
            //2.指定要解析的xml文件
            Document document = saxReader.read(new File("src/class.xml"));
            //3.可以随心所欲的读取xml文件了

            //基本的XPath语法类似于在一个文件系统中定位文件,如果路径以斜线 / 开始,那么该路径就表示到一个元素的绝对路径
// List<Element> list = document.selectNodes("/class/student/sex");//取出class元素下边的student元素下的所有的sex元素
// for (int i = 0; i < list.size(); i++) {
// String text = list.get(i).getText();
// System.out.println("所有的sex元素的内容:"+text);
// }

            //如果路径以双斜线 // 开头,则表示选择文档中所有满足双斜线//之后规则的元素(无论层级关系)
// List<Element> list = document.selectNodes("//student");
// System.out.println(list.size());

            //星号 * 表示选择所有由星号之前的路径所定位的元素
            List<Element> list = document.selectNodes("/class/student/*");
            System.out.println(list.size());

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

    }

}

xpath的一些相关内容的说明: 1.基本的XPath语法类似于在一个文件系统中定位文件,那么该路径就表示到一个元素的绝对路径 2.如果路径以双斜线 // 开头,则表示选择文档中所有满足双斜线//之后规则的元素(无论层级关系) 3.星号 * 表示选择所有由星号之前的路径所定位的元素 4.方块号里的表达式可以进一步的指定元素,其中数字表示元素在选择集里的位置,而last()函数则表示选择集中的最后一个元素.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读