初识XML

XML也是用来存储传输数据的一种可扩展标记语言

XML(eXtensible Markup Language的缩写),意为可扩展的标记语言。与HTML相似,XML是一种显示数据的标记语言,它能使数据通过网络无障碍地进行传输,并显示在用户的浏览器上。XML是一套定义语义标记的规则,这些标记将文档分成许多部件并对这些部件加以标识。它也是元标记语言,即定义了用于定义其他与特定领域有关的、语义的、结构化的标记语言的句法语言。

唔。。。感觉跟JSON差不多,但是区别还是挺大的,比如我要存储两所或者更多所学校的信息,用JSON储存就比较麻烦,用XML就比较方便,xml代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<chinaschool>
    
    <school name="超神学院">
        <headmaster>狗剩</headmaster>   <!--校长是狗剩-->
        <address>永恒虚空</address>            <!--学校在永恒虚空-->
        <years>1000年</years>                    <!--学校由1000年历史了-->
    </school>
    
    <school name="装逼学院">
        <headmaster>翠兰</headmaster>
        <address>兰尼斯达威尔逊卡吉尼亚</address>
        <years>9999年</years>
    </school>

</chinaschool>

这段代码里有两所学院,分别是超神学院和装逼学院,XML的数据是树形结构的,代码里有一个根节点,根节点里有一些节点,一些节点里又有一些节点。
SAX
嗯。。。长得像一颗倒着得树。

<?xml version="1.0" encoding="UTF-8"?>表示这是一个XML标记语言,解析器看到这句话就知道,哦,这是一个XML标记语言,然后对下面的代码开始解析。version属性是版本号,版本号现在最新得就是1.0,然后encoding属性是编码,使用国际通用编码UTF-8。

<chinaschool></chinaschool>
XML由若干个节点组成,一个节点以<节点名>开始,</节点名>结束,结束标签比开始标签多了一个/。

<school name="超神学院">
可以在开始标签中添加属性,格式就是name="超神学院" id=1属性之间用空格隔开

<headmaster>狗剩</headmaster>
节点中可以嵌套字符串也可以嵌套子节点(所以在节点中的空白和回车也会被认为是字符串
school节点就是chinaschool的子节点

如何解析XML?

解析XML的方法有四种,分别是:DOM、SAX、JDOM、DOM4J
这里我用SAX来进行解析,用SAX需要额外创建一个Handler类,继承DefaultHandler类

SAXParserTest.java

package cc.jethro.saxParser;

import java.io.IOException;

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

import org.xml.sax.SAXException;

public class SAXParserTest {
    
    public static void main(String[] args) {
        //新建一个SAXParserFactory对象
        SAXParserFactory factory = SAXParserFactory.newInstance();
        try {
            //用工厂对象new一个SAXParse对象
            SAXParser school = factory.newSAXParser();
            //运行解析方法,传入一个xml文件,以及一个XMLHandler对象,自己创建,继承DefaultHandler类
            //会抛出一个IO异常,将异常剪切到下面,保持代码工整
            //这里我把school.xml放在了项目的根目录,放在了其他地方需要输入完整的路径
            school.parse("school.xml", new XMLHandler());
        } catch (ParserConfigurationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SAXException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

XMLHandler.java

package cc.jethro.saxParser;

import javax.jws.WebParam;
import javax.jws.soap.InitParam;
import javax.lang.model.element.Element;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
 * 本类会从上至下的解析节点。
 * @author jethro
 *
 */
public class XMLHandler extends DefaultHandler{
    /**
     * 当程序开始解析XML根节点开始标签时会运行这一个方法
     */
    @Override
    public void startDocument() throws SAXException {
        // TODO Auto-generated method stub
        super.startDocument();//当开始解析的时候,打印“解析开始”
        System.out.println("-----解析开始-----");
    }
    /**
     * 当程序开始解析XML根节点结束标签时会运行这一个方法
     */
    @Override
    public void endDocument() throws SAXException {
        // TODO Auto-generated method stub
        super.endDocument();
        System.out.println("-----解析结束------");//当开始解析的时候,打印“解析开始”
    }
    /**
     * 解析节点的开始标签的时候运行这个方法
     * @param qName 节点名
     * @param attributes 存放节点的信息,可以用来get节点的属性
     */
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        // TODO Auto-generated method stub
        super.startElement(uri, localName, qName, attributes);
        
        //判断当前节点是否是school节点
        if(qName.equals("school")){
            //如果是就打印“开始解析某个学校”
            System.out.println("========开始解析某个学校=======");
            //读取并打印school节点的name属性,也就是学校的名字拉
            System.out.println("校名:"+attributes.getValue("name"));
        }else if(qName.equals("headmaster")){   //判断当前节点是否是school节点
            //打印"校长:"然后接着程序会运行 characters 方法,characters方法会打印校长节点的text字符串
            System.out.print("校长:");
        }else if(qName.equals("address")){
            System.out.print("地址:");
        }else if(qName.equals("years")){
            System.out.print("校龄:");
        }
    }    
    /**
     * 解析节点的结束标签的时候运行这个方法
     * @param qName 节点名
     * @param attributes 存放节点的信息,可以用来get节点的属性
     */
    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        // TODO Auto-generated method stub
        super.endElement(uri, localName, qName);
    }
    /**
     * 节点的开始标签结束后运行此方法,此方法会读取当前节点中的字符串子节点
     * @param ch XML中的所有字符串都在这里,打印他就可以得到XML文档的内容
     * @param start 当前节点的字符串开始位置
     * @param length 当前节点字符串的长度
     */
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        // TODO Auto-generated method stub
        super.characters(ch, start, length);
        //将当前子节点字符串读取到String对象
        String tmp = new String(ch,start,length);
        //还记得节点中的空格和回车都会算作子节点字符串,所以要对这个子节点进行筛选
        if(!tmp.trim().equals("")){      //运行trim方法清理字符串中的空格和回车,如果清理后是空字符串,就不打印,否则进行打印
            //打印字符串
            System.out.println(tmp);
        }
    }
}

运行一下,得到以下结果:
结果

添加新评论