(一)什么是XML?
- XML 指可扩展标记语言(EXtensible Markup Language)
- XML 是一种标记语言,很类似 HTML
- XML 的设计宗旨是传输数据,而非显示数据
- XML 标签没有被预定义。您需要自行定义标签。
- XML 被设计为具有自我描述性。
- XML 是 W3C 的推荐标准
(二)XML的作用
- 不同应用程序之间通信、传输信息(订票程序和支付程序)
- 不同系统间的通信(例:Windows系统和IOS系统)
- 不同平台间的数据共享(手机端和PC端)
- 不同APP之间的通信,不同的平台间的通信,不同平台间的数据共享
(三)DOM解析XML文件的准备工作
1.创建一个books.xml文件
<?xml version="1.0" encoding="UTF-8"?> <!-- xml文件的申明,包括版本号以及编码字符集 -->
<bookstore> <!-- 根节点 -->
<book id="1"> <!-- 子节点 -->
<name>冰与火之歌</name>
<author>乔治马丁</author>
<year>2014</year>
<price>88</price>
</book>
<book id="2">
<name>安徒生童话</name>
<year>2004</year>
<price>77</price>
<language>English</language>
</book>
</bookstore>
2.创建一个java项目,并将books.xml文件拷贝到项目中
3.使用DocumentBuilderFactory对象,DocumentBuilder对象以及Document对象完成对books.xml文件的加载(一个典型的工厂设计模式),切记Document对象应该导入org.w3c.dom下的包
// 创建一个DocumentBuilderFactory对象
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
//创建一个DucumentBuilder对象
DocumentBuilder db = dbf.newDocumentBuilder();
//通过DocumentBuilder对象的parse方法加载books.xml文件到当前项目下
Document document = db.parse("books.xml");
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
(四)使用DOM解析XML文件的属性名和属性值
1.获取所有的book节点的集合,并遍历每一个book节点
//通过节点名获取book节点的集合
NodeList bookList = document.getElementsByTagName("book");
System.out.println("一共有" + bookList.getLength() + "本书");
//遍历每一个book节点
for(int i = 0;i < bookList.getLength(); i++){
//通过循环遍历book节点的集合,并在其中对每个节点进行操作
}
2.获取book节点中所有属性的集合,并遍历每一个book属性,获取其属性名以及属性值(前提是不知道属性个数以及属性名)
//遍历每一个book节点
for(int i = 0;i < bookList.getLength(); i++){
System.out.println("======下面开始遍历第" + (i + 1) + "本书的内容======");
//通过item(i)方法获取每一个book节点,nodeList的索引值从0开始
Node book = bookList.item(i);
//获取book节点的所有属性集合
NamedNodeMap attrs = book.getAttributes();
System.out.println("第" + (i + 1) + "本书共有" + attrs.getLength() + "个属性");
//遍历book的属性
for(int j = 0; j < attrs.getLength(); j++){
//通过item(index)方法获取book节点的某一属性
Node attr = attrs.item(j);
//获取属性名
System.out.print("属性名:" + attr.getNodeName());
//获取属性值
System.out.println("--属性值:" + attr.getNodeValue());
}
System.out.println("======结束遍历第" + (i + 1) + "本书的内容======");
}
运行结果
3.已经知道book节点有且只有1个id属性时,可以将book节点进行强制类型转换,转换成element类型
//遍历每一个book节点
for(int i = 0;i < bookList.getLength(); i++){
System.out.println("======下面开始遍历第" + (i + 1) + "本书的内容======");
//将book节点强制转换为element类型
Element book = (Element)bookList.item(i);
//通过getAttribute("id")方法获取属性值
String attrValue = book.getAttribute("id");
System.out.println("id属性的属性值为:" + attrValue);
System.out.println("======结束遍历第" + (i + 1) + "本书的内容======");
}
运行结果
(五)使用DOM解析XML文件的节点名和节点值
1.常用的节点类型
节点类型 | NodeType | nodeName 的返回值 | nodeValue 的返回值 |
---|---|---|---|
Element | 1 | element name | null |
Attr | 2 | 属性名称 | 属性值 |
Text | 3 | #text | 节点内容 |
2.解析book节点的子节点,首先我们先试着获取book节点下的子节点的数量:
//解析book节点的子节点
NodeList childNodes = book.getChildNodes();
//获取子节点的数量(即childNodes的长度)
System.out.println("第" + (i +1) + "本书共有" +
childNodes.getLength() + "个子节点");
运行结果:
我们可以看出,结果和我们预料的并不一致,这是为什么呢?
其实,代码并没有出错,book节点的子节点的确有9个;
我们可以回看之前节点类型的表格,我们会发现除了我们需要的Element类型的节点外,
book节点下还有5个由空格和换行符组成的Text类型的节点
3.测试输出book节点下的每个子节点
//测试输出每个子节点的名称
for(int k=0;k<childNodes.getLength();k++){
System.out.println(childNodes.item(k).getNodeName());
}
运行结果:
我们可以发现,的确是多出来了5个Text类型的子节点;
所以,我们在获取book节点的子节点时,需要选择输出Element类型的子节点,而不是把所有的子节点全部输出
4.区分Text类型的节点和Element类型的子节点,并输出其节点名和节点值
//区分text类型的node以及element类型的node
if(childNodes.item(k).getNodeType() == Node.ELEMENT_NODE){
//获取了element类型节点的节点名
System.out.print(childNodes.item(k).getNodeName()+ " ");
System.out.println(childNodes.item(k).getNodeValue());
}
运行结果:
可以看出,子节点的节点名是正常输出了,但是节点值却都是null
原因就是Element类型节点的节点值都是null
5.获取Element类型的节点名和节点值
-
System.out.println("--节点值是:" + childNodes.item(k).getFirstChild().getNodeValue());
-
System.out.println("--节点值是:" + childNodes.item(k).getTextContent());
以上两种方法都能获取Element类型节点的节点值,而二者的区别在于:
getFirstChild().getNodeValue()方法是先获取该节点下的第一个子节点,然后输出其节点值;
getTextContent()方法是获取该节点下所有的节点值(包括子节点的节点值)