DOM解析:
DOM解析XML的概述:
DOM解析优点:
整个文档树在内存中,便于操作;
可以修改,删除、重新排列XML;
可以随机访问任何一个节点,访问效率高。
DOM解析的缺点:
占用内存大,占用资源多
解析速度慢
DOM解析适用场合:
需多次访问这些数据;
对解析效率要求不高;
硬件资源充足(内存、CPU)。
DOM解析XML文件的步骤:
// 1、 获取解析器类工厂
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// 2、根据解析器工厂获得解析器
DocumentBuilder db = factory.newDocumentBuilder();
// 3、根据解析器获得document对象
Document document = db.parse("dtd/books.xml");//根据自己的XML文件路径填写
得到了DOCUMENT对象document,就相当于得到了整个xml文件
接下来通过代码进行实例的分析:
books.xml:
<?xml version="1.0" encoding="gbk" standalone="no"?><books>
<book language="zh">
<name>红楼梦</name>
<author>曹雪芹</author>
<price>76</price>
</book>
<book language="en">
<name>西游记</name>
<author>吴承恩</author>
<price>89</price>
</book>
</books>
DOM方式解析XML(通过简单的获取元素和属性):
public class Demo1 {
@Test
public void Test() {
// 1、 获取解析器类工厂
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// 2、根据解析器工厂获得解析器
try {
DocumentBuilder db = factory.newDocumentBuilder();
// 3、根据解析器获得document对象
Document document = db.parse("dtd/books.xml");
// 根据document对象获得节点值
NodeList nodes1 = document.getElementsByTagName("book");// 根据节点的元素名获取元素,返回的book节点可能不只一个,返回的是一个NodeList对象
System.out.println(nodes1.getLength());
for (int i = 0; i < nodes1.getLength(); i++) {
Node node = nodes1.item(i);// 根据元素获取元素节点book
//根据节获元素属性
NamedNodeMap attributes = node.getAttributes();
for (int j = 0; j < attributes.getLength(); j++) {
Node item = attributes.item(j);
System.out.println(item.getNodeName());//得到属性名
System.out.println(item.getNodeValue());//得到属性值
}
System.out.println(node.getNodeName());// 得到book元素(可能不只一个book元素)
NodeList childNodes = node.getChildNodes();// 根据上一步获得的book节点,获取book节点下面的子节点
for (int j = 0; j < childNodes.getLength(); j++) {
Node text = childNodes.item(j);
// 根据节点名称和xml文件中的元素名称做比较equals的打印输出
if (text.getNodeName().equals("name")) {
System.out.println(text.getTextContent());
}
if (text.getNodeName().equals("author")) {
System.out.println(text.getTextContent());
}
if (text.getNodeName().equals("price")) {
System.out.println(text.getTextContent());
}
}
}
} catch (ParserConfigurationException | SAXException | IOException e) {
e.printStackTrace();
}
}
}
接下来对XML文件进行简单的增、删、改操作:
增加元素和属性操作:
在book后面添加 1997-12-15 节点:
1、添加的位置
2、将元素创建出来
// dom元素增加操作
@Test
public void Test1() throws UnsupportedEncodingException, FileNotFoundException {
// 1、获取document对象
Document document = DomUtil.getDocument("xml/books.xml");
// 2、问题分析:book后面添加<data>1997-12-15</data>节点
// 2.1首先元素添加到那个位置
Node book = document.getElementsByTagName("book").item(0);
// 2.2元素要创建出来
Element data = document.createElement("data");
data.setTextContent("1997-12-15");
book.appendChild(data);
// 回写操作
DomUtil.backWrite(document, "xml/books.xml");
}
@Test
// 添加元素的属性
public void Test2() throws UnsupportedEncodingException, FileNotFoundException {
// 获得document对象
Document document = DomUtil.getDocument("xml/books.xml");
Element book = (Element) document.getElementsByTagName("book").item(0);
book.setAttribute("language", "英文");
// 回写操作
DomUtil.backWrite(document, "xml/books.xml");
}
删除元素和属性操作:
// dom删除元素
@Test
public void Test6() throws UnsupportedEncodingException, FileNotFoundException {
// 获取document对象
Document document = DomUtil.getDocument("xml/books.xml");
// 获取book元素
Node data = document.getElementsByTagName("data").item(0);
data.getParentNode().removeChild(data);// 先获取父节点,在根据父节点去删除子节点
// 回写操作
DomUtil.backWrite(document, "xml/books.xml");
}
@Test
// dom删除元素的属性
public void Test4() throws UnsupportedEncodingException, FileNotFoundException {
// 获取document对象
Document document = DomUtil.getDocument("xml/books.xml");
// 获取book元素
Element book = (Element) document.getElementsByTagName("book").item(0);
book.removeAttribute("language");
// 回写操作
DomUtil.backWrite(document, "xml/books.xml");
}
修改元素和属性操作:
@Test
// 修改元素内容 name中的内容
public void fun1() throws UnsupportedEncodingException, FileNotFoundException {
// 获取document对象
Document document = DomUtil.getDocument("dtd/books.xml");
// 得到name元素对象
NodeList authors = document.getElementsByTagName("author");
Node author = authors.item(0);// 得到第一个元素为author节点,假设知道
// 修改节点内容
author.setTextContent("小曹");
// 此时需要对author中的内容进行回写操作
// 回写操作
DomUtil.backWrite(document, "dtd/books.xml");
}
// 修改元素属性
@Test
public void fun2() throws UnsupportedEncodingException, FileNotFoundException {
// 获取document对象
Document document = DomUtil.getDocument("dtd/books.xml");
// 获取需要修改的元素
// 获取得到的元素是NodeList的返回值,.item(0)之后是Node的返回值,但是不能获取单个属性,查文档发现Element是可以获取得到单个属性
Element en = (Element) document.getElementsByTagName("book").item(0);
en.setAttribute("language", "en");
// 回写操作
DomUtil.backWrite(document, "dtd/books.xml");
}
将回写操作和获得document对象进行封装:
//将获得document对象进行封装
public static Document getDocument(String uri) {
// 1、创建解析器类工厂
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// 2、根据解析器工厂生产解析器
try {
DocumentBuilder db = factory.newDocumentBuilder();
// 3、根据生产的解析器获取document对象
Document document = db.parse(uri);
return document;
} catch (IOException | SAXException | ParserConfigurationException e) {
e.printStackTrace();
}
return null;
}
//将回写操作进行封装
public static void backWrite(Document document, String uri)
throws UnsupportedEncodingException, FileNotFoundException {
// 1、获得修改器工厂
TransformerFactory factory = TransformerFactory.newInstance();
// 2、根据修改器工厂获得修改器
try {
Transformer tf = factory.newTransformer();
// 3、根据修改器进行回写操作
// tf.transform(new DOMSource(document), new StreamResult(new
// File("dtd/books.xml")));
//解决乱码问题,出现问题的原因是:保存的XML文件的编码和解析是的编码不一致
tf.transform(new DOMSource(document),
new StreamResult(new OutputStreamWriter(new FileOutputStream(uri), "GBK")));// 解决乱码问题
} catch (TransformerConfigurationException e) {
e.printStackTrace();
} catch (TransformerException e) {
e.printStackTrace();
}
}