菜鸟一只,最近一直在慕课网上学习java,结合自己的理解并且在网上查找相关讲解,将自己的学习笔记整理出来与大家分享一下,菜鸟就能不断进步。
1 XML文件简介
XML是可扩展标记语言(Extensible Markup Language)的缩写,其中Markup是关键部分,可以创建内容,然后使用限定标记标记它,从而使每个单词、短语或块成为可识别、可分类的信息。
1.1 XML文件是以树形结构存储
<根元素名称>
<子元素名 属性 = "属性值"
…… ……>
<子元素名>****</子元素名>
…… …… ……
<子元素名>****</子元素名>
</子元素名>
…… …… ……
</根元素名称>
PS:
1. 相同元素名的不同元素属性和其子元素可以不同.
2. XML 文件由内容和标记组成,将内容文本包含到元素中,即分别在文本的首末两端添加开始和结束标记<元素名>文本
1.2 在XML文件首行声明–可选部分
它将文件识别为 XML 文件,有助于工具和人类识别XML,这个声明必须出现在文件的开头
<?xml version = "1.0" encoding = 编码格式(eg."UTF-8")?>
1.3 用途
解决不同程序、不同平台、不同操作系统的通讯问题。
2 JAVA中解析XML文件
在java中有四种解析XML文件的方式:DOM,SAX,DOM4J,JDOM。前两个是官方提供的,不需要额外的jar包
以student.xml文件为例:
<?xml version = "1.0" encoding = "UTF-8" ?>
<school>
<student id = "0001">
<name>王明</name>
<sex>男</sex>
<major>计算机科学与技术</major>
</student>
<student id = "0002">
<name>李红</name>
<sex>女</sex>
<major>计算数学</major>
</student>
</school>
2.1 应用DOM方式解析XML
2.1.1 准备工作
创建一个DocumentBuilderFactory对象:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
创建一个DocumentBuilder对象:
DocumentBuilder db = dbf.newDocumentBuilder()
通过DocumentBuilder对象的parse方法加载xml文件到当前项目中:
Document document = db.parse("*****.xml");
说明:
1. newInstance()是DocumentBuilderFactory的静态方法,用于获取DocumentBuilderFactory的一个实例;
2. newDocumentBuilder()用于获取DocumentBuilder的对象;
3. parse()方法是org.w3c.dom中的方法;
4. 注意捕捉异常。
2.1.2 获取元素(元素)的属性名和属性值
Document中的getElementByTagName(“student”)方法根据给定的元素名来获取该元素组成的集合,返回为NodeList类型(stuList):
NodeList stuList = document.getElementByTagName("student");
通过item(int index)方法遍历stuList中的每个元素,返回Node类型:
Node stu = stuList.item(i);
获得了每个元素后就可以获得进一步得到每个元素的属性,通过getAttributes()方法获得一个所有属性和属性值的映射NamedNodeMap:
NamedNodeMap attr = stu.getAtrributes();
同样的,属性映射attr通过item(index)方法获得每个属性,显然将返回一个Node类型:
Node attrnode = atts.item(i);
这时我们要进一步得到每个属性(attrnode)的名字和属性值,分别通过getNodeName()和getNodeValue()方法。同时,注意到元素student除了有属性外,还有许多子元素(name,major等),如何获取呢?
通过getChildNodes()方法获取子元素的集合,和前面类似,返回值也是NodeList类型。每个元素中包含的文本也被看作是该元素的子元素,获取每个元素包含的文本可以通过getNodeValue()方法获取。
备注:
1. 常用的元素类型:
类型 | NodeType | Named Constant | nodeName/nodeValue |
---|---|---|---|
Element | 1 | ELEMENT_NODE | element name / null |
Attr | 2 | ATTRIBUTE_NODE | attribute name / attribute value |
Text | 3 | TEXT_NODE | text / node text |
由标记包含的元素(school、student、name等)的类型就是Element,元素的属性就是Attr类型,元素中的文本内容和xml元素间的空格等就是Text类型
2. 因为空格也会被看作是元素,所以获取我们所需要的元素时,应注意避免获取空格,我们可以通过判断得到的元素类型来避免空格:
node.getNodeType() == Node.ELEMENT_NODE;
3. 获取每个元素中的文本也可通过getTextContext()方法,它返回的是包括子元素的所有文本。
4. 可通过getFirstChild()方法获取元素的第一个子元素,可以和getTextContext()搭配使用。
2.1.3 代码示例如下:
public class DomTest {
public static void main(String[] args) {
//创建一个DocumentBuilderFactory对象
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
//创建一个DocumentBuilder对象
DocumentBuilder db = dbf.newDocumentBuilder();
//通过DocumentBuilder对象的parse方法加载books.xml到当前项目下
Document document = db.parse("students.xml");
//根据节点名获取所有该节点的集合
NodeList stuList = document.getElementsByTagName("student");
System.out.println("一共有"+stuList.getLength()+"个学生");
//遍历每一个student节点
for(int i = 0;i < stuList.getLength();++ i){
//通过item(i)方法获取一个节点
Node book = stuList.item(i);
NamedNodeMap atts =book.getAttributes();
System.out.println("第"+(i+1)+"个学生共有"+atts.getLength()+"个属性");
for(int j = 0; j < atts.getLength(); ++ j){
Node node = atts.item(j);
System.out.println(
node.getNodeName()+","+node.getNodeValue());
}
NodeList childNodes = book.getChildNodes();
System.out.println("共有"+childNodes.getLength()+"个子节点");
for(int j = 0;j < childNodes.getLength();++ j)
{
Node node = childNodes.item(j);
//区分出text类型的node以及element类型中的node
if(node.getNodeType() == Node.ELEMENT_NODE){
//获取element类型节点的节点名的三种方式
System.out.println( node.getNodeName()+","+
node.getChildNodes().item(0).getNodeValue());
System.out.println(node.getNodeName()+","+
node.getFirstChild().getNodeValue());
System.out.println(node.getNodeName()+","+
node.getFirstChild().getTextContent());
}
}
}
} catch (ParserConfigurationException e) {
e.printStackTrace();
}catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.2 应用SAX方式解析XML
SAX方式是通过DefaultHanlder逐行扫描XML文件内容,文档的读入过程也就是SAX的解析过程。
2.2.1 准备工作
使用SAXParserFactory的静态方法newInstance()获取 SAXParserFactory实例:
SAXParserFactory factory = SAXParserFactory.newInstance();
通过factory.newSAXParser()方法获取SAXParser实例:
SAXParser parser = factory.newSAXParser();
用parse()方法解析XML文件:
parser.parse("student.xml",DefaultHandler handler)
上一步中,我们需要一个DefaultHandler参数:
创建一个类继承DefaultHandler,重写其中的一些方法,进行业务处理并创建这个类的实例传给parse()方法
public class SAXParserHandler extends DefaultHandler
2.2.2 获取元素文本
在handler类中会重写如下几个方法:
startDocument()方法,文件解析开始使调用;
endDocument()方法,文件解析结束时调用;
startElement(String uri, String localName, String qName, Attributes attrs)方法
变量名 表示 qName 当前访问的元素名 attrs 元素的属性 每访问一个元素都会调用该方法,如上表所述,qName可以得到 当前访问元素名,attrs保存了该元素的属性集合,可以通过getQName(index)和getQValue(index)方法遍历属性。
endElement(String uri, String localName, String qName)方法,当某个元素访问结束后调用;
characters(char[] ch, int start, int length)方法中,ch变量保存了整个xml文件内容,而start和length表示了当前访问元素文本的开始位置和长度,从而可将每个元素的文本内容保存到字符串中(根据程序执行结果,调用该方法是根据每个元素中文本和子元素的顺序调用的,如下代码的顺序:aaa ->root ->bbb)
<root> <a>aaa</a> root <b>bbb</b> <root>
但是需注意空格也将被看作子元素,所以应将全是空格的字符串筛选掉,可用trim()方法删除字符串左右两边的空格,然后判断剩余字符串是否是空(equals(“”))。
备注:
1.注意以上方法将抛出异常
不断学习不断总结^_^。。。