SAX解析和xml约束

一、SAX解析

1.特点

SAX解析:读一点,取一点,节省内存空间。一旦遇到开始标签触发之后,及时从内存中将开始节点从内存中释放点。

2.三要素

/**
 * SAX解析:针对事件编程
 * 三要素:
 * 1)事件源
 * 2)事件监听器
 *          遇到文档开始  startDocument(......)
 *          遇到开始标签  startElement(......)
 *          遇到文本内容  characters(......)
 *          遇到结束标签   endElement(......)
 *          遇到文档结束    endDocument(......)
 * 3)注册事件监听器:基于事件处理程序
 * DefaultHandler
 *    开发步骤:
 *              1)创建SAX解析器对象
 *              2)解析当前xml文件
 *              3)基于事件处理进行判断(开始标签/结束标签/文本内容)
 */

3.DOM解析和SAX解析的区别

原理:前者,读一点,取一点,节省内存空间。一旦遇到开始标签触发之后,及时从内存中将开始节点从内存中释放点。
          后者,一次性加载整个xml文件,如果xml文件结构层次深,可能会导致OOM异常,浪费空间。
使用过程区别:前者,只能去读(需求:使用SAX解析,将xx.xml文件原封不动打印)
                        后者:不仅能读,还能写,并且能往返读。
编程思想:前者,面向事件编程方式---->Java开发者难理解。
                  后者,面向对象编程思想,编程方式--->Java开发者好理解。

二、SAX解析的使用

1.使用SAX解析xml文件

xml文件为:

<?xml version="1.0" encoding="utf-8" ?>
<!--使用xml文件来标签联系人,姓名 性别 电话-->
<contact id="001">
        <name>张三</name>
        <phone>18292886805</phone>
        <gender>男</gender>
</contact>
package com.xunpu.sax;
/**
 * SAX解析:
 * 读一点,取一点。节省空间,一旦遇到开始标签触发之后,及时从内存中将开始节点内存中释放。
 */

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/**
 * 编写监听器:自定义类  继续自基类(DefaultHandler)
 */
public class MyDefault1 extends DefaultHandler {
    /**
     *
     * @param uri
     * @param localName
     * @param qName  开始标签名称<contact id="" name="">
     * @param attributes  属性列表
     * @throws SAXException
     */
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        System.out.println("MyDefaultHandler1.startDociment:"+qName);
    }

    /**遇到文本内容
     * @param ch
     * @param start
     * @param length
     * @throws SAXException
     */
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        //遇到文本:每次读取到的是当前文本的实际内容
        String content=new String(ch,start,length);
        System.out.println("文档内容:"+content);
    }

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

    /**
     *
     * @throws SAXException
     */
    @Override
    public void endDocument() throws SAXException {
        System.out.println("MyDefault endDocument:森当解析结束了");
    }
}
package com.xunpu.sax;

import org.dom4j.Document;
import org.dom4j.io.SAXReader;
import org.xml.sax.SAXException;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.IOException;


public class SAXDemo {
    public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
        //1)创建一个SAX解析器对象  SAXParse--抽象类 使用它的工厂类创建对象。
        SAXParser parser=SAXParserFactory.newInstance().newSAXParser();
        //2)读取xml文件
        //事件源:解析contact.xml
        parser.parse(SAXDemo.class.getClassLoader().getResourceAsStream("contact.xml"),
                new MyDefault1());


    }
}

注意:xml文件首行的拼写一定不能出现错误,否则就会出现"Exception in thread "main" org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 21; 应该有伪属性名。"类错误。

结果:

解析过程:

<contact id="001"> ------>startElement(qname,Attribute)  开始元素的触发事件
<name>张三------->张三:characters(ch,start,length)  文本触发事件
</name></contact>--------->endElement(qname,....)  结束标签触发的事件

2.使用SAX解析将xml文件原封不动输出

步骤:

1)创建解析器
2)读取xml文件
3)定义一个基于事件的处理程序(一个类 extends DefaultHandler)
    使用字符串缓冲区对象StringBuffer
    定义一个方法-->可以将字符缓冲区的内容-->String类型。

package com.xunpu.sax;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
//基于事件的处理程序
public class MyDefault2 extends DefaultHandler {
    private StringBuffer sb=new StringBuffer();

    //定义一个成员方法
    public String getContent(){
        return sb.toString();
    }
    //遇到开始标签  qName:标签名称
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        sb.append("<"+qName);
        //遍历属性列表  getLength():返回属性列表的长度
        for(int i=0;i<attributes.getLength();i++){
            //获取到每一个属性对象
            String attributesName=attributes.getQName(i);
            String attrValue=attributes.getValue(i);
            //双引号需要转义
            sb.append(" "+attributesName+"=\""+attrValue);
        }
        sb.append(">");
    }

    //遇到文本内容
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
       String content=new String(ch,start,length);
       sb.append(content);
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        sb.append("</"+qName+">");
    }
}
package com.xunpu.sax;

import org.dom4j.io.SAXReader;
import org.xml.sax.SAXException;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.IOException;

public class SAXDemo2 {
    public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
        SAXParser parser=SAXParserFactory.newInstance().newSAXParser();
        MyDefault2 handler2=new MyDefault2();
        parser.parse(SAXDemo2.class.getClassLoader().getResourceAsStream("contact.xml"),handler2);

        String content=handler2.getContent();
        System.out.println(content);
    }
}

结果:

三、xml文件的约束(简介)

1.dtd约束

<!--内部方式-->
<!DOCTYPE note[
    <!ELEMENT note (to,from,heading,body)>
    <!ELEMENT to (#PCDATA)>
    <!ELEMENT from (#PCDATA)>
    <!ELEMENT heading (#PCDATA)>
    <!ELEMENT body (#PCDATA)>
        ]>
<note>
    <to>Tove</to>
    <from>Jani</from>
    <heading>Reminder</heading>
    <body>Don't forget me this weekend!</body>
</note>
note.xml文件
<!--外部方式   note是根节点 约束为note.dtd文件-->
<!DOCTYPE note SYSTEM "note.dtd">
<note>
    <to>Tove</to>
    <from>Jani</from>
    <heading>Reminder</heading>
    <body>Don't forget me this weekend!</body>
</note>

note.dtd文件:
        <!ELEMENT note (to,from,heading,body)>
        <!ELEMENT to (#PCDATA)>
        <!ELEMENT from (#PCDATA)>
        <!ELEMENT heading (#PCDATA)>
        <!ELEMENT body (#PCDATA)>

外部文件一些约束的声明:
<!--声明属性:
<!ATTLIST 元素名称 属性名称 属性类型 默认值>
CDATA:普通字符串
<!ATTLIST body id CDATA #REQUIRED>  :约束body的内容是普通字符串而且必须指定id属性。
 <!ATTLIST body id CDATA #FIXED "002">   :约束body的内容是普通字符串而且必须id属性值必须是"002",否则值无效。

-->

2.schema约束

名称空间的定义格式:  xmlns:名称空间="别名"(URL)

如:

<bite:书架 xmlns:bite="http://www.bite.cn"
           xmlns:xsi="htttp://wwwww.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://www.bite.cn book.xsd">

在第一行中,bite是名称空间,"http://www.bite.cn"是别名。
schemaLocation中指代的文件是用来约束书架的!!

使用名称空间:1)使用名称空间在xml中定义标签,必须指定别名。如:“http://www.bite.cn”
2)关联当前别名地址:schemaLocation="别名1 地址1 别名2 地址2....."。

定义后的名称空间,指定标签名称格式:名称空间:标签名称(如bite:书架)----->书架标签被book.xsd文件所约束。

xxx.xsd:schema约束文件
w3c组织定义的格式:xs:约束xml文件定义的标签。

Schema约束(类型丰富) 是基于 XML 的 DTD 替代者。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值