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

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 localName, 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, String localName, String qName, Attributes attributes) throws SAXException {
        System.out.println("属性名称:" + qName);
    }

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

    @Override
    // 发现xml文件中的一个元素结束
    public void endElement(String uri, String localName, 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()函数则表示选择集中的最后一个元素.

时间: 2024-08-25 13:30:53

XML解析的三种方式(dom,sax,dom4j)的相关文章

XML解析的三种方式

参考:http://blog.csdn.net/liuhe688/article/details/6415593 首先定义一个接口 package com.lei.xml; import java.io.InputStream; import java.util.List; public interface XMLParser { // 解析xml <T> List<T> xmlParse(InputStream is); //构造xml <T> String xmlS

详解android解析Xml的三种方式——DOM、SAX以及XMLpull

今天学习了android解析Xml的三种方式——DOM.SAX以及XMLpull,这里对它们进行总结. 如果理解有误,欢迎指正   ^_* 一.DOM方式解析: xml是先把xml文档都读到内存中,然后再用DOM API来访问树形结构,并获取数据.这个写起来很简单,但是很消耗内存.要是数据过大,手机不够牛逼,可能手机直接死机. 常用的DoM接口和类: Document:该接口定义分析并创建DOM文档的一系列方法,它是文档树的根,是操作DOM的基础.Element:该接口继承Node接口,提供了获

解析Xml文件的三种方式及其特点

解析Xml文件的三种方式 1.Sax解析(simple api  for xml) 使用流式处理的方式,它并不记录所读内容的相关信息.它是一种以事件为驱动的XML API,解析速度快,占用内存少.使用回调函数来实现. 1 class MyDefaultHander extends DefaultHandler{ 2 private List<Student> list; 3 private Student student; 4 5 @Override 6 public void startDo

爬虫之数据解析的三种方式

一,正则表达式解析 re正则就不写了,前面已经写入一篇很详细的正则表达式模块了~ 而且,在爬虫中,下面两种方式用的多一些~ 正则表达式:https://www.cnblogs.com/peng104/p/9619801.html 大致用法: pattern = re.compile('<dd>.*?board-index.*?>(\d+)</i>.*?src="(.*?)".*?name"><a' +'.*?>(.*?)<

爬虫数据解析的三种方式

一.正则表达式解析 常用正则表达式回顾: 单字符: . : 除换行以外所有字符 [] :[aoe] [a-w] 匹配集合中任意一个字符 \d :数字 [0-9] \D : 非数字 \w :数字.字母.下划线.中文 \W : 非\w \s :所有的空白字符包,括空格.制表符.换页符等等.等价于 [ \f\n\r\t\v]. \S : 非空白 数量修饰: * : 任意多次 >=0 + : 至少1次 >=1 ? : 可有可无 0次或者1次 {m} :固定m次 hello{3,} {m,} :至少m次

android解析XML总结-SAX、Pull、Dom三种方式

在android开发中,经常用到去解析xml文件,常见的解析xml的方式有一下三种:SAX.Pull.Dom解析方式.最近做了一个android版的CSDN阅读器,用到了其中的两种(sax,pull),今天对android解析xml的这三种方式进行一次总结. xml示例(channels.xml)如下: <?xml version="1.0" encoding="utf-8"?> <channel> <item id="0&q

(五十七)android解析XML总结(SAX、Pull、Dom三种方式)

一.SAX.DOM.PULL的比较 SAX.DOM.PULL各有自己的特点,具体操作XML的时候该如何选择呢? 1.内存占用 这是一个根本性问题.由于Android手机性能相对于现在的应用操作还是有限的,程序对内存的占用直接影响到了解析XML的速度.在这点上,SAX.Pull以它们比DOM占用更少的内存的解析方式,更适合于Android手机开发. 2.编程方式 SAX采用事件驱动,在相应事件触发的时候,会调用用户编写好的方法.也就是说,每解析一类XML,就要编写一个新的适合该类XML的处理类.这

javascript创建函数的三种方式

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content=

解析XML文件的两种方式 SAX和DOM

1.数据解析 解析的基本概念 所谓“解析”:从事先规定好的格式中提取数据 解析的前提:提前约定好格式,数据提供方按照格式提供数据.数据获取方则按照格式获取数据 iOS开发常见的解析:XML解析.JSON解析 2.XML数据结构 XML:Extensible Markup language(可扩展标记语言),主流数据格式之一,可以用来存储和传输数据. XML数据格式的功能 数据交换 内容管理 用作配置文件 XML数据结构的语法 声明 节点使用一对标签表示:起始和结束标签. 根节点是起始节点,只有一