一、XML是什么?
XML是指可扩展标记语言(eXtensible MarkupLanguage),它是一种标记语言。它被设计的宗旨是描述数据(XML),而非显示数据(HTML)
应用场景:1、描述数据 2、作为配置文件存在
二、XML语法
在编写XML文档时,需要先使用文档声明来声明XML文档。且必须出现在文档的第一行。
XML声明之前不能有注释 不允许第一行写注释(不同于java)
通常第一句:
<?xml version="1.0" encoding="UTF-8"?>
三、XML的DOM解析
DOM解析原理
XML解析器一次性把整个XML文档加载进内存,然后在内存中构建一颗Document的对象树,通过Document对象,得到树上的节点对象,通过节点对象访问(操作)到XML文档的内容。
给出一个xml文件做为栗子:
<?xml version="1.0" encoding="UTF-8"?>
<students>
<student id="0229" name="柯林" sex="女" birthday="2000/02/29">
<hobby>刷b站</hobby>
<hobby>音乐</hobby>
<hobby>bigbang</hobby>
<hobby>吃鸡</hobby>
<introduce>
喜欢迷幻,后摇,黑泡的短发女孩
</introduce>
</student>
<student id="0518" name="东永裴" sex="男" birthday="1988/05/18">
<hobby>跳舞</hobby>
<hobby>音乐</hobby>
<hobby>bigbang</hobby>
<hobby>种花</hobby>
<introduce>
宇宙大明星太阳,暖男,笑眼,喜欢狗狗,克里斯马无敌,柯林的爱豆
</introduce>
</student>
<student id="0818" name="权志龙" sex="男" birthday="1988/08/18">
<hobby>跳舞</hobby>
<hobby>音乐</hobby>
<hobby>bigbang</hobby>
<hobby>画画</hobby>
<introduce>
宇宙大明星龙,权艺术家,小狮子,柯林的爱豆
</introduce>
</student>
<student id="0406" name="某幻君" sex="男" birthday="1997/04/06">
<hobby>rap</hobby>
<hobby>游戏视频</hobby>
<hobby>给指甲盖打水印</hobby>
<hobby>剪视频噢</hobby>
<introduce>
柯林现实中最想和他做朋友,幽默,头大,脸黑,但是帅呢哈哈,rap无敌的马鸽鸽
</introduce>
</student>
</students>
从上面的xml文件可以看出 描述的是student,可以给出一个student实体类,以便后续方便使用
package stu.crayue.about_xml.model;
import java.util.ArrayList;
import java.util.List;
/**
* @author Crayue
* @version 2019年11月10日 下午4:46:49
*/
public class StudentInfo {
private String id;
private String name;
private String sex;
private String birthday;
private String introduce;
private List<String> hobbies;
public StudentInfo() {
hobbies=new ArrayList<String>();
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
public String getIntroduce() {
return introduce;
}
public void setIntroduce(String introduce) {
this.introduce = introduce;
}
public List<String> getHobbies() {
return hobbies;
}
public void addHobby(String hobby) {/此处不需要set hobbies的值,重新写一个方法来添加爱好
if(hobbies.contains(hobby)) {
return;
}
hobbies.add(hobby);
}
@Override
public String toString() {/拼接字符串时,常用stringbuffer
StringBuffer res= new StringBuffer();
res.append(id).append(" ")
.append(sex).append(" ")
.append(name).append(" ")
.append(birthday).append("简介:")
.append(introduce).append("\n");
for(String hobby:hobbies) {
res.append('\t').append(hobby).append('\n');
}
return res.toString();
}
}
现在开始写XML文件的DOM解析吧~
private static final DocumentBuilderFactory dbf;
private static DocumentBuilder db;
static {
dbf=DocumentBuilderFactory.newInstance(); /建立DocumentBuilderFactor,用于获得DocumentBuilder对象:
try {
db=dbf.newDocumentBuilder(); /建立DocumentBuidler
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
}
上面的程序有一个静态代码块;
Java静态代码块中的代码会在类加载JVM时运行,且只被执行一次,也就是说这些代码不需要实例化类就能够被调用。静态块常用来执行类属性的初始化
需要调用parse(InputStream)方法才能打开要处理的XML文档,得到一个Document类的对象;
public static Document getDocument(InputStream is) {
Document document=null; /建立Document对象,获取树的入口:
try {
document=db.parse(is);
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return document;
}
public static Document getDocument (String xmlPath) {
InputStream is = XMLParser.class.getResourceAsStream(xmlPath);
if(is==null) {
return null;
}
return getDocument(is);
}
做一个XML解析的工具类,文档里面的内容是未知的,具体的实现需要通过使用此工具的用户完成。因此需要一个抽象的处理方法。
public abstract void dealElement(Element element,int index); /抽象方法,需要通过用户实现
public void parseTag(Document document,String tagName) { /获取document中的名为tagname的元素名列表
NodeList nodeList=document.getElementsByTagName(tagName);
for(int index=0;index<nodeList.getLength();index++) {
Element ele = (Element) nodeList.item(index);
dealElement(ele,index);
}
}
public void parseTag(Element element,String tagName) { /获取element元素里面名为tagname的元素列表
NodeList nodeList=element.getElementsByTagName(tagName);
for(int index=0;index<nodeList.getLength();index++) {
Element ele = (Element) nodeList.item(index);
dealElement(ele,index);
}
}
因此完成了我们的XML解析工具类:源码如下
package stu.crayue.util;
/**
* @author Crayue
* @version 2019年11月10日 下午5:47:17
*/
import java.io.IOException;
import java.io.InputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public abstract class XMLParser {
private static final DocumentBuilderFactory dbf;
private static DocumentBuilder db;
static {
dbf=DocumentBuilderFactory.newInstance();
try {
db=dbf.newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
}
public XMLParser() {
}
public static Document getDocument (String xmlPath) {
InputStream is = XMLParser.class.getResourceAsStream(xmlPath);
if(is==null) {
return null;
}
return getDocument(is);
}
public static Document getDocument(InputStream is) {
Document document=null;
try {
document=db.parse(is);
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return document;
}
public abstract void dealElement(Element element,int index);
public void parseTag(Document document,String tagName) {
NodeList nodeList=document.getElementsByTagName(tagName);
for(int index=0;index<nodeList.getLength();index++) {
Element ele = (Element) nodeList.item(index);
dealElement(ele,index);
}
}
public void parseTag(Element element,String tagName) {
NodeList nodeList=element.getElementsByTagName(tagName);
for(int index=0;index<nodeList.getLength();index++) {
Element ele = (Element) nodeList.item(index);
dealElement(ele,index);
}
}
}
我们可以将这个工具类压缩成一个jar文件,复制并且构建路径到需要用到的工程里,简化XML文档解析的操作过程,节约编码时间,将XML解析工具化。
下面给出一个测试代码:
package stu.crayue.about_xml.test;
import org.w3c.dom.Element;
import stu.crayue.about_xml.model.StudentInfo;
import stu.crayue.util.XMLParser;
/**
* @author Crayue
* @version 2019年11月10日 下午6:10:14
*/
public class Test {
public static void main(String[] args) {
new XMLParser() {
@Override
public void dealElement(Element element,int index) {
StudentInfo stu = new StudentInfo();
String id=element.getAttribute("id");
stu.setId(id);
String name = element.getAttribute("name");
stu.setName(name);
String sex = element.getAttribute("sex");
stu.setSex(sex);
String birthday = element.getAttribute("birtdhday");
stu.setBirthday(birthday);
new XMLParser() {
@Override
public void dealElement(Element element,int index) {
String hobbyString = element.getTextContent();
stu.addHobby(hobbyString);
}
}.parseTag(element, "hobby");/获取element元素里面名为hobby的元素列表
new XMLParser() {
@Override
public void dealElement(Element element,int index) {
String introduce=element.getTextContent().trim();
stu.setIntroduce(introduce);
}
}.parseTag(element, "introduce");/获取element元素里面名为introduce的元素列表
System.out.println(stu); /输出students内容
}
}.parseTag(XMLParser.getDocument("/student.xml"), "student"); /获取document中的名为student的元素名列表
}
}
输出结果截图: