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的数据是树形结构的,代码里有一个根节点,根节点里有一些节点,一些节点里又有一些节点。
嗯。。。长得像一颗倒着得树。
<?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);
}
}
}
运行一下,得到以下结果: