使用dom4j解析、增删改xml文档,xPath技和SAX解析

一、dom4j解析xml
二、删改xml文档
三、xPath技术
四、SAX解析xml

一、dom4j解析xml

xml 是一种可可扩展标记语言,用于标记电子文件使其具有结构性的标记语言。标记指计算机能理解得信息符号,通过此种标记,计算机之间可以处理包含各种的信息。也可以用来标记数据,定义数据类型,是一种允用户对自己的标记语言进行定义的源语言。xml文件除了给开发者看,更多情况是程序读取xml文件的内容

xml解析的方式: 1、DOM解析
1)JAXP
2)JDOM
3)Dom4J(三大框架的默认读取xml工具就是Dom4J)
2、SAX解析
1)Sax

dom4j是一个Java的XML API,用来读写XML文件的。Dom4j是一个易用的、开源的库,用于XML,XPath和XSLT。它应用于Java平台,采用了Java集合框架并完全支持DOM,SAX和JAXP。
xml解析器把解析xml文档时,把xml文件的各个部分的内容封装成对象,我们通过这些对象来操作xml文档,这种方法叫做DOM解析(DOM编程)

Document树只有一个根标签。树上分分子,叫节点Node() 节点的信息(封装在Node对象):
1、节点名称
2、节点类型(标签节点,属性节点,文本节点,注释节点)
节点类型
1、标签节点: 封装在Element对象
标签名称
2、属性节点: 封装在Attribute对象
属性名称
属性值
3、文本节点: 封装在Text对象
文本内容


调用dom4j的类,需要导入dom4j的jar包。
下载dom4j.jar

dom4j解析xml主要用到的类和方法主要有:

//SAXReader creates a DOM4J tree from SAX parsing events.
//SAXReader 从解析xml文件,创建一个dom4J树
SAXReader sax = new SAXReader();
Document doc = sax.read()

//Returns the root Element for this document.
//返回一个根标签
Element rootElement = doc.getRootElement();

//后面,就主要是Element标签的操作。
//Returns the attributes that this element contains as a List
//返回一个属性列表
public List attributes()

//Returns an iterator over all this elements child elements.
//返回子标签的迭代器
public Iterator elementIterator()

//返回根据子标签的名字,返回子标签的文本内容
public String elementText(String name)


相应的代码:

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Iterator;

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

/**
 * Description:
 * 使用domj4解析xml文件
 * 
 * @author Lee
 * */
public class Parser {

    /**
     * Description :
     * 使用dom4j的SAXReader类解析xml文件
     * 
     * */
    public static void test1(){
        /*
         * SAXReader creates a DOM4J tree from SAX parsing events.
         * */
        SAXReader sax = new SAXReader();

        try{
            /*
             * Reads a document from a given stream.
             * return a newly document instance.
             * 从输入流中读取一个ducument实例,并返回。
             * Document对象,代表一个完整xml文档。
             * 通过Document对象可以得到其下面的其他节点对象,通过节点对象获取相应的信息。
             * */
            Document doc = sax.read(
                    new FileInputStream(
                            "C:\\Users\\lenovopc\\workspace\\"
                            + "Demo\\src\\prop.xml"));
            //获取根元素
            Element rootElement = doc.getRootElement();
            //获取根元素的迭代器
            Iterator iterator = rootElement.elementIterator();
            while(iterator.hasNext()){

                //获取子元素
                Element subElement = (Element)iterator.next();

                /*
                 *  This returns the attribute value for the attribute with the given name 
                 *  and any namespace or null if there is no such attribute 
                 *  or the empty string if the attribute value is empty.
                 * 
                 * */
                //获取子元素的id属性的值
                String id = subElement.attributeValue("id");

                //或许子元素的孙元素的值
                String name = subElement.elementText("name");
                String sex = subElement.elementText("sex");

                System.out.println("id="+id+",name="+name+",sex="+sex);
            }

        }catch(IOException e){
            e.printStackTrace();
        }catch(DocumentException e){
            e.printStackTrace();
        }

    }

    public static void main(String[] args) {
        test1();
    }

}



二、删改xml文档

dom4j删改xml主要用到的类和方法主要有:

//XMLWriter takes a DOM4J tree and formats it to a stream as XML.
//XMLWriter 将一个dom4j树,格式化输出成一个xml文档
public class XMLWriter extends XMLFilterImpl implements LexicalHandler
//This will print the Document to the current Writer.
public void write(Document doc) throws IOException

//创建一个DOM4J树
public final class DocumentHelper extends Object
public static Document createDocument()

//1、增加: 
DocumentHelper.createDocument()  //增加文档
addElement("名称")  //增加标签
addAttribute("名称",“值”)  //增加属性
//2、修改:
Attribute.setValue("值")  //修改属性值
Element.addAtribute("同名的属性名","值")  //修改同名的属性值
Element.setText("内容")  //修改文本内容
//3、删除
Element.detach();  //删除标签  
Attribute.detach();  //删除属性


package com.xml;

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

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;

/**
 * Description:
 * 使用dom4j修改xml文件
 * 
 * @author Lee
 * */
public class Modify {


    /**
     * Description:
     * 创建一个document对象,添加标签、属性,并输出成一个xml文件
     * 
     * 
     * */
    public static void test1(){
        //创一个document对象
        Document doc = DocumentHelper.createDocument();
        //添加一个根标签(有且仅有一个根标签)
        Element rootElt = doc.addElement("Students");

        //为根标签添加子标签
        Element subElt1 = rootElt.addElement("student");
        Element subElt2 = rootElt.addElement("student");

        //为子标签添加属性
        subElt1.addAttribute("id", "1");
        subElt2.addAttribute("id", "2");

        //为子标签添加文本
        subElt1.addText("lee");
        subElt2.addText("wang");

        //指定xml格式,编码
        OutputFormat format = OutputFormat.createPrettyPrint();
        //OutputFormat fotmat = OutputFormat.createCompactFormat();
        format.setEncoding("utf-8");

        //输出该xml文档
        XMLWriter writer = null;
        try{
            writer = new XMLWriter(
                new FileOutputStream("./newprop.xml"),format);

            //将document对象输出成一个xml文件
            writer.write(doc);

        }catch(IOException e){
            e.printStackTrace();
        }finally{
            //关闭资源
            try{
                writer.close();
            }catch(IOException e){
                e.printStackTrace();
            }
        }

    }

    /**
     * Description:
     * 修改,删除xml文件内容
     * 
     * */
    public static void test2(){
        //修改属性、文本
        //方法一:获得标签对象, 获得属性对象,修改属性对象的值
        //elt.attribute().setValue(""); 
        //方法二:获取标签对象,添加一个同名属性的犯法,来修改属性对象的值
        //elt.addAttribute();

        //删除标签,属性,文本
        //elt.detach();自我移除  parentElt.remove(childElt);通过父标签移除子标签

        //读取想要修改的xml文件
        SAXReader reader = new SAXReader();
        Document doc = null;
        try{
            doc = reader.read(new FileInputStream("./newprop.xml"));
        }catch(IOException |DocumentException e){
            e.printStackTrace();
        }

        //获取根标签
        Element rootElt = doc.getRootElement();
        //获取所有子标签(这里并不是通用的方法,是建立在我们已经知道只有两个标签)
        List<?> subElt = rootElt.elements();
        Element subElt1 = (Element)subElt.get(0);
        Element subElt2 = (Element)subElt.get(1);

        //获取标签属性的对象,修改属性对象的值
        subElt1.attribute("id").setValue("0");
        //也可以通过添加同名属性来修改标签属性
        //subElt1.addAttribute("id","0");

        //修改标签文本值,同时也可以修改为空字符,以达到删除文本的目的
        subElt1.setText("huang");


        //获取标签的属性对象,调用detach()方法删除该属性对象
        subElt2.attribute("id").detach();
        //或者通过标签对象调用remove()方法传入属相对象,删除该属性对象
        //subElt2.remove(subElt2.attribute("id"));

        //标签对象通过调用detach()方法,移除标签对象本身
        subElt2.detach();
        //也可以通过父标签remove()方法,移除子标签
        //rootElt.remove(subElt2);



        //设置文本编码,格式
        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding("utf-8");

        //将document对象输出为xml文件
        XMLWriter writer = null;
        try{
            writer = new XMLWriter(
                        new FileOutputStream("./newprop.xml"),format);
            writer.write(doc);
        }catch(IOException e){
            e.printStackTrace();
        }finally{
            //关闭资源
            try {
                writer.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    public static void main(String[] args) {
        test1();
        //test2();
    }

}



三、xPath技术

XPath即为XML路径语言,它是一种用来确定XML(标准通用标记语言的子集)文档中某部分位置的语言。XPath基于XML的树状结构,提供在数据结构树中找寻节点的能力。
主要用于快速获取所需要的节点对象。xpath是一门xml文档中查找信息语言,xpath可以用来xml文档中对元素和属性进行遍历。
dom4j内置支持xpath技术


调用xPath的类,需要导入xPath的jar包。可以在dom4j的jar包中找得到
\\dom4j-1.6.1\lib\jaxen-1.1-beta-6.jar

简单xPath语法
/    绝对路径   表示从xml的根位置开始子元素
//   相对路径   表示不分任何层次结构的选择元素
*    通配符   表示匹配所有元素
[]   条件   表示选择什么条件下元素
@    属性   通过前缀@来指定
and  且关系

简单的例子:
[1]                            代表第一个
[last()]                       代表最后一个
//BBB[@*]                      代表所有有属性的BBB元素
//BBB[not(@*)]                 代表所有没有属性的BBB元素
//BBB[@id='b1']                带表所有id属性且值为B1的BB元素
//name/text()                  代表所有name标签节点的文本
//student/name[text='lee']     代表所有student标签下name标签文本内容为lee的name标签(然后。通过name标签对象获取父标签对象)

关于xpath语法见于官方网站…](http://www.zvon.org/xxl/XPathTutorial/Output_chi)

xPath主要用到的方法

List<Node> selectNodes("xpath表达式");   //查询多个节点对象
Node selectSingleNode("xpath表达式");  //查询一个节点对象


package com.xml;

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

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

/**
 * Description:
 * 使用xPath技术
 * 
 * @author lee
 * 
 * */
public class XPath {

    /**
     * Description:
     * xPath技术快速找到需要的节点
     * 
     * */
    public static void test1(){
        //xpath的表达式就是xpath的语法
        //List<Node> document.selectNodes("xpath的表达式");
        //Node document.selectSingleNode("xpath的表达式");

        //读取xml文档
        Document doc = null;
        try{
            doc  = new SAXReader().read(new FileInputStream("./newprop.xml"));

        }catch(IOException |DocumentException e){
            e.printStackTrace();
        }

        //通过xPath技术,快速地找到所需要的节点
        //     //student[@id='2']  ->  找到第一个有id属性且值为2的student标签节点
        Element stuElt1 = (Element)doc.selectSingleNode("//student[@id='2']");
        if(stuElt1!=null)
            stuElt1.setText("huang");
        else
            System.out.println("未找到该标签");

        //    //student[text()='lee']  ->  找到第一个文本内容为lee的student标签节点
        Element stuElt2 = (Element)doc.selectSingleNode("//student[text()='lee']");
        if(stuElt2!=null)
            stuElt2.setText("zeng");
        else
            System.out.println("未找到该标签!");

        //指定编码,格式
        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding("utf-8");

        //将documen对象苏输出成xml文档
        XMLWriter writer = null;
        try{
            writer = new XMLWriter(new FileOutputStream("./newprop.xml"),format);
            writer.write(doc);
        }catch(IOException e){
            e.printStackTrace();
        }finally{
            try{
                writer.close();
            }catch(IOException e){
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        test1();
    }

}



程序所生成,调用xml文件内容:

<?xml version="1.0" encoding="utf-8"?>
<Students>
  <student id="1">lee</student>
  <student id="2">wang</student>
</Students>



四、SAX解析xml

SAX,全称Simple API for XML,既是一种接口,也是一种软件包。它是一种XML解析的替代方法。SAX不同于DOM解析,它逐行扫描文档,一边扫描一边解析。
由于应用程序只是在读取数据时检查数据,因此不需要将数据存储在内存中,相比DOM解析原理(一次性把xml文档加载进内存然后在内存中构建documen树。不适合读取大容量的文件,容易导致内存溢出。),对于大型文档的解析是个巨大优势。

实际上,sax解析是基于事件的编程方法,当调用SAXParser的parse()方法去解析一个xml文档的时候,该方法会会从xml文件中,从上到下逐步地读取,当读取到相应的内容时就会调用像相应的方法。
而我们需要做的就是,实现DefaultHandler接口的方法。实现方法,在遇到相应内容时,做出相应的处理。


SAX解析主要用到的类和方法


//以下,是DefaultHandler接口的关键方法

//Receive notification of the beginning of the document.
//当开始读取整个document树时调用该方法
public void startDocument() throws SAXException

//Receive notification of the end of the document.
//当结束读取document树时调用该方法
public void endDocument() throws SAXException

//Receive notification of the start of an element.
//当读取到开始标签时调用该方法
public void startElement(String uri,
                         String localName,
                         String qName,
                         Attributes attributes)
                  throws SAXException

//Receive notification of the end of an element.
//当读到结束标签时调用该方法
public void endElement(String uri,
                       String localName,
                       String qName)
                throws SAXException

//Receive notification of character data inside an element.
//读到文本内容时会调用该方法
public void characters(char[] ch,
                       int start,
                       int length)
                throws SAXException


例如,我们将xml原因输出在控制台中。

package com.xml;

import java.io.FileInputStream;
import java.io.IOException;

import javax.xml.parsers.ParserConfigurationException;
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;

/**
 * Description:
 * 用sax解析xml文件
 * 
 * @author lee
 * */
public class SAX {

    /**
     * Description:
     * sax解析xml文件
     * */
    public static void test1(){
        //创建一个SAXParser对象
        //SAXParser的构造方法是protected的,需要通过调用工厂类创建SAXParser类
        SAXParser parser = null;
        try{
            //构造一个SAXParser对象
            parser = SAXParserFactory.newInstance().newSAXParser();
        }catch(SAXException | ParserConfigurationException e){
            e.printStackTrace();
        }

        //传入一个实现SAX2 事件处理程序的默认基类的类,来解析xml文件
        try{
            parser.parse(new FileInputStream("./newprop.xml"), new MyDefaultHandler());
        }catch(SAXException |IOException e){
            e.printStackTrace();
        }

    }

    /**
     * Description:
     * 主方法
     * 
     * */
    public static void main(String[] args) {
        test1();

    }

}

/**
 * Description:
 * Application writers can extend this class 
 * when they need to implement only part of an interface; 
 * parser writers can instantiate this class to provide default handlers 
 * when the application has not supplied its own.
 * 
 * 实际上,sax解析是基于事件的编程方法,当调用SAXParser的parse()方法去解析一个xml文档的时候,
 * 该方法会会从xml文件中,从上到下逐步地读取,当读取到相应的内容时就会调用像相应的方法。
 * 而我们需要做的就是,实现DefaultHandler接口的方法。实现方法,在遇到相应内容时,做出相应的处理。
 * 
 * 例如,现在我们需要实现将整个xml文档输出在控制台中。
 * @author lee
 * */
class MyDefaultHandler extends DefaultHandler{
    //创建一个StringBuffer实例来装整个xml
    StringBuffer xml = new StringBuffer();
    //表示当前读取到的内容
    String current = "";

    /**
     * Description:
     * 当开始读取整个document树时调用该方法
     * 
     * */
    @Override
    public void startDocument(){

    }

    /**
     * Description:
     * 当结束读取document树时调用该方法
     * 
     * */
    @Override
    public void endDocument(){
        //在结束整个document文档时,输出xml
        System.out.println(xml);
    }

    /**
     * Description:
     * 当读取到开始标签时调用该方法
     * 
     * @param qName 表示标签名
     * @param attributes 表示标签属性列表
     * 
     * */
    @Override
    public void startElement(String uri, String localName,String qName,Attributes attributes) throws SAXException{
        //赋值当前标签的名字
        current = qName;

        //添加开始标签名字
        xml.append("<"+qName);

        //添加标签属性
        for(int i=0;i<attributes.getLength();i++){
            xml.append(" "+attributes.getQName(i)+"="+attributes.getValue(i));
        }

        xml.append(">");
    }

    /**
     * Description:
     * 当读到结束标签时调用该方法
     * 
     * @param qName 表示结束标签的名字
     * 
     * */
    @Override
    public void endElement(String uri, String localname, String qName){
        //结束标签时,当前标签名字赋值为空
        current = "";

        //添加结束标签名字
        xml.append("<"+qName+">");

    }

    /**
     * Description:
     * 读到文本内容时会调用该方法
     * 
     * @param ch 表示当前读取到的所有的文本内容
     * @param start 表示当前读取的文本内容的开始位置
     * @param length 表示当前读取的文本内容的长度
     * 
     * */
    @Override
    public void characters(char[] ch, int start,int length){
        //获取当前读取的文本内容
        String text = new String(ch,start,length);
        //添加文本内容
        xml.append(text);

    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值