Java解析xml文件
在Java程序中读取xml文件的过程也称为“解析xml文件”;
解析的目的:
- 获取 节点名和节点值
- 获取 属性名、属性值。
四中解析方式:
- DOM
- SAX
- DOM4J
- JDOM
(其中DOM、SAX是官方提供的解析方式,不需要额外的jar包,后两种则需要)
例:DOM方式解析books.xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<bookstore>
<book type="fiction" id="1">
<name>冰与火之歌</name>
<author>乔治马丁</author>
<year>2014</year>
<price>89</price>
</book>
<book id="2">
<name>安徒生童话</name>
<year>2004</year>
<price>77</price>
<language>English</language>
</book>
</bookstore>
15
1
<?xml version="1.0" encoding="UTF-8" ?>
2
<bookstore>
3
<book type="fiction" id="1">
4
<name>冰与火之歌</name>
5
<author>乔治马丁</author>
6
<year>2014</year>
7
<price>89</price>
8
</book>
9
<book id="2">
10
<name>安徒生童话</name>
11
<year>2004</year>
12
<price>77</price>
13
<language>English</language>
14
</book>
15
</bookstore>
以上是我们需要解析的xml文件,我们的目的是:通过Java获取xml文件的所有数据。
准备工作
准备工作:
- (1)创建一个DocumentBuilderFactory对象
- (2)创建一个DocumentBuilder对象
- (3)通过DocumentBuilder对象的parse(String fileName)方法解析xml文件
public class DomTest {
public static void main(String[] args) {
//(1)创建DocumentBuilderFactory对象
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
//(2)创建DocumentBuilder对象
DocumentBuilder db = dbf.newDocumentBuilder();
//(3)通过DocumentBuilder对象的parse方法加载book.xml
Document document = db.parse("books.xml");
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
19
1
public class DomTest {
2
public static void main(String[] args) {
3
//(1)创建DocumentBuilderFactory对象
4
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
5
try {
6
//(2)创建DocumentBuilder对象
7
DocumentBuilder db = dbf.newDocumentBuilder();
8
//(3)通过DocumentBuilder对象的parse方法加载book.xml
9
Document document = db.parse("books.xml");
10
11
} catch (ParserConfigurationException e) {
12
e.printStackTrace();
13
} catch (SAXException e) {
14
e.printStackTrace();
15
} catch (IOException e) {
16
e.printStackTrace();
17
}
18
}
19
}
解析xml文件属性
解析属性:
- (1)Document类来获取节点集合
- (2)遍历节点集合
- (3)通过item(i)获取节点Node
- (4)通过Node的getAttributes获取节点的属性集合
- (5)遍历属性
- (6)获取属性和属性名
public class DomTest {
public static void main(String[] args) {
//创建DocumentBuilderFactory对象
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
//创建DocumentBuilder对象
DocumentBuilder db = dbf.newDocumentBuilder();
//通过DocumentBuilder对象的parse方法加载book.xml
Document document = db.parse("books.xml");
//(1)获取所有book节点的集合
NodeList booklist = document.getElementsByTagName("book");
System.out.println("共有" + booklist.getLength() + "本书");
System.out.println("-------------------------------------");
//(2)遍历每个book节点
for (int i = 0; i < booklist.getLength(); i++) {
//(3)通过item(i)获取book节点,nodelist索引从0开始
Node book = booklist.item(i);
//(4)获取book节点的所有属性集合
NamedNodeMap attrs = book.getAttributes();
//获取属性的数量
System.out.println("第" + (i + 1) + "本书有" + attrs.getLength() + "个属性");
System.out.print("分别是:");
//(5)遍历book的属性
for (int j = 0; j < attrs.getLength(); j++) {
//(6)获取属性
Node att = attrs.item(j);
//(6)获取属性的名称
String attName = att.getNodeName();
System.out.print(attName + ", ");
}
System.out.println();
System.out.println("-------------------------------------");
}
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
47
1
public class DomTest {
2
public static void main(String[] args) {
3
//创建DocumentBuilderFactory对象
4
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
5
try {
6
//创建DocumentBuilder对象
7
DocumentBuilder db = dbf.newDocumentBuilder();
8
//通过DocumentBuilder对象的parse方法加载book.xml
9
Document document = db.parse("books.xml");
10
11
//(1)获取所有book节点的集合
12
NodeList booklist = document.getElementsByTagName("book");
13
System.out.println("共有" + booklist.getLength() + "本书");
14
System.out.println("-------------------------------------");
15
16
//(2)遍历每个book节点
17
for (int i = 0; i < booklist.getLength(); i++) {
18
//(3)通过item(i)获取book节点,nodelist索引从0开始
19
Node book = booklist.item(i);
20
//(4)获取book节点的所有属性集合
21
NamedNodeMap attrs = book.getAttributes();
22
23
//获取属性的数量
24
System.out.println("第" + (i + 1) + "本书有" + attrs.getLength() + "个属性");
25
System.out.print("分别是:");
26
27
//(5)遍历book的属性
28
for (int j = 0; j < attrs.getLength(); j++) {
29
//(6)获取属性
30
Node att = attrs.item(j);
31
//(6)获取属性的名称
32
String attName = att.getNodeName();
33
System.out.print(attName + ", ");
34
}
35
System.out.println();
36
System.out.println("-------------------------------------");
37
}
38
39
} catch (ParserConfigurationException e) {
40
e.printStackTrace();
41
} catch (SAXException e) {
42
e.printStackTrace();
43
} catch (IOException e) {
44
e.printStackTrace();
45
}
46
}
47
}
打印结果:
共有2本书
-------------------------------------
第1本书有2个属性
分别是:id, type,
-------------------------------------
第2本书有1个属性
分别是:id,
-------------------------------------
8
1
共有2本书
2
-------------------------------------
3
第1本书有2个属性
4
分别是:id, type,
5
-------------------------------------
6
第2本书有1个属性
7
分别是:id,
8
-------------------------------------
解析xml文件属性的子节点
解析子节点:
- (1)使用getChildNodes()获取子节点集合
- (2)遍历子节点
- (3)获取子节点
- (4)输出子节点名称和内容
public class DomTest {
public static void main(String[] args) {
//创建DocumentBuilderFactory对象
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
//创建DocumentBuilder对象
DocumentBuilder db = dbf.newDocumentBuilder();
//通过DocumentBuilder对象的parse方法加载book.xml
Document document = db.parse("books.xml");
//获取所有book节点的集合
NodeList booklist = document.getElementsByTagName("book");
System.out.println("共有" + booklist.getLength() + "本书");
System.out.println("-------------------------------------");
//遍历每个book节点
for (int i = 0; i < booklist.getLength(); i++) {
//通过item(i)获取book节点,nodelist索引从0开始
Node book = booklist.item(i);
//获取book节点的所有属性集合
NamedNodeMap attrs = book.getAttributes();
//获取属性的数量
System.out.println("第" + (i + 1) + "本书有" + attrs.getLength() + "个属性");
System.out.print("分别是:");
//遍历book的属性
for (int j = 0; j < attrs.getLength(); j++) {
//获取属性
Node att = attrs.item(j);
//获取属性的名称
String attName = att.getNodeName();
System.out.print(attName + ", ");
}
System.out.println();
System.out.println("子节点:");
//(1)解析book节点的子节点
NodeList bookChildNodes = book.getChildNodes();
//(2)遍历bookChildNodes获取每个子节点
for (int k = 0; k < bookChildNodes.getLength(); k++) {
//(3)获取子节点
Node bookChild = bookChildNodes.item(k);
//注(a)
//区分text类型的node以及element类型的node(子节点含我们不需要的文本型,所以我们要筛选)
if (bookChild.getNodeType() == Node.ELEMENT_NODE) {
//注(b)
//(4)获取和输出节点名和节点内容
//方法1:
System.out.println(bookChild.getNodeName() + ", " + bookChild.getTextContent());
//方法2:
//System.out.println(bookChild.getNodeName() + ", " + bookChild.getFirstChild().getNodeValue());
}
}
System.out.println("-------------------------------------");
}
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
x
1
public class DomTest {
2
public static void main(String[] args) {
3
//创建DocumentBuilderFactory对象
4
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
5
try {
6
//创建DocumentBuilder对象
7
DocumentBuilder db = dbf.newDocumentBuilder();
8
//通过DocumentBuilder对象的parse方法加载book.xml
9
Document document = db.parse("books.xml");
10
11
//获取所有book节点的集合
12
NodeList booklist = document.getElementsByTagName("book");
13
System.out.println("共有" + booklist.getLength() + "本书");
14
System.out.println("-------------------------------------");
15
16
//遍历每个book节点
17
for (int i = 0; i < booklist.getLength(); i++) {
18
//通过item(i)获取book节点,nodelist索引从0开始
19
Node book = booklist.item(i);
20
//获取book节点的所有属性集合
21
NamedNodeMap attrs = book.getAttributes();
22
23
//获取属性的数量
24
System.out.println("第" + (i + 1) + "本书有" + attrs.getLength() + "个属性");
25
System.out.print("分别是:");
26
27
//遍历book的属性
28
for (int j = 0; j < attrs.getLength(); j++) {
29
//获取属性
30
Node att = attrs.item(j);
31
//获取属性的名称
32
String attName = att.getNodeName();
33
System.out.print(attName + ", ");
34
}
35
System.out.println();
36
37
System.out.println("子节点:");
38
//(1)解析book节点的子节点
39
NodeList bookChildNodes = book.getChildNodes();
40
//(2)遍历bookChildNodes获取每个子节点
41
for (int k = 0; k < bookChildNodes.getLength(); k++) {
42
//(3)获取子节点
43
Node bookChild = bookChildNodes.item(k);
44
45
//注(a)
46
//区分text类型的node以及element类型的node(子节点含我们不需要的文本型,所以我们要筛选)
47
if (bookChild.getNodeType() == Node.ELEMENT_NODE) {
48
//注(b)
49
//(4)获取和输出节点名和节点内容
50
//方法1:
51
System.out.println(bookChild.getNodeName() + ", " + bookChild.getTextContent());
52
//方法2:
53
//System.out.println(bookChild.getNodeName() + ", " + bookChild.getFirstChild().getNodeValue());
54
}
55
56
}
57
System.out.println("-------------------------------------");
58
}
59
} catch (ParserConfigurationException e) {
60
e.printStackTrace();
61
} catch (SAXException e) {
62
e.printStackTrace();
63
} catch (IOException e) {
64
e.printStackTrace();
65
}
66
}
67
}
打印结果:
共有2本书
-------------------------------------
第1本书有2个属性
分别是:id, type,
子节点:
name, test冰与火之歌
author, 乔治马丁
year, 2014
price, 89
-------------------------------------
第2本书有1个属性
分别是:id,
子节点:
name, 安徒生童话
year, 2004
price, 77
language, English
-------------------------------------
18
1
共有2本书
2
-------------------------------------
3
第1本书有2个属性
4
分别是:id, type,
5
子节点:
6
name, test冰与火之歌
7
author, 乔治马丁
8
year, 2014
9
price, 89
10
-------------------------------------
11
第2本书有1个属性
12
分别是:id,
13
子节点:
14
name, 安徒生童话
15
year, 2004
16
price, 77
17
language, English
18
-------------------------------------
注(a):解析时是把空白也算为文本型的子节点,如下看似只有4个子节点,算上空白会输出9个子节点。
<bookstroe>
<book id="1">
<name>冰与火之歌</name>
<author>乔治马丁</author>
<year>2014</year>
<price>89</price>
</book>
</bookstroe
8
1
<bookstroe>
2
<book id="1">
3
<name>冰与火之歌</name>
4
<author>乔治马丁</author>
5
<year>2014</year>
6
<price>89</price>
7
</book>
8
</bookstroe
如上图所示,黄色和橙色也都算成了text类型的节点,这是我们不需要的,往往需要判断筛选。
<bookstroe>
<book id="1">
<name>冰与火之歌</name>
<author>乔治马丁</author>
<year>2014</year>
<price>89</price>
</book>
</bookstroe>
1
<bookstroe>
2
<book id="1">
3
<name>冰与火之歌</name>
4
<author>乔治马丁</author>
5
<year>2014</year>
6
<price>89</price>
7
</book>
8
</bookstroe>
注(b):假如此时我们想要获取<name>中的“冰与火之歌”
1)获取子节点的内容的时候,不是使用getNodeValue(),如上图,该方法只会返回null;我们要使用getTextContent()来获取两个标签中间的内容;
2)另外,也可以使用获取这个子节点的子节点,之前有提到,text也被视为子节点,这里的“冰与火之歌”被视为<name>的子节点,所以获取子节点的子节点以后,再使用getNodeValue()才有意义,即先获取book的子节点<name>,再获取name的子节点;
3)这两种方法的区别:
假如有<name><a>test</a>冰与火之歌</name>
getTextContext() --> test冰与火之歌(获取name下所有的文本并拼接起来)
getFirstChild().getNodeValue() --> null(获得子节点并输出其值)
如何在Java中保留xml数据的结构?
创建一个Book类,包含属性name、author、year、price等,在解析该xml的同时,就对该对象中的属性进行赋值。
当然,多个对象的时候,自然还需要存到集合中去。