博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

05XML

Posted on 2019-02-05 16:46  心默默言  阅读(142)  评论(0编辑  收藏  举报

1.XML入门

1.1 引入

HTML, 超文本标记语言。

html语言语法是很松散的!                 

1)标签不区分大小写的!

2)标签可以不匹配的。

由w3c组织,针对html的语法缺陷,去设计了另一门,叫xml语言。

html语言的标签是固定的。

1.2 XML语言

 XML:,  Extend Markup lanuage 可扩展标记语言。                        

 HTML               XML

概念       超文本标记语言      可扩展标记语言

标记数量   是固定的             是不固定的,可扩展的

作用       负责网页的结构      

1)描述带关系的数据结构(作为软件的配置文件)

    

配置使用场景:

1)框架(struts2 , hibernate,spring),xml作为框架的配置文件

2)tomcat服务器软件配置文件(web.xml server.xml)

                                                              

2)装载数据(作为小型的“数据库”)。

1.3组成部分

1. 文档声明
  1. 格式:<?xml 属性列表 ?>
  2. 属性列表:
    * version:版本号,必须的属性
    * encoding:编码方式。告知解析引擎当前文档使用的字符集,默认值:ISO-8859-1
    * standalone:是否独立
      * 取值:
        * yes:不依赖其他文件
        * no:依赖其他文件
2. 指令(了解):结合css的
  * <?xml-stylesheet type="text/css" href="a.css" ?>
3. 标签:标签名称自定义的
  * 规则:
    * 名称可以包含字母、数字以及其他的字符
    * 名称不能以数字或者标点符号开始
    * 名称不能以字母 xml(或者 XML、Xml 等等)开始
    * 名称不能包含空格

2.XML作用

2.1 作为软件配置文件

PCweb服务器:学生管理系统 - > 添加学生 -> name=张三,age=20  -》 提交到后台程序 - 》 把数据存储到数据库中         

两台通讯条件;

IP地址和端口

java代码:

根据ip和端口连接数据库服务器(ip改动会改变代码)                      

properties文件:

ip=211.34.21.43

port=20

xml文件:
                    <host-list>
                        <host id="main">
                            <ip> 211.34.21.43</ip>
                            <port>20</port>
                        </host>
                        <host id="backup">
                            <ip> 211.34.21.44</ip>
                            <port>20</port>
                        </host>
                    </host-list>

PC数据库服务器1:oracle数据库      211.34.21.43     20                               

PC数据库服务器2:oracle数据库      211.34.21.44     20

2.2 作为小型数据库                      

教师管理系统      教师信息: 姓名  工龄  邮箱地址

传输数据:

字符串:  张|三|20|zhangsan@qq.com|.......|....    (格式不是行业规范的,不通用)

xml格式:

         <teacher-list>

                <teacher>

                       <name></name>

                       <email></email>

                       <workage></workage>

                        ....

                </teacher>

                <teacher>

                    <name></name>

                    <email></email>

                    <workage></workage>

                     ....

              </teacher>
        <teacher-list>              (xml是w3c组织的制定的标准)

 

财务系统

发邮件给教师:

邮箱地址   姓名

方案1:财务系统中也存储了一套教师信息。数据维护成本比较高了!!!

方案2: 财务系统使用的教师数据从教师管理系统中发送过去的。

3.XML语法                             

3.1 标签

<student>学生</student> 

 注意:

1)分带标签体的标签,也有空标签。

2)标签是区分大小写

3)标签一定要配对

4)标签中间不能含有空格

5)不能使用数字开头

6)如果没有指定名称空间的话, 标签名中间不能含有冒号

7)在同一个xml文件中,有且仅有一个根标签        

3.2 属性

 <student id="1"></student>

注意:

1)一个属性分为属性名和属性值。属性名和值之间使用=号分割。

2)属性值一定要使用单引号或者双引号包含,不能省略,也不能单双混用!

3)一个标签内可以包含多个属性,但是不能出现同名的属性

3.3 注释

 <!--  xml --->

3.4 文档声明

<?xml version="1.0"  encoding="码表"?>

version: xml的版本号,必须要写

encoding: 表示解析xml文件内容时使用的码表

xml文件的编码问题:          

1)xml文件内容保存的编码(另存为-》选择编码保存)

2)解析xml文件内容的编码(   <?xml version="1.0" encoding="utf-8"?> )

以上两个编码必须保存一致,才能避免中文乱码问题。

注意:

如果在ecplise开发工具上,编写xml文件,那么xml文件内容自动按照文档声明的encoding的编码保存,所以不会中文乱码问题.

3.5 转义字符

和html的转义字符.

3.6 CDATA块

把CDATA块中的内容全部原样输入

3.7 约束

规定xml文档的书写规则
  作为框架的使用者(程序员):
    1. 能够在xml中引入约束文档
    2. 能够简单的读懂约束文档

分类:

    1. DTD:一种简单的约束技术
    2. Schema:一种复杂的约束技术

#student.dtd
<!
ELEMENT students (student*) > <!ELEMENT student (name,age,sex)> <!ELEMENT name (#PCDATA)> <!ELEMENT age (#PCDATA)> <!ELEMENT sex (#PCDATA)> <!ATTLIST student number ID #REQUIRED>

引入dtd文档到xml文档中
  内部dtd:将约束规则定义在xml文档中
  外部dtd:将约束的规则定义在外部的dtd文件中
    本地:<!DOCTYPE 根标签名 SYSTEM "dtd文件的位置">
    网络:<!DOCTYPE 根标签名 PUBLIC "dtd文件名字" "dtd文件的位置URL">

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE students SYSTEM "student.dtd">

<students>
    <student number="itcast_0001">
        <name>tom</name>
        <age>18</age>
        <sex>male</sex>
    </student>
    
</students>

Schema:
  引入:
    1.填写xml文档的根元素
    2.引入xsi前缀. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3.引入xsd文件命名空间. xsi:schemaLocation="http://www.itcast.cn/xml student.xsd"
    4.为每一个xsd约束声明一个前缀,作为标识 xmlns="http://www.itcast.cn/xml"

<?xml version="1.0"?>
<xsd:schema xmlns="http://www.itcast.cn/xml"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        targetNamespace="http://www.itcast.cn/xml" elementFormDefault="qualified">
    <xsd:element name="students" type="studentsType"/>
    <xsd:complexType name="studentsType">
        <xsd:sequence>
            <xsd:element name="student" type="studentType" minOccurs="0" maxOccurs="unbounded"/>
        </xsd:sequence>
    </xsd:complexType>
    <xsd:complexType name="studentType">
        <xsd:sequence>
            <xsd:element name="name" type="xsd:string"/>
            <xsd:element name="age" type="ageType" />
            <xsd:element name="sex" type="sexType" />
        </xsd:sequence>
        <xsd:attribute name="number" type="numberType" use="required"/>
    </xsd:complexType>
    <xsd:simpleType name="sexType">
        <xsd:restriction base="xsd:string">
            <xsd:enumeration value="male"/>
            <xsd:enumeration value="female"/>
        </xsd:restriction>
    </xsd:simpleType>
    <xsd:simpleType name="ageType">
        <xsd:restriction base="xsd:integer">
            <xsd:minInclusive value="0"/>
            <xsd:maxInclusive value="256"/>
        </xsd:restriction>
    </xsd:simpleType>
    <xsd:simpleType name="numberType">
        <xsd:restriction base="xsd:string">
            <xsd:pattern value="heima_\d{4}"/>
        </xsd:restriction>
    </xsd:simpleType>
</xsd:schema> 
<?xml version="1.0" encoding="UTF-8" ?>
<!-- 
    1.填写xml文档的根元素
    2.引入xsi前缀.  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3.引入xsd文件命名空间.  xsi:schemaLocation="http://www.itcast.cn/xml  student.xsd"
    4.为每一个xsd约束声明一个前缀,作为标识  xmlns="http://www.itcast.cn/xml" 
    
    
 -->
 <students   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xmlns="http://www.itcast.cn/xml" 
            xsi:schemaLocation="http://www.itcast.cn/xml  student.xsd"
             >
     <student number="heima_0001">
         <name>tom</name>
         <age>18</age>
         <sex>male</sex>
     </student>
         
 </students>

4.XML解析

4.1xml解析方式

1)DOM解析:将标记语言文档一次性加载进内存,在内存中形成一颗DOM树

  优点:操作方便,可以对文档进行CRUD的所有操作。

  缺点:占内存。

2)SAX解析:逐行读取,基于事件驱动的。  

  优点:不占内存。

  缺点:只能读取,不能写(增删改)。 

4.2DOM解析的工具

jaxp:sun公司提供的解析器,支持dom和sax两种思想。

jsoup: jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。

PULL:Android操作系统内置的解析器,sax方式的。

dom4j工具: 三大框架读取xml文件的程序。(非官方的,第三方的)

dom for java

4.3dom4j工具使用

1)到dom4j的官方下载 。dom4j-1.6.1.zip

2)导入dom4j的支持jar包、

dom4j-1.6.1.jar核心包

4.4使用dom4j读取xml的标签

<?xml version="1.0" encoding="utf-8" ?>
<!--<contact
        id = "001"
        name="张三"
        gender="男"
        phone="13411112222"
        email="zhangsan@qq.com"
        address="广州天河">
</contact>-->
<contact-list>
    <contact id="001">
        <name>张三</name>
        <gender></gender>
        <phone>13411112222</phone>
        <email>zhangsan@qq.com</email>
        <address>广州天河</address>
    </contact>
    <contact id="002">
        <name>李四</name>
        <gender></gender>
        <phone>13511112222</phone>
        <email>lisi@qq.com</email>
        <address>广州越秀</address>
    </contact>
    <student> </student>
</contact-list>
package cn.jxufe.java.chapter01;

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

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

/**
 * 使用dom4j工具读取一个xml文件
 * 
 * @author zhao
 *
 */
public class w01demo {

    /*
     * 使用dom4j读取xml的标签
     *      getRootElement(): 获取根标签
     *      getName(): 获取标签名称
     *      element("名称"): 获取第一个指定名称的子标签
     *      elements("名称"): 获取指定名称的所有的子标签
     *      elements(): 获取所有子标签
     */
    public static void main(String[] args) throws DocumentException {
        // TODO Auto-generated method stub
        SAXReader reader = new SAXReader();// 2)读取xml文件
        Document doc = reader.read(new File("./src/contact.xml"));
        System.out.println(doc);
        /**
         * 读取标签
         */
        // 1.1 读取根标签
        Element rootElem = doc.getRootElement();
        System.out.println(rootElem);

        // 1.2 获取标签名称
        System.out.println(rootElem.getName());
        // 1.3 获取第一个子标签(根据指定的名称获取第一个子标签)
        Element conElem = rootElem.element("contact");
        System.out.println(conElem.getName());
        System.out.println(conElem);
        System.out.println("==============");
        // 1.4 获取所有子标签(根据指定的名称获取所有同名子标签)
        List<Element> list = rootElem.elements("contact");
        // 遍历List
        // 几种方式?
        // 1)传统for循环
        /*for(int i=0;i<list.size();i++){
            list.get(i); //根据角标获取指定对象
        }*/

        // 2)for-each循环
        for (Element e : list) {
            System.out.println(e);
        }

        // 3)迭代器
        /*Iterator it = list.iterator();
        while(it.hasNext()){ //hasNext(): 判断是否有下一个元素
            it.next(); //next():取出当前对象
        }*/

        System.out.println("================");

        // 1.4 获取所有子标签(不指定名称)
        List<Element> eList = rootElem.elements();
        for (Element e : eList) {
            System.out.println(e);
        }
        System.out.println("===========");

    }

}

4.5使用dom4j获取xml上的属性信息

package cn.jxufe.java.chapter01;

import java.io.File;
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;

/**
 * 使用dom4j获取xml上的属性信息
 * 
 * @author zhao
 *
 */
public class w02demo {
    public static void main(String[] args) throws DocumentException {
        // 1)创建xml解析器
        SAXReader reader = new SAXReader();
        Document doc = reader.read(new File("./src/contact.xml"));

        /**
         * 读取属性 注意:获取属性,必须先得到属性所在的标签
         */
        Element conElem = doc.getRootElement().element("contact");
        // 1.1 在标签上获取属性值(根据属性名称获取对应的属性值)

        String value = conElem.attributeValue("id");
        System.out.println(value);

        Element conElem2 = (Element) doc.getRootElement().elements().get(1);// 返回的是object,强转
        System.out.println(conElem2.attributeValue("id"));

        // 1.2 根据属性名称获取属性对象
        // 拿到标签对象
        conElem = doc.getRootElement().element("contact");
        // 拿到属性对象
        Attribute idAttr = conElem.attribute("id");
        // 通过属性对象拿到 属性名
        String idName = idAttr.getName();
        // 通过属性对象拿到 属性值
        String idValue = idAttr.getValue();
        System.out.println(idName + "=" + idValue);

        Element conElem3 = (Element) doc.getRootElement().elements().get(1);
        // 拿到属性对象
        Attribute idAttr2 = conElem3.attribute("id");
        // 通过属性对象拿到 属性名
        String idName2 = idAttr2.getName();
        // 通过属性对象拿到 属性值
        String idValue2 = idAttr2.getValue();
        System.out.println(idName2 + "=" + idValue2);
        System.out.println("=====================");
        // 1.3 获取标签的所有属性对象
        conElem = doc.getRootElement().element("contact");
        List<Attribute> attrList = conElem.attributes();
        for (Attribute attr : attrList) {
            System.out.println(attr.getName() + "=" + attr.getValue());
        }
    }
}

4.6使用dom4j获取xml的文本信息

package cn.jxufe.java.chapter01;

import java.io.File;

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

/**
 * 使用dom4j获取xml的文本信息
 * 
 * @author zhao
 *
 */
public class w03demo {

    public static void main(String[] args) throws DocumentException {
        // TODO Auto-generated method stub
        SAXReader reader = new SAXReader();
        Document doc = reader.read(new File("./src/contact.xml"));
        
        /**
         * 注意: 在xml文件中,空格和换行会作为xml的内容被解析到。 xml中空格和换行和java代码中空格换行不一样。
         * java代码中的空格和换行是没意义的,为了代码的格式格式好看而已。
         */
        Element con = doc.getRootElement().element("contact");
        System.out.println(con.getText());
        
        /**
         * 读取文本: 注意: 获取文本,要先获取文本所在的标签对象
         */
        // 1.1 拿到所在标签上的文本内容
        Element nameElem = doc.getRootElement().element("contact").element("name");
        String content = nameElem.getText();
        System.out.println(content);

        // 1.2 通过父标签获取指定子标签的文本内容
        Element conElem = doc.getRootElement().element("contact");
        content = conElem.elementText("gender");
        System.out.println(content);
    }

}

4.7使用dom4j把xml文件的信息封装成对象

package cn.jxufe.java.chapter01;

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

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

/**
 * 使用dom4j把xml文件的信息封装成对象
 * 
 * @author zhao
 *
 */
public class w04demo {

    public static void main(String[] args) throws DocumentException {
        // TODO Auto-generated method stub
        // 目标: contact.xml信息 -> List集合
        // 1)读取xml文件
        SAXReader reader = new SAXReader();
        Document doc = reader.read(new File("./src/contact.xml"));

        // 2)创建List对象
        List<Contact> list = new ArrayList<Contact>(); // List接口-》 ArrayList/LinkedList/Vector

        // 3)把xml信息->list对象
        // 3.1 读取到所有contact标签
        List<Element> conList = doc.getRootElement().elements("contact");
        for (Element elem : conList) {
            // 3.2 创建Contact对象
            Contact con = new Contact();

            // 3.3 把contact标签数据放入contact对象中
            con.setId(elem.attributeValue("id"));
            con.setName(elem.elementText("name"));
            con.setGender(elem.elementText("gender"));
            con.setPhone(elem.elementText("phone"));
            con.setEmail(elem.elementText("email"));
            con.setAddress(elem.elementText("address"));

            // 3.4 把contact对象放入list对象
            // 保存数据 list.add(对象)
            list.add(con);
        }

        // 4)输出
        for (Contact con : list) {
            System.out.println(con);
        }
    }

}

4.8写出一个xml文件

package cn.jxufe.java.chapter02;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

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

/*
 * 写出一个xml文件
 */
public class T01demo {

    public static void main(String[] args) throws IOException, DocumentException {
        // TODO Auto-generated method stub
        /*
         * 修改xml信息的步骤
         * 1)读取到原来的xml文件(document对象)
         * 2)操作document对象,改变xml信息(docuement对象)
         * 3)把修改后的document对象写出到xml文件中(覆盖原来的文件)
         */

        Document doc = new SAXReader().read(new File("./src/contact.xml"));
        /*
         * 输出流
         *       字符输出流: 
         *          Writer ->  FileWriter/BufferedWriter
         *                 方法:
         *                     write(char c): 写出一个字符
         *                     write(char[] data): 写出多个字符
         *                     write(String str): 写出一个字符串  
         *       字节输出流
         *          OutputStream -> FileOutputStream/BufferedOutputStream/ObjectOutputStream
         *                     write(byte) :写出一个字节
         *                     write(byte[] data): 写出多个字节
         */
        /**
         * 把内存的document对象写出到硬盘的xml文件
         */
        // 创建输出流
        OutputStream outStream = new FileOutputStream("e:/contact.xml");
        // 1)创建输出对象
        XMLWriter writer = new XMLWriter(outStream);
        // 2)写出数据
        writer.write(doc);
    }

}

4.9写出xml文件的细节

package cn.jxufe.java.chapter02;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

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

/**
 * 写出xml文件的细节
 * 
 * @author zhao
 *
 */
public class T02demo {
    public static void main(String[] args) throws DocumentException, IOException {
        Document doc = new SAXReader().read(new File("./src/contact.xml"));

        // 创建输出流
        OutputStream outStream = new FileOutputStream("e:/contact.xml");
        // 一、设置输出的格式
         OutputFormat format = OutputFormat.createCompactFormat();//紧凑的格式.空格和换行去掉了!!
        // 系统上线了使用
//        OutputFormat format = OutputFormat.createPrettyPrint();// 漂亮的格式。包含空格和换行。 测试时使用
        // 二、 设置输出的编码格式
        /*
         * 作用: 1)影响了xml的文档声明的encoding编码 
         *      2)影响了xml内容保存的编码
         */
        format.setEncoding("gbk");

        // 1)创建输出对象
        XMLWriter writer = new XMLWriter(outStream, format);
        // 2)写出数据
        writer.write(doc);
    }
}

4.10对XML进行增删改查

package cn.jxufe.java.chapter02;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import org.dom4j.Attribute;
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;

public class T03demo {
    /*
     * 查:
            标签: element("name")  
                            elements("name")
                            elements();
                            getName() 标签名称
                            getRootElement(): 根标签
            属性: atrributeValue("name")  属性值
                            atrribute("name")  对象
                            atrributes()  属性对象列表
                            getName() : 属性名
                            getValue() 属性值
            文本:
                          getText();  当前标签的文本
                          elementText("name")  子标签的文本
                        
           增:
            DocumentHelper.createDocument()   文档
            addElement("name");   标签
            addAtribute("name","value" )  属性
            
            改:
            setValue()   修改属性值
            addAttribute(”同名“) 修改属性值
            setText()    修改文本内容
    
             删除:
            detach()   标签、属性
            getParent().remove(标签/属性)
    
     */
    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub
//        add();
//        edit();
        delete();

    }

    public static void add() throws IOException {
        // 1.1 添加空文档
        Document document = DocumentHelper.createDocument();
        // 1.2 添加标签
        Element conListElement = document.addElement("contact-list");
        Element conElement = conListElement.addElement("contact");
        conElement.addElement("name");

        // 1.3 添加属性
        conElement.addAttribute("id", "001");
        conElement.addAttribute("name", "eric");

        // 把文档写出到xml文件中
        OutputStream out = new FileOutputStream("e:/contact.xml");
        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding("utf-8");

        XMLWriter writer = new XMLWriter(out, format);
        writer.write(document);
    }

    public static void edit() throws DocumentException, IOException {
        Document doc = new SAXReader().read(new File("./src/contact.xml"));
        // 修改属性
//        // 1.1 先得到属性对象,再调用方法修改属性值
//        Element conElem = doc.getRootElement().element("contact");
//        Attribute idAttr = conElem.attribute("id");
//        idAttr.setValue("003");

        // 1.2 在标签中添加同名的属性,覆盖属性值
        Element conElem = doc.getRootElement().element("contact");
        conElem.addAttribute("id", "004");

        // 修改文本
        Element nameElem = doc.getRootElement().element("contact").element("name");
        nameElem.setText("王五");

        // 把文档写出到XML中
        OutputStream out = new FileOutputStream("e:/contact.xml");
        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding("utf-8");
        XMLWriter writer = new XMLWriter(out, format);
        writer.write(doc);
    }

    public static void delete() throws DocumentException, Exception {
        Document doc = new SAXReader().read(new File("./src/contact.xml"));
        // 1.1 删除标签
        Element conElem = doc.getRootElement().element("contact");
        conElem.detach(); // 自杀
//        conElem.getParent().remove(conElem); // 他杀

//        // 1.2 删除属性
        Attribute idAttr = doc.getRootElement().element("contact").attribute("id");
        idAttr.detach();

        // 把文档写出到xml文件中
        OutputStream out = new FileOutputStream("e:/contact.xml");
        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding("utf-8");

        XMLWriter writer = new XMLWriter(out, format);
        writer.write(doc);
    }
}

5.xPath技术

5.1引入

问题:当使用dom4j查询比较深的层次结构的节点(标签,属性,文本),比较麻烦!!!

5.2xPath作用

主要是用于快速获取所需的节点对象。

5.3在dom4j中如何使用xPath技术

1)导入xPath支持jar包 。  jaxen-1.1-beta-6.jar

2)使用xpath方法

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

  Node       selectSingleNode("xpath表达式");  查询一个节点对象

<?xml version="1.0" encoding="utf-8" ?>
<contact-list>
    <contact id="001" font="s">
        <name>张三</name>
        <gender></gender>
        <phone>13411112222</phone>
        <email>zhangsan@qq.com</email>
        <address>广州天河</address>
    </contact>
    <contact id="002">
        <name>李四</name>
        <gender></gender>
        <phone>13511112222</phone>
        <email>lisi@qq.com</email>
        <address>广州越秀</address>
    </contact>
    <student> 
    </student>
</contact-list>
package dom4j_xPath;

import java.io.File;
import java.io.FileOutputStream;

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

public class Demo1 {

    public static void main(String[] args) throws Exception {
        /*
         * 需求:删除id为002的标签
         */
        Document doc = new SAXReader().read(new File("d:/contact.xml"));
        //1.查询id为002的标签
        Element contactElem = (Element) doc.selectSingleNode("//contact[@id='002']");

        //2.删除标签
        contactElem.detach();

        OutputFormat format = OutputFormat.createPrettyPrint();//漂亮的格式,有空格和换行,开发、调试的时候用
        FileOutputStream out = new FileOutputStream("d:/contact.xml");
        format.setEncoding("utf-8");
        XMLWriter writer = new XMLWriter(out, format);
        writer.write(doc);
        writer.close();

    }
}

结果:

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

<contact-list> 
  <contact id="001" font="s"> 
    <name>张三</name>  
    <gender></gender>  
    <phone>13411112222</phone>  
    <email>zhangsan@qq.com</email>  
    <address>广州天河</address> 
  </contact>  
  <student></student> 
</contact-list>

5.4xPath语法

/      绝对路径      表示从xml的根位置开始或子元素(一个层次结构)

//     相对路径       表示不分任何层次结构的选择元素。

*      通配符         表示匹配所有元素

[]      条件           表示选择什么条件下的元素

@     属性            表示选择属性节点

and     关系          表示条件的与关系(等价于&&)

text()    文本           表示选择文本内容

6.SAX解析                       

6.1回顾DOM解析

DOM解析原理:一次性把xml文档加载进内存,然后在内存中构建Document树。

  对内存要求比较高。    

  缺点: 不适合读取大容量的xml文件,容易导致内存溢出。 

SAX解析原理: 加载一点,读取一点,处理一点。对内存要求比较低。

6.2SAX解析工具  

SAX解析工具-  Sun公司提供的。内置在jdk中。org.xml.sax.*

核心的API:

  SAXParser类: 用于读取和解析xml文件对象

    parse(File f, DefaultHandler dh)方法: 解析xml文件

      参数一: File:表示 读取的xml文件。

      参数二: DefaultHandler: SAX事件处理程序。使用DefaultHandler的子类

package sax;

import java.io.File;

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 Demo1 {
    public static void main(String[] args) throws Exception {
        //1.创建SAXParser对象
        SAXParser parser = SAXParserFactory.newInstance().newSAXParser();

        //2.调用parse方法
        /*
         * 参数一:xml文档
         * 参数二:DefaultHandler
         */
        parser.parse(new File("./src/contact.xml"), new MyDefaultHandler());

    }
}

/**
 * SAX处理程序
 */
class MyDefaultHandler extends DefaultHandler {

    /*
     * 开始文档时调用
     */
    @Override
    public void startDocument() throws SAXException {
        System.out.println("MyDefaultHandler.startDocument()");
    }

    /**
     * 开始标签调用
     * @param qName:表示开始标签的签名
     * @param attributes:表示开始标签内包含的属性列表
     */
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        System.out.println("MyDefaultHandler.startElement()" + qName);
    }

    /**
     * 结束标签调用
     * 
     */
    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        System.out.println("MyDefaultHandler.endElement()  " + qName);
    }

    /**
     * 读到文本内容的时候调用
     * @param ch:表示xml的所有的文本内容
     * @param start:表示当前文本内容的开始位置
     * @param length:表示当前文本内容的长度
     */
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        String content = new String(ch,start,length);
        System.out.println("MyDefaultHandler.characters()  "+content);
    }

    /*
     * 结束文档时调用
     */
    @Override
    public void endDocument() throws SAXException {
        System.out.println("MyDefaultHandler.endDocument()");
    }
}

输出:

MyDefaultHandler.startDocument()
MyDefaultHandler.startElement()  contact-list
MyDefaultHandler.characters()  
    
MyDefaultHandler.startElement()  contact
MyDefaultHandler.characters()  
        
MyDefaultHandler.startElement()  name
MyDefaultHandler.characters()  张三
MyDefaultHandler.endElement()  name
MyDefaultHandler.characters()  
        
MyDefaultHandler.startElement()  gender
MyDefaultHandler.characters()  男
MyDefaultHandler.endElement()  gender
MyDefaultHandler.characters()  
        
MyDefaultHandler.startElement()  phone
MyDefaultHandler.characters()  13411112222
MyDefaultHandler.endElement()  phone
MyDefaultHandler.characters()  
        
MyDefaultHandler.startElement()  email
MyDefaultHandler.characters()  zhangsan@qq.com
MyDefaultHandler.endElement()  email
MyDefaultHandler.characters()  
        
MyDefaultHandler.startElement()  address
MyDefaultHandler.characters()  广州天河
MyDefaultHandler.endElement()  address
MyDefaultHandler.characters()  
    
MyDefaultHandler.endElement()  contact
MyDefaultHandler.characters()  
    
MyDefaultHandler.startElement()  contact
MyDefaultHandler.characters()  
        
MyDefaultHandler.startElement()  name
MyDefaultHandler.characters()  李四
MyDefaultHandler.endElement()  name
MyDefaultHandler.characters()  
        
MyDefaultHandler.startElement()  gender
MyDefaultHandler.characters()  女
MyDefaultHandler.endElement()  gender
MyDefaultHandler.characters()  
        
MyDefaultHandler.startElement()  phone
MyDefaultHandler.characters()  13511112222
MyDefaultHandler.endElement()  phone
MyDefaultHandler.characters()  
        
MyDefaultHandler.startElement()  email
MyDefaultHandler.characters()  lisi@qq.com
MyDefaultHandler.endElement()  email
MyDefaultHandler.characters()  
        
MyDefaultHandler.startElement()  address
MyDefaultHandler.characters()  广州越秀
MyDefaultHandler.endElement()  address
MyDefaultHandler.characters()  
    
MyDefaultHandler.endElement()  contact
MyDefaultHandler.characters()  
    
MyDefaultHandler.startElement()  student
MyDefaultHandler.characters()   
    
MyDefaultHandler.endElement()  student
MyDefaultHandler.characters()  

MyDefaultHandler.endElement()  contact-list
MyDefaultHandler.endDocument()

案例:

package sax;

import java.io.File;

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;

import com.sun.org.apache.xerces.internal.xni.QName;

/**
 * 案例:以文本的原格式读取内容到内存
 */
public class Demo2 {
    public static void main(String[] args) throws Exception {
        //1.创建SAXParser对象
        SAXParser parser = SAXParserFactory.newInstance().newSAXParser();

        //2.调用parse方法
        /*
         * 参数一:xml文档
         * 参数二:DefaultHandler
         * 
         */
        MyDefaultHandler2 handler = new MyDefaultHandler2();
        parser.parse(new File("./src/contact.xml"), handler);
        String content = handler.getContent();
        System.out.println(content);

    }
}

/**
 * SAX处理程序
 */
class MyDefaultHandler2 extends DefaultHandler {
    private StringBuffer sb = new StringBuffer();

    public String getContent() {
        return sb.toString();
    }

    /**
     * 开始标签调用
     * @param qName:表示开始标签的签名
     * @param attributes:表示开始标签内包含的属性列表
     */
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        sb.append("<" + qName);
        //判断是否有属性
        if (attributes != null) {
            for (int i = 0; i < attributes.getLength(); i++) {
                String attrName = attributes.getQName(i);
                String attrValue = attributes.getValue(i);
                sb.append(" " + attrName + "=\"" + attrValue + "\"");
            }
        }
        sb.append(">");
    }

    /**
     * 结束标签调用
     * 
     */
    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        sb.append("</" + qName);
    }

    /**
     * 读到文本内容的时候调用
     * @param ch:表示xml的所有的文本内容
     * @param start:表示当前文本内容的开始位置
     * @param length:表示当前文本内容的长度
     */
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        String content = new String(ch, start, length);
        sb.append(content);
    }

}