JavaWeb 4 XML

4 XML

1 XML入门
        1.1 引入
        HTML: 负责网页的结构    
        CSS: 负责网页的样式(美观)
        Javascript: 负责在浏览器端与用户进行交互。

负责静态的网页制作的语言
            
        HTML语言特点:
                1)由标签组成。 <title> <p> <hr/> <br/>
                2)语法结构松散的    <p></p>   <p>  <P>
                    大小写不区分
                    结束标签和开始标签不一定匹配
<html>
    <head>
        <title>this is title</title>
    </head>
    <body>
        <p>html标签</p>
        <P>html标签</P>
        <abc>abc标签</abc>  自定义标签
    </body>
</html>

这种自定义标签可以把他们叫做xml标签。

2 HTML和XML的区别    
                HTML                                     
名称:       HyperText Markup Languae(超文本标记语言)    
标签:     标签是w3c组成指定,固定的,约100来个                                                                 
作用:      负责网页的结构

XML
名称 Extend Markup Languge(可扩展标签语言)
标签 标签由开发者自己制定的(要按照一定的语法定义)
作用 1)描述带关系的数据(作为软件的配置文件) 包含与被包含的关系
properties文件
 key-value
name=eric
password=123456

<user>
    <name>eric</name>
    <password>123456</password>
</user>
场景:
    tomcat
    struts Hibernate spring (三大框架)
2)作为数据的载体(存储数据,小型的“数据库”)

3 XML语法
    xml文件以xml后缀名结尾。
    xml文件需要使用xml解析器去解析。浏览器内置了xml解析器。    
3.1 标签
            语法: <student></student>  开始标签  标签体内容  结束标签
                1)<student/> 或 <student></student> 空标签。没有标签体内容
                2)xml标签名称区分大小写。
                3)xml标签一定要正确配对。
                4)xml标签名中间不能使用空格
                5)xml标签名不能以数字开头
                6)注意: 在一个xml文档中,有且仅有一个根标签
3.2 属性
            语法: <Student name="eric">student</Student>
            注意:
                    1)属性值必须以引号包含,不能省略,也不能单双引号混用!!!
                    2)一个标签内可以有多个属性,但不能出现重复的属性名!!!
3.3 注释
                    语言: <!--  xml注释 -->
练习:
                通讯录系统
                联系人数据:编号 (唯一的) 姓名   年龄   电话 邮箱  QQ

要求:
                contact.xml
                    1)设计一个xml文件,用于存储联系人数据
                    2)这个xml文件可以多个联系人。
3.4 文档声明
        语法: <?xml version="1.0" encoding="utf-8"?>

version: xml的版本号
        encoding: 解析xml文件时查询的码表(解码过程时查询的码表)

注意:
                1)如果在ecplise工具中开发xml文件,保存xml文件时自动按照文档声明的encoding来保存文件。
                2)如果用记事本工具修改xml文件,注意保存xml文件按照文档声明的encoding的码表来保存。
3.5 转义字符
        在xml中内置了一些特殊字符,这些特殊字符不能直接被浏览器原样输出。
        如果希望把这些特殊字符按照原样输出到浏览器,对这些特殊字符进行转义。转义之后的字符就叫转义字节。

特殊字符  转义字符
                 <         &lt;
                 >         &gt;
                 "         &quot;
                &         &amp;
                空格      &nsbp;
3.6 CDATA块
        作用: 可以让一些需要进行包含特殊字符的内容统一进行原样输出。

3.7 处理指令
            作用: 告诉xml解析如果解析xml文档
            
            案例: <?xml-stylesheet type="text/css" href="1.css"?> 告诉xml解析该xml文档引用了哪个css文件

需要提前xml内容可以使用xml-stylesheet指令指令

4 XML解析    
        4.1 引入
        xml文件除了给开发者看,更多的情况使用程序读取xml文件的内容。这叫做xml解析
4.2 XML解析方式(原理不同)
        DOM解析
        SAX解析
4.3 XML解析工具
        DOM解析原理:
            1)JAXP (oracle-Sun公司官方)
            2)JDOM工具(非官方)
            3)Dom4J工具(非官方)
            三大框架(默认读取xml的工具就是Dom4j)

SAX解析原理:
            1)Sax解析工具(oracle-sun公司官方)
4.4 什么是DOM解析
            DOM解析原理:xml解析器一次性把整个xml文档加载进内存,然后在内存中构建一颗Document的对象树,
            通过Document对象,得到树上的节点对象,通过节点对象访问(操作)到xml文档的内容。
4.5 Dom4j工具
            非官方,不在jdk中。

使用步骤:
                1)导入dom4j的核心包。 dom4j-1.6.1.jar
                2)编写Dom4j读取xml文件代码\

    public static void main(String[] args) {
        try {
            //1.创建一个xml解析器对象
            SAXReader reader = new SAXReader();
            //2.读取xml文档,返回Document对象
            Document doc = reader.read(new File("./src/contact.xml"));

            System.out.println(doc);
        } catch (DocumentException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }

    }

4.6 Dom4j读取xml文件
        节点:
            Iterator  Element.nodeIterator();  //获取当前标签节点下的所有子节点

标签:
            Element  Document.getRootElement();  //获取xml文档的根标签        
            Element   ELement.element("标签名") //指定名称的第一个子标签
            Iterator<Element> Element.elementIterator("标签名");// 指定名称的所有子标签
            List<Element>     Element.elements(); //获取所有子标签
                        
        属性:
            String   Element.attributeValue("属性名") //获取指定名称的属性值
            Attribute    Element.attribute("属性名");//获取指定名称的属性对象    
            Attribute.getName()  //获取属性名称
            Attibute.getValue()  //获取属性值
            List<Attribute>     Element.attributes();  //获取所有属性对象
            Iterator<Attribute>        Element.attibuteIterator(); //获取所有属性对象

文本:
            Element.getText();  //获取当前标签的文本
            Element.elementText("标签名") //获取当前标签的指定名称的子标签的文本内容

读取XML文件

JavaWeb 4 XML

public class Demo5 {

    //把xml文档信息封装到对象中
    public static void main(String[] args) throws Exception {

        List<Contact> list = new ArrayList<Contact>();

        //读取xml,封装对象
        SAXReader reader = new SAXReader();
        Document doc = reader.read(new File("./src/contact.xml"));
        //读取contact标签
        Iterator<Element> it = doc.getRootElement().elementIterator("contact");
        while(it.hasNext()){
            Element elem = it.next();
            //创建Contact
            Contact contact = new Contact();
            contact.setId(elem.attributeValue("id"));
            contact.setName(elem.elementText("name"));
            contact.setAge(elem.elementText("age"));
            contact.setPhone(elem.elementText("phone"));
            contact.setEmail(elem.elementText("email"));
            contact.setQq(elem.elementText("qq"));
            list.add(contact);
        }

        for (Contact contact : list) {
            System.out.println(contact);
        }

    }

}

5 Dom4j修改xml文档
5.1 写出内容到xml文档
                XMLWriter writer = new XMLWriter(OutputStream, OutputForamt)
                wirter.write(Document);

//写出内容到xml文档
    public static void main(String[] args) throws Exception {
        Document doc = new SAXReader().read(new File("./src/AndroidManifest.xml"));
        //指定文件输出的位置
        FileOutputStream out = new FileOutputStream("C:/Users/Administrator/Desktop/contact.xml");
        //C:\Users\Administrator\Desktop\ 改写成C:/Users/Administrator/Desktop/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();
    }

5.2 修改xml文档的API
            增加:
                    DocumentHelper.createDocument()  增加文档
                    addElement("名称")  增加标签
                    addAttribute("名称",“值”)  增加属性

//增加:文档,标签 ,属性
    public static void main(String[] args) throws Exception {
        //1.创建文档
        Document doc = DocumentHelper.createDocument();
        //2.增加标签
        Element rootElem = doc.addElement("contactList");
        Element contactElem = rootElem.addElement("contact");
        contactElem.addElement("name");
        //3.增加属性
        contactElem.addAttribute("id", "003");
        contactElem.addAttribute("name", "demo7");

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

修改:
                    Attribute.setValue("值")  修改属性值
                    Element.addAtribute("同名的属性名","值")  修改同名的属性值
                    Element.setText("内容")  修改文本内容

//修改:属性值,文本
    public static void main(String[] args) throws Exception {
        Document doc = new SAXReader().read(new File("C:/Users/Administrator/Desktop/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 contactElem1 = doc.getRootElement().element("contact");
        //1.2 通过增加同名属性的方法,修改属性值
        contactElem.addAttribute("id", "004");

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

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

删除
                    Element.detach();  删除标签  
                    Attribute.detach();  删除属性

//删除:标签,属性
    public static void main(String[] args) throws Exception {
        Document doc = new SAXReader().read(new File("C:/Users/Administrator/Desktop/contact.xml"));
        //1.删除标签     1.1 得到标签对象  1.2 删除标签对象
        Element ageElem = doc.getRootElement().element("contact").element("age");
        //1.2 删除标签对象
        ageElem.detach();
        //ageElem.getParent().remove(ageElem);

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

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

一个小练习

需求
     * 1.使用dom4j的api来生成以下的xml文件
    <Students>
    <Student id="1">
        <name>张三</name>
        <gender>男</gender>
        <grade>计算机1班</grade>
        <address>广州天河</address>
    </Student>
    <Student id="2">
        <name>李四</name>
        <gender>女</gender>
        <grade>计算机2班</grade>
        <address>广州越秀</address>
    </Student>
    </Students>

2.修改id为2的学生的姓名,改为“王丽”

3.删除id为2的学生

public static void main(String[] args) throws Exception {
        //1.内存创建xml文档
        Document doc = DocumentHelper.createDocument();
        //2.写入内容
        Element rootElem = doc.addElement("Students");

        //2.1 增加标签
        Element studentElem1 = rootElem.addElement("Student");
        //2.2 增加属性
        studentElem1.addAttribute("id", "1");
        //2.3 增加标签,同时设置文本
        studentElem1.addElement("name").setText("张三");
        studentElem1.addElement("gender").setText("男");
        studentElem1.addElement("grade").setText("计算机1班");
        studentElem1.addElement("address").setText("广州天河");

        //2.1 增加标签
        Element studentElem2 = rootElem.addElement("Student");
        //2.2 增加属性
        studentElem2.addAttribute("id", "2");
        //2.3 增加标签,同时设置文本
        studentElem2.addElement("name").setText("李四");
        studentElem2.addElement("gender").setText("女");
        studentElem2.addElement("grade").setText("计算机2班");
        studentElem2.addElement("address").setText("广州越秀");

        //3.内容写出到xml文件
        save(doc);

        //修改id为2的学生姓名
        //1.查询到id为2的学生
        Document doc1 = new SAXReader().read(new File("C:/Users/Administrator/Desktop/test/student.xml"));
        //1.1 找到所有的Student标签
        Iterator<Element> it = doc1.getRootElement().elementIterator("Student");
        while(it.hasNext()){
            Element stuElem = it.next();
            //1.2 查询id为id的学生标签
            if(stuElem.attributeValue("id").equals("2")){
                stuElem.element("name").setText("王丽");
                break;
            }
        }

        save(doc1);

        //删除id为2的学生
        Document doc2 = new SAXReader().read(new File("C:/Users/Administrator/Desktop/test/student.xml"));
        //1.1 找到所有的Student标签
        Iterator<Element> it2 = doc2.getRootElement().elementIterator("Student");
        while(it2.hasNext()){
            Element stuElem = it2.next();
            //1.2 查询id为id的学生标签
            if(stuElem.attributeValue("id").equals("2")){
                //1.3 删除该学生标签
                stuElem.detach();
                break;
            }
        }

        save(doc2);

    }

    private static void save(Document  doc) throws Exception{
        //3.1 输出位置
        FileOutputStream out = new FileOutputStream("C:/Users/Administrator/Desktop/test/student.xml");
        //3.2 指定格式
        OutputFormat format = OutputFormat.createPrettyPrint();
        // 设置编码
        format.setEncoding("utf-8");
        XMLWriter writer = new XMLWriter(out,format);
        //3.3 写出内容
        writer.write(doc);
        //3.4关闭资源
        writer.close();
    }

6 xPath技术  
            3.1 引入
            问题:当使用dom4j查询比较深的层次结构的节点(标签,属性,文本),比较麻烦!!!
            3.2 xPath作用
                主要是用于快速获取所需的节点对象。

public static void main(String[] args) throws Exception {

        //1.内存创建xml文档
        Document doc = DocumentHelper.createDocument();
        //2.写入内容
        Element rootElem = doc.addElement("Students");

        //2.1 增加标签
        Element studentElem1 = rootElem.addElement("Student");
        //2.2 增加属性
        studentElem1.addAttribute("id", "1");
        //2.3 增加标签,同时设置文本
        studentElem1.addElement("name").setText("张三");
        studentElem1.addElement("gender").setText("男");
        studentElem1.addElement("grade").setText("计算机1班");
        studentElem1.addElement("address").setText("广州天河");

        //2.1 增加标签
        Element studentElem2 = rootElem.addElement("Student");
        //2.2 增加属性
        studentElem2.addAttribute("id", "2");
        //2.3 增加标签,同时设置文本
        studentElem2.addElement("name").setText("李四");
        studentElem2.addElement("gender").setText("女");
        studentElem2.addElement("grade").setText("计算机2班");
        studentElem2.addElement("address").setText("广州越秀");

        //3.内容写出到xml文件
        save(doc);

        //删除除id值为2的学生标签  使用xpath
        Document doc1 = new SAXReader().read(new File("C:/Users/Administrator/Desktop/test/student.xml"));
        Element stuElem = (Element)doc1.selectSingleNode("//Student[@id='2']");
        stuElem.detach();

        save(doc1);
    }

    private static void save(Document  doc) throws Exception{
        //3.1 输出位置
        FileOutputStream out = new FileOutputStream("C:/Users/Administrator/Desktop/test/student.xml");
        //3.2 指定格式
        OutputFormat format = OutputFormat.createPrettyPrint();
        // 设置编码
        format.setEncoding("utf-8");
        XMLWriter writer = new XMLWriter(out,format);
        //3.3 写出内容
        writer.write(doc);
        //3.4关闭资源
        writer.close();
    }

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

3.4 xPath语法
                /      绝对路径      表示从xml的根位置开始或子元素(一个层次结构)
                //     相对路径       表示不分任何层次结构的选择元素。
                *      通配符         表示匹配所有元素
                []      条件           表示选择什么条件下的元素
                @     属性            表示选择属性节点
                and     关系          表示条件的与关系(等价于&&)
                text()    文本           表示选择文本内容

//学习xPath表达式语法
    public static void main(String[] args) throws Exception {

        Document doc = new SAXReader().read(new File("./src/contact.xml"));

        String xpath = "";

        /**
         * 1.      /      绝对路径      表示从xml的根位置开始或子元素(一个层次结构)
         */
        xpath = "/contactList";
        xpath = "/contactList/contact";

        /**
         * 2. //     相对路径       表示不分任何层次结构的选择元素。
         */
        xpath = "//contact/name";
        xpath = "//name";

        /**
         * 3. *      通配符         表示匹配所有元素
         */
        xpath = "/contactList/*"; //根标签contactList下的所有子标签
        xpath = "/contactList//*";//根标签contactList下的所有标签(不分层次结构)

        /**
         * 4. []      条件           表示选择什么条件下的元素
         */
        //带有id属性的contact标签
        xpath = "//contact[@id]";
        //第二个的contact标签
        xpath = "//contact[2]";
        //选择最后一个contact标签
        xpath = "//contact[last()]";

        /**
         * 5. @     属性            表示选择属性节点
         */
        xpath = "//@id"; //选择id属性节点对象,返回的是Attribute对象
        xpath = "//contact[not(@id)]";//选择不包含id属性的contact标签节点
        xpath = "//contact[@id='002']";//选择id属性值为002的contact标签
        xpath = "//contact[@id='001' and @name='eric']";//选择id属性值为001,且name属性为eric的contact标签

        /**
         *6.  text()   表示选择文本内容
         */
        //选择name标签下的文本内容,返回Text对象
        xpath = "//name/text()";
        xpath = "//contact/name[text()='张三']";//选择姓名为张三的name标签

        List<Node> list = doc.selectNodes(xpath);
        for (Node node : list) {
            System.out.println(node.getName());
        }
    }

模拟用户登录效果

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("登录失败");
        }

    }

使用xpath技术读取一个规范的html文档

public static void main(String[] args) throws Exception {
        Document doc = new SAXReader().read(new File("./src/personList.html"));

        Element titleElem = (Element)doc.selectSingleNode("//title");
        String title = titleElem.getText();
        System.out.println(title);

        /**
         * 练习:读取联系人的所有信息
         * 按照以下格式输出:
         *          编号:001 姓名:张三 性别:男 年龄:18 地址:xxxx 电话: xxxx
         *       编号:002 姓名:李四 性别:女 年龄:20 地址:xxxx 电话: xxxx
         *       ......
         */
        //1.读取出所有tbody中的tr标签
        List<Element> list = (List<Element>)doc.selectNodes("//tbody/tr");
        //2.遍历
        for (Element elem : list) {
            //编号
            //String id = ((Element)elem.elements().get(0)).getText();
            String id = elem.selectSingleNode("td[1]").getText();
            //姓名
            String name = ((Element)elem.elements().get(1)).getText();
            //性别
            String gender = ((Element)elem.elements().get(2)).getText();
            //年龄
            String age = ((Element)elem.elements().get(3)).getText();
            //地址
            String address = ((Element)elem.elements().get(4)).getText();
            //电话
            String phone = ((Element)elem.elements().get(5)).getText();

            System.out.println("编号:"+id+"\t姓名:"+name+"\t性别:"+
                                gender+"\t年龄:"+
                                age+"\t地址:"+address+
                                "\t电话:"+phone);
        }

    }

7 SAX解析
            4.1回顾DOM解析
                DOM解析原理:一次性把xml文档加载进内存,然后在内存中构建Document树。
                                对内存要求比较要。    
                        缺点: 不适合读取大容量的xml文件,容易导致内存溢出。
                    
                SAX解析原理: 加载一点,读取一点,处理一点。对内存要求比较低。
            4.2 SAX解析工具    
                    SAX解析工具-  Sun公司提供的。内置在jdk中。org.xml.sax.*

核心的API:
                           SAXParser类: 用于读取和解析xml文件对象
                                parse(File f, DefaultHandler dh)方法: 解析xml文件
                
                        参数一: File:表示 读取的xml文件。
                        参数二: DefaultHandler: SAX事件处理程序。使用DefaultHandler的子类

DefaultHandler类的API:
                        void startDocument()  :  在读到文档开始时调用
                        void endDocument()  :在读到文档结束时调用
                        void startElement(String uri, String localName, String qName, Attributes attributes)  :读到开始标签时调用                
                        void endElement(String uri, String localName, String qName)   :读到结束标签时调用
                        void characters(char[] ch, int start, int length)  : 读到文本内容时调用

第一个例子

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());
    }

MyDefaultHandler

public class MyDefaultHandler extends  DefaultHandler{

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

    //开始标签时调用
    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        super.endElement(uri, localName, qName);
        System.out.println("MyDefaultHandler.startElement()-->"+qName);
    }

    //结束标签时调用
    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {
        super.startElement(uri, localName, qName, attributes);
        System.out.println("MyDefaultHandler.endElement()-->"+qName);
    }

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

    @Override
    public void endDocument() throws SAXException {
        super.endDocument();
        System.out.println("MyDefaultHandler.endDocument()");
    }

}

第二个例子

读取contact.xml文件,完整输出文档内容

public static void main(String[] args)throws Exception {
        //1.创建SAXParser
        SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
        //2.读取xml文件
        MyDefaultHandler2 handler = new MyDefaultHandler2();
        parser.parse(new File("./src/contact.xml"), handler);
        String content = handler.getContent();
        System.out.println(content);
    }

MyDefaultHandler2

public class MyDefaultHandler2 extends DefaultHandler {

    //存储xml文档信息
    private StringBuffer sb = new StringBuffer();

    //获取xml信息
    public String getContent(){
        return sb.toString();
    }

    // 开始标签
    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {
        super.startElement(uri, localName, qName, attributes);

        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 characters(char[] ch, int start, int length)
            throws SAXException {
        super.characters(ch, start, length);
        //得到当前读取的文本
        String content = new String(ch,start,length);
        sb.append(content);
    }

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

}

最后一个例子

使用sax解析把 xml文档封装成对象

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);
        }
    }

MyDefaultHandler3

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 startDocument() throws SAXException {
        super.startDocument();
        System.out.println("MyDefaultHandler.startDocument()");
    }

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

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

    //读到文本内容的时调用
    //ch: 表示当前读完的所有文本内容
    //start: 表示当前文本内容的开始位置
    //length: 表示当前文本内容的长度
    @Override
    public void characters(char[] ch, int start, int length)
            throws SAXException {
        super.characters(ch, start, length);
        //当前文本内容
        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 {
        super.endElement(uri, localName, qName);
        //设置空时为了避免空格换行设置到对象的属性中
        curTag = null;
        //读到contact的结束标签放入List中
        if("contact".equals(qName)){
            list.add(contact);
        }
    }

    @Override
    public void endDocument() throws SAXException {
        super.endDocument();
        System.out.println("MyDefaultHandler.endDocument()");
    }

}

DOM解析    vs   SAX解析
原理: 一次性加载xml文档,不适合大容量的文件读取
DOM解析可以任意进行增删改查
DOM解析任意读取任何位置的数据,甚至往回读
DOM解析面向对象的编程方法(Node,Element,Attribute),Java开发者编码比较简单。

SAX解析
原理: 加载一点,读取一点,处理一点。适合大容量文件的读取
SAX解析只能读取
SAX解析只能从上往下,按顺序读取,不能往回读
SAX解析基于事件的编程方法。java开发编码相对复杂。

以上所有代码见Giihub https://github.com/huanyi0723/Xml/

上一篇:跨域http头


下一篇:html相关介绍