文章524
标签277
分类67

Java基础总结之八

本文是Java面试总结中Java基础篇的第八篇


1. xml有哪些解析技术?区别是什么?

1.DOM生成和解析XML文档

为 XML 文档的已解析版本定义了一组接口, 解析器读入整个文档,然后构建一个驻留内存的树结构,然后代码就可以使用 DOM 接口来操作这个树结构

优点:整个文档树在内存中,便于操作;支持删除、修改、重新排列等多种功能;

缺点:将整个文档调入内存(包括无用的节点),浪费时间和空间;

使用场合:一旦解析了文档还需多次访问这些数据;硬件资源充足(内存、CPU)


2.SAX生成和解析XML文档

为解决DOM的问题,出现了SAX: SAX,事件驱动

当解析器发现元素开始、元素结束、文本、文档的开始或结束等时,发送事件,程序员编写响应这些事件的代码,保存数据

优点:不用事先调入整个文档,占用资源少;SAX解析器代码比DOM解析器代码小,适于Applet,下载

缺点:不是持久的;事件过后,若没保存数据,那么数据就丢了;无状态性;从事件中只能得到文本,但不知该文本属于哪个元素;

使用场合:Applet; 只需XML文档的少量内容,很少回头访问;机器内存少;

3.DOM4J生成和解析XML文档

DOM4J 是一个非常非常优秀的Java XML API,具有性能优异、功能强大和极端易用使用的特点,同时它也是一个开放源代码的软件

如今你可以看到越来越多的 Java 软件都在使用 DOM4J 来读写 XML,特别值得一提的是连 Sun 的 JAXM 也在用 DOM4J

4.JDOM生成和解析XML

为减少DOM、SAX的编码量,出现了JDOM;

优点:20-80原则,极大减少了代码量

使用场合:要实现的功能简单,如解析、创建等,但在底层,JDOM还是使用SAX(最常用)、DOM、Xanan文档


2. XML文档定义有几种形式?它们之间有何本质区别?解析XML文档有哪几种方式?

两种形式: dtd 和schema

本质区别: schema本身是xml的,可以被XML解析器解析(这也是从DTD上发展schema的根本目的)

解析XML的方式: 有DOM,SAX,STAX等

DOM: 处理大型文件时其性能下降的非常厉害, 这个问题是由DOM的树结构所造成的,这种结构占用的内存较多,而且DOM必须在解析文件之前把整个文档装入内存,适合对XML的随机访问

SAX: 不现于DOM,SAX是事件驱动型的XML解析方式. 它顺序读取XML文件,不需要一次全部装载整个文件。当遇到像文件开头,文档结束,或者标签开头与标签结束时,它会触发一个
事件,用户通过在其回调事件中写入处理代码来处理XML文件,适合对XML的顺序访问

STAX: Streaming API for XML


3. 你在项目中用到了xml技术的哪些方面?如何实现的?

答: 用到了数据存贮,信息配置两方面

在做数据交换平台时,将不能作为数据源的数据组装成XML文件,然后将XML文件压缩打包加密后通过网络传送给接收者,接收解密与解压缩后再同XML文件中还原相关信息进行处理

在做软件配置时,利用XML可以很方便的进行,软件的各种配置参数都存贮在XML文件中


4. 用jdom解析xml文件时如何解决中文问题?如何解析?

如下例子, 创建了一个xml文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

/**
* @author zk
*/
public class DomTest {

public static void main(String[] args) {
String filename = "test.xml";

try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = builder.newDocument();
Element root = document.createElement("老师");
Element wang = document.createElement("王");

wang.appendChild(document.createTextNode("我是王老师"));
root.appendChild(wang);
document.appendChild(root);

Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.transform(new DOMSource(document), new StreamResult(filename));
} catch (Exception e) {
e.printStackTrace();
}
}
}

输出的xml文件如下:

1
2
3
4
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<老师>
<王>我是王老师</王>
</老师>

5. 编程用Dom4j解析XML

如下test.xml文件在工程下的resources文件夹下:

1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8" ?>
<jdbc>
<driver name="driver">com.mysql.jdbc.Driver</driver>
<url name="url">jdbc:mysql://localhost:3306/exam</url>
<username name="username">root</username>
<password name="password">root</password>
</jdbc>

下面是使用Dom4j解析xml文件的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.util.Iterator;
import java.util.List;

/**
* @author zk
*/
public class Dom4jTest {

public static void main(String[] args) throws DocumentException {
// 创建saxReader对象
SAXReader reader = new SAXReader();

// 通过read方法读取一个文件 转换成Document对象
Document document = reader.read(new File("src/main/resources/test.xml"));

//获取根节点元素对象
Element node = document.getRootElement();
//遍历所有的元素节点
listNodes(node);
}

/**
* 遍历当前节点元素下面的所有(元素的)子节点
*
* @param node 待遍历根节点
*/
public static void listNodes(Element node) {
System.out.println("当前节点的名称: " + node.getName());
// 获取当前节点的所有属性节点
List<Attribute> list = node.attributes();

// 遍历属性节点
for (Attribute attr : list) {
System.out.println(attr.getText() + ": " + attr.getName() + " -- " + attr.getValue());
}

if (!("".equals(node.getTextTrim()))) {
System.out.println("文本内容: " + node.getText());
}

// 当前节点下面子节点迭代器
Iterator<Element> it = node.elementIterator();
// 遍历
while (it.hasNext()) {
// 获取某个子节点对象
Element e = it.next();
// 对子节点进行遍历
listNodes(e);
}
}
}

------- Output -------
当前节点的名称: jdbc
当前节点的名称: driver
driver: name -- driver
文本内容: com.mysql.jdbc.Driver
当前节点的名称: url
url: name -- url
文本内容: jdbc:mysql://localhost:3306/exam
当前节点的名称: username
username: name -- username
文本内容: root
当前节点的名称: password
password: name -- password
文本内容: root


总结:

① 获得Document对象的方式有三种:

1
2
3
4
5
6
7
8
9
10
11
>// 读取XML文件,获得document对象  
>SAXReader reader = new SAXReader();
>Document document = reader.read(new File("pom.xml"));

>// 解析XML形式的文本,得到document对象
>String text = "<test>Test</test>";
>Document document = DocumentHelper.parseText(text);

>// 主动创建document对象
>Document document = DocumentHelper.createDocument(); //创建根节点
>Element root = document.addElement("test");

② 节点对象操作的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
>// 获取文档的根节点
>Element root = document.getRootElement();

>// 取得某个节点的子节点
>Element element = node.element("四大名著");

>// 取得节点的文字
>String text = node.getText();

>// 取得某节点下所有名为“test”的子节点,并进行遍历
>List nodes = rootElm.elements("test");
>for (Iterator it = nodes.iterator(); it.hasNext(); ) {
Element elm = (Element) it.next();
// do something
>}

>// 对某节点下的所有子节点进行遍历
>for (Iterator it = root.elementIterator(); it.hasNext(); ) {
Element element = (Element) it.next();
// do something
>}

>// 在某节点下添加子节点
>Element elm = newElm.addElement("朝代");

>// 设置节点文字
>elm.setText("明朝");

>// 删除某节点: childElement是待删除的节点, parentElement是其父节点
>parentElement.remove(childElment);

>// 添加一个CDATA节点
>Element contentElm = infoElm.addElement("content");
>contentElm.addCDATA("cdata区域");

③ 节点对象的属性方法操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
>// 取得某节点下的某属性    
>Element root = document.getRootElement(); // 属性名name
>Attribute attribute = root.attribute("id");

>// 取得属性的文字
>String text = attribute.getText();

>// 删除某属性
>Attribute attribute = root.attribute("size");
>root.remove(attribute);

>// 遍历某节点的所有属性
>Element root = document.getRootElement();
>for(Iterator it = root.attributeIterator(); it.hasNext(); ){
Attribute attribute = (Attribute) it.next();
String text=attribute.getText();
System.out.println(text);
>}

>// 设置某节点的属性和文字
>newMemberElm.addAttribute("name", "sitinspring");

>// 设置属性的文字
>Attribute attribute = root.attribute("name");
>attribute.setText("test");

④ 将文档写入XML文件

1
2
3
4
5
6
7
8
9
10
11
12
>// 文档中全为英文,不设置编码,直接写入的形式. 
>XMLWriter writer = new XMLWriter(new FileWriter("ot.xml"));
>writer.write(document);
>writer.close();

>// 文档中含有中文,设置编码格式写入的形式
>// 创建文件输出的时候,自动缩进的格式
>OutputFormat format = OutputFormat.createPrettyPrint();
>format.setEncoding("UTF-8");//设置编码
>XMLWriter writer = new XMLWriter(newFileWriter("output.xml"), format);
>writer.write(document);
>writer.close();

⑤ 字符串与XML的转换

1
2
3
4
5
6
7
8
9
10
11
12
>// 将字符串转化为XML
>String text = "<test> <java>Java</java></test>";
>Document document = DocumentHelper.parseText(text);

>// 将文档或节点的XML转化为字符串
>SAXReader reader = new SAXReader();
>Document document = reader.read(new File("test.xml"));
>Element root=document.getRootElement();
>String docXmlText=document.asXML();
>String rootXmlText=root.asXML();
>Element memberElm=root.element("test");
>String memberXmlText=memberElm.asXML();


本文作者:Jasonkay
本文链接:https://jasonkayzk.github.io/cn/2019/12/05/Java%E5%9F%BA%E7%A1%80%E6%80%BB%E7%BB%93%E4%B9%8B%E5%85%AB/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可