XML(2)

写出内容到xml文档

    XMLWriter writer = new XMLWriter(OutputStream, OutputForamt)
    wirter.write(Document);
package gz.itcast.a_dom4j_write;

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

import org.dom4j.Document;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
/** * 讨论写出内容到xml文档的细节 * @author APPle * */
public class Demo2 {

    /** * @param args */
    public static void main(String[] args) throws Exception{
        Document doc = new SAXReader().read(new File("./src/contact.xml"));
        //指定文件输出的位置
        FileOutputStream out = new FileOutputStream("e:/contact.xml");
        /** * 1.指定写出的格式 */
        OutputFormat format = OutputFormat.createCompactFormat(); //紧凑的格式.去除空格换行.项目上线的时候
        //OutputFormat format = OutputFormat.createPrettyPrint(); //漂亮的格式.有空格和换行.开发调试的时候
        /** * 2.指定生成的xml文档的编码 * 同时影响了xml文档保存时的编码 和 xml文档声明的encoding的编码(xml解析时的编码) * 结论: 使用该方法生成的xml文档避免中文乱码问题。 */
        format.setEncoding("utf-8");


        //1.创建写出对象
        XMLWriter writer = new XMLWriter(out,format);

        //2.写出对象
        writer.write(doc);
        //3.关闭流
        writer.close();
    }

}

修改xml文档的API

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

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

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

/** * 修改xml内容 * 增加:文档,标签 ,属性 * 修改:属性值,文本 * 删除:标签,属性 * @author APPle * */
public class Demo3 {

    /** * 增加:文档,标签 ,属性 */
    @Test
    public void test1() throws Exception{
        /** * 1.创建文档 */
        Document doc = DocumentHelper.createDocument();
        /** * 2.增加标签 */
        Element rootElem = doc.addElement("contactList");
        //doc.addElement("contactList");
        Element contactElem = rootElem.addElement("contact");
        contactElem.addElement("name");
        /** * 3.增加属性 */
        contactElem.addAttribute("id", "001");
        contactElem.addAttribute("name", "eric");

        //把修改后的Document对象写出到xml文档中
        FileOutputStream out = new FileOutputStream("e:/contact.xml");
        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding("utf-8");
        XMLWriter writer = new XMLWriter(out,format);
        writer.write(doc);
        writer.close();
    }

    /** * 修改:属性值,文本 * @throws Exception */
    @Test
    public void test2() throws Exception{
        Document doc = new SAXReader().read(new File("./src/contact.xml"));

        /** * 方案一: 修改属性值 1.得到标签对象 2.得到属性对象 3.修改属性值 */
        //1.1 得到标签对象
        /* Element contactElem = doc.getRootElement().element("contact"); //1.2 得到属性对象 Attribute idAttr = contactElem.attribute("id"); //1.3 修改属性值 idAttr.setValue("003"); */
        /** * 方案二: 修改属性值 */
        //1.1 得到标签对象
        /* Element contactElem = doc.getRootElement().element("contact"); //1.2 通过增加同名属性的方法,修改属性值 contactElem.addAttribute("id", "004"); */

        /** * 修改文本 1.得到标签对象 2.修改文本 */
        Element nameElem = doc.getRootElement().
            element("contact").element("name");
        nameElem.setText("李四");



        FileOutputStream out = new FileOutputStream("e:/contact.xml");
        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding("utf-8");
        XMLWriter writer = new XMLWriter(out,format);
        writer.write(doc);
        writer.close();
    }


    /** * 删除:标签,属性 * @throws Exception */
    @Test
    public void test3() throws Exception{
        Document doc = new SAXReader().read(new File("./src/contact.xml"));

        /** * 1.删除标签 1.1 得到标签对象 1.2 删除标签对象 */
        // 1.1 得到标签对象
        /* Element ageElem = doc.getRootElement().element("contact") .element("age"); //1.2 删除标签对象 ageElem.detach(); //ageElem.getParent().remove(ageElem); */
        /** * 2.删除属性 2.1得到属性对象 2.2 删除属性 */
        //2.1得到属性对象
        //得到第二个contact标签
        Element contactElem = (Element)doc.getRootElement().
            elements().get(1);
        //2.2 得到属性对象
        Attribute idAttr = contactElem.attribute("id");
        //2.3 删除属性
        idAttr.detach();
        //idAttr.getParent().remove(idAttr);

        FileOutputStream out = new FileOutputStream("e:/contact.xml");
        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding("utf-8");
        XMLWriter writer = new XMLWriter(out,format);
        writer.write(doc);
        writer.close();
    }
}

xPath

引入

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

xPath作用

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

在dom4j中如何使用xPath技术

            1)导入xPath支持jar包 。  jaxen-1.1-beta-6.jar
            2)使用xpath方法
                    List<Node>  selectNodes("xpath表达式");   查询多个节点对象
                    Node       selectSingleNode("xpath表达式");  查询一个节点对象

xPath语法

            /      绝对路径      表示从xml的根位置开始或子元素(一个层次结构)
            //     相对路径      表示不分任何层次结构的选择元素。
            *      通配符        表示匹配所有元素
            []     条件          表示选择什么条件下的元素
            @      属性          表示选择属性节点
            and    关系          表示条件的与关系(等价于&&)
            text() 文本          表示选择文本内容
      3.5 案例
            用户登录功能:
                用户输入用户名和密码 -> 到“数据库”查询是否有对应的用户 -> 
                    有: 则表示登录成功
                    没有: 则表示登录失败

            用xml当做数据库
                    user.xml   用来存储用户的数据
package gz.itcast.b_xpath;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;

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

/** * xpath案例: 模拟用户登录效果 * @author APPle * */
public class Demo3 {

    public static void main(String[] args)throws Exception{
        //1.获取用户输入的用户名和密码
        BufferedReader br = 
                new BufferedReader(new InputStreamReader(System.in));

        System.out.println("请输入用户名:");
        String name = br.readLine();

        System.out.println("请输入密码:");
        String password = br.readLine();

        //2.到“数据库”中查询是否有对应的用户
        //对应的用户: 在user.xml文件中找到一个
           //name属性值为‘用户输入’,且password属性值为‘用户输入’的user标签
        Document doc = new SAXReader().read(new File("./src/user.xml"));
        Element userElem = (Element)doc.selectSingleNode("//user[@name='" +name +"' and @password='"+password+"']");

        if(userElem!=null){
            //登录成功
            System.out.println("登录成功");
        }else{
            //登录失败
            System.out.println("登录失败");
        }
    }

}

SAX解析

回顾DOM解析

            DOM解析原理:一次性把xml文档加载进内存,然后在内存中构建Document树。
                            对内存要求比较要。   
                    缺点: 不适合读取大容量的xml文件,容易导致内存溢出。

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

SAX解析工具

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

核心的API:
        SAXParser类: 用于读取和解析xml文件对象
            parse(File f, DefaultHandler dh)方法: 解析xml文件

            参数一: File:表示 读取的xml文件。
            参数二: DefaultHandler: SAX事件处理程序。使用DefaultHandler的子类

        例如:{
                1.创建SAXParser对象  
                     SAXParser parser=SAXParserFactory.newInstance().newSAXParser();
                2.调用parse方法
                    parser.parse(new File("./src/contact.xml"), new MyDefaultHandler());
            }                   
[一个类继承 class 类名(extends DefaultHandler)  在调用时创建传进去

DefaultHandler类的API:
        void startDocument() :  在读到文档开始时调用
        void endDocument() :在读到文档结束时调用
        void startElement(String uri, String localName, String qName, Attributes attributes):
            读到开始标签时调用   
                Attributes API:
                    int getLength() :获得长度
                    String getQName(int index) :通过索引获得属性名称  
                    String getValue(int index) :通过索引获得属性的值
                    String getValue(String qName) :通过属性名称获得属性的值

        void endElement(String uri, String localName, String qName)   :读到结束标签时调用
        void characters(char[] ch, int start, int length)  : 读到文本内容时调用
package gz.itcast.c_sax;

import java.io.File;

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

/** * 第一个SAX读取xml文件程序 * @author APPle * */
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());
    }

}



package gz.itcast.c_sax;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/** * SAX处理程序(如何解析xml文档) * @author APPle * */
public 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);
    }

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

    /** * 读到文本内容的时调用 * @param ch: 表示当前读完的所有文本内容 * @param start: 表示当前文本内容的开始位置 * @param length: 表示当前文本内容的长度 * char[]( 张三 20) 100 * 98 2 */ 
    @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()");
    }

}

练习题

把xml文档信息封装到对象中

类:
    public class Contact {
            private String id;
            private String name;
            private String age;
            private String phone;
            private String email;
            private String qq;
    }
XML文件:
    <?xml version="1.0" encoding="utf-8"?>
    <?xml-stylesheet type="text/css" href="03.contact.css"?>
    <contactList>
        <contact id="001">
            <name>张三</name>
            <age>20</age>
            <phone>134222223333</phone>
            <email>[email protected]</email>
            <qq>432221111</qq>
        </contact>
        <contact id="003">
            <name>lisi</name>
            <age>20</age>
            <phone>134222225555</phone>
            <email>[email protected]</email>
            <qq>432222222</qq>
        </contact>
    </contactList>
package gz.itcast.c_sax;

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

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

/** * 使用sax解析把 xml文档封装成对象 * @author APPle * */
public class Demo3 {

    public static void main(String[] args)throws Exception {
        SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
        MyDefaultHandler3 handler = new MyDefaultHandler3();
        parser.parse(new File("./src/contact.xml"), handler);
        List<Contact> list = handler.getList();
        for (Contact contact : list) {
            System.out.println(contact);
        }
    }
}


package gz.itcast.c_sax;

import java.util.ArrayList;
import java.util.List;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/** * SAX处理程序 * @author APPle * */
public class MyDefaultHandler3 extends DefaultHandler {
    //存储所有联系人对象
    private List<Contact> list = new ArrayList<Contact>();

    public List<Contact> getList(){
        return list;
    }
    //保存一个联系人信息
    private Contact contact;
    /** * 思路: * 1)创建Contact对象 * 2)把每个contact标签内容存入到Contact对象 * 3)把Contact对象放入List中 */
    //用于临时存储当前读到的标签名
    private String curTag;

    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {
        curTag = qName;
        //读取到contact的开始标签创建Contact对象
        if("contact".equals(qName)){
            contact = new Contact();

            //设置id值
            contact.setId(attributes.getValue("id"));
        }
    }

    @Override
    public void characters(char[] ch, int start, int length)
            throws SAXException {
        //当前文本内容
        String content = new String(ch,start,length);

        if("name".equals(curTag)){
            contact.setName(content);
        }

        if("age".equals(curTag)){
            contact.setAge(content);
        }

        if("phone".equals(curTag)){
            contact.setPhone(content);
        }

        if("email".equals(curTag)){
            contact.setEmail(content);
        }

        if("qq".equals(curTag)){
            contact.setQq(content);
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        //设置空时为了避免空格换行设置到对象的属性中
        curTag = null;
        //读到contact的结束标签放入List中
        if("contact".equals(qName)){
            list.add(contact);
        }
    }
}

DOM与SAX的区别

DOM SAX
原理: 一次性加载xml文档,不适合大容量的文件读取 原理: 加载一点,读取一点,处理一点。适合大容量文件的读取
DOM解析可以任意进行增删改查 SAX解析只能读取
DOM解析任意读取任何位置的数据,甚至往回读 SAX解析只能从上往下,按顺序读取,不能往回读
DOM解析面向对象的编程方法(Node,Element,Attribute),Java开发者编码比较简单。 SAX解析基于事件的编程方法。java开发编码相对复杂。

你可能感兴趣的:(XML(2))