DOM在内存中属于树形结构,当应用程序使用DOM解析时,首先要将读取到程序中的XML文件转换为DOM树,因此使用DOM解析的并不是文件本身,而是读取到内存中的DOM树。
在XML解析的过程中,最大的接口为org.w3c.dom.Node
接口,在Node接口中提供有如下主要方法:
No | 返回值 | 方法名称 | 描述 |
---|---|---|---|
1 | Node | appendChild(Node newChild) | 将节点 newChild添加到此节点的子节点列表的末尾 |
2 | NodeList | getChildNodes() | 取得当前节点下的所有子节点 |
3 | Node | getFirstChild() | 取得当前节点下的第一个子节点 |
4 | String | getNodeName() | 取得节点名称 |
5 | String | getNodeValue() | 取得节点内容 |
6 | Node | getParentNode() | 取得当前节点的父节点 |
7 | String | getTextContent() | 取得节点中的文本内容 |
8 | Node | removeChild(Node oldChild) | 删除当前节点中的指定子节点 |
9 | Node | replaceChild(Node newChild, Node oldChild) | 替换子节点 |
10 | void | setNodeValue(String nodeValue) | 设置节点内容 |
11 | void | setTextContent(String textContent) | 设置节点文本内容 |
Node接口下提供了很多子接口:
Attr , CDATASection , CharacterData , Comment , Detail , DetailEntry , Document , DocumentFragment , DocumentType , Element , Entity , EntityReference , Node , Notation , ProcessingInstruction , SOAPBody , SOAPBodyElement , SOAPElement , SOAPEnvelope , SOAPFault , SOAPFaultElement , SOAPHeader , SOAPHeaderElement , Text , Text
其中比较常用的有Element
接口和Document
接口
元素接口(Element)中提供了如下主要方法:
No | 返回值 | 方法名称 | 描述 |
---|---|---|---|
1 | String | getAttribute(String name) | 取得该元素中指定属性的内容 |
2 | void | setAttribute(String name, String value) | 设置该元素中的属性名称以及内容 |
3 | NodeList | getElementsByTagName(String name) | 取得指定元素中指定名称的所有子元素 |
4 | String | getTagName() | 取得指定元素的指定标签名称 |
5 | void | removeAttribute(String name) | 删除指定元素的属性信息 |
Document
接口用来描述整个文档,即一个Document
包含了多个Element
,在Document
中定义了如下主要方法:
No | 返回值 | 方法名称 | 描述 |
---|---|---|---|
1 | Element | createElement(String tagName) | 创建新元素 |
2 | Text | createTextNode(String data) | 创建文本节点 |
3 | NodeList | getElementsByTagName(String tagname) | 取得文中所有的指定元素的节点对象 |
如果要进行DOM的处理操作,首先要启动其核心接口Document,若想得到Docuemnt接口对象可以通过文件解析或者自行创建。
在javax.xml.parsers.DocumentBuilderFactory
有如下主要方法:
No | 返回值 | 方法名称 | 描述 |
---|---|---|---|
1 | DocumentBuilderFactory | newInstance() | 获得一个新的一个 DocumentBuilderFactory实例 |
2 | DocumentBuilder | newDocumentBuilder() | 创建一个新的DocumentBuilder实例 |
在javax.xml.parsers.DocumentBuilder
有如下主要方法:
No | 返回值 | 方法名称 | 描述 |
---|---|---|---|
1 | Document | newDocument() | 创建一个新的文档 |
2 | Document | parse(InputStream is) | 将指定的XML输入流变为DOM树 |
1.创建petshop.xml文件
<shop>
<pet id="001">
<name>旺财name>
<species>拉布拉多species>
<age>2age>
pet>
<pet id="002">
<name>大明name>
<species>哈士奇species>
<age>0.5age>
pet>
shop>
2.编写程序实现读取操作
package xml;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
public class ReadTest {
public static void main(String[] args) throws Exception {
File file = new File("src"+File.separator+"petshop.xml");
InputStream input = new FileInputStream(file);
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.parse(input);
Element rootElement = (Element)document.getElementsByTagName("shop").item(0);
NodeList petElements = rootElement.getElementsByTagName("pet");
for(int x=0;x<petElements.getLength();x++){
String id = ((Element)petElements.item(x)).getAttributeNode("id").getValue();
String name = ((Element)petElements.item(x)).getElementsByTagName("name").
item(0).getFirstChild().getNodeValue();
String species = ((Element)petElements.item(x)).getElementsByTagName("species").
item(0).getFirstChild().getNodeValue();
String age = ((Element)petElements.item(x)).getElementsByTagName("age").
item(0).getFirstChild().getNodeValue();
System.out.println("id="+id+"\t"+"name="+name+"\t"+"species="+species+"\t"+"age="+age);
}
input.close();
}
}
因为DOM中没有规定输出的支持,如果想要输出,则需要借助以下类来完成:
在javax.xml.transform.TransformerFactory
有如下主要方法:
No | 返回值 | 方法名称 | 描述 |
---|---|---|---|
1 | TransformerFactory | newInstance() | 取得TransformerFactory类对象 |
2 | Transformer | newTransformer() | 取得Transformer类对象 |
在javax.xml.transform.Transformer
有如下主要方法:
No | 返回值 | 方法名称 | 描述 |
---|---|---|---|
1 | void | setOutputProperty(String name, String value) | 设置输出属性 |
2 | void | transform() | 转换输出 |
在javax.xml.transform.OutputKeys
有如下主要属性:
No | 属性名称 | 取值 | 描述 |
---|---|---|---|
1 | ENCODING | 字符编码 | 指定了encoding应用于将字符序列编码为字节序列的首选字符编码 |
2 | INDENT | yes或no | 输出时是否添加空格 |
package xml;
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;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class WriteTest {
public static void main(String[] args) throws Exception {
String[] names = {"拉布拉多","大明狗","大郎狗","大捞狗"};
String[] tels = {"156078945","gou-98745115","gou-98665115","gou-52565115"};
File file = new File("src"+File.separator+"phones.xml");
if(!file.getParentFile().exists()){
file.getParentFile().mkdirs();
if(!file.exists()){
file.createNewFile();
}
}
OutputStream output = new FileOutputStream(file);
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.newDocument();
Element phonesEle = document.createElement("phones");
for(int x=0;x<names.length;x++){
Element phoneEle = document.createElement("phone");
phoneEle.setAttribute("id",String.valueOf(x));
Element nameEle = document.createElement("name");
Element telEle = document.createElement("tel");
nameEle.appendChild(document.createTextNode(names[x]));
telEle.appendChild(document.createTextNode(tels[x]));
phoneEle.appendChild(nameEle);
phoneEle.appendChild(telEle);
phonesEle.appendChild(phoneEle);
}
document.appendChild(phonesEle);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.ENCODING,"UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT,"yes");
Source domSource = new DOMSource(document);
Result result = new StreamResult(output);
transformer.transform(domSource,result);
}
}
运行程序后发现,在src目录中出现了books.xml文件。
<phones>
<phone id="1">
<name>拉布拉多name>
<tel>156078945tel>
phone>
<phone id="2">
<name>大明狗name>
<tel>gou-98745115tel>
phone>
<phone id="3">
<name>大郎狗name>
<tel>gou-98665115tel>
phone>
<phone id="4">
<name>大捞狗name>
<tel>gou-52565115tel>
phone>
phones>
以DOM解析时所用的petshop.xml文件为例,若想再每一个pet节点下增加一个source子节点,则需要先将文件读入成为DOM树,修改后重新输出。
package xml;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
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;
import java.io.*;
public class UpdateTest {
public static void main(String[] args) throws Exception {
File file = new File("src"+File.separator+"petshop.xml");
InputStream input = new FileInputStream(file);
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.parse(input);
NodeList petElements = document.getElementsByTagName("pet");
for(int x=0;x<petElements.getLength();x++){
Element petElement = (Element)petElements.item(x);
Element sourceElement = document.createElement("source");
sourceElement.appendChild(document.createTextNode("GUB宠物商店"));
petElement.appendChild(sourceElement);
}
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT,"yes");
transformer.setOutputProperty(OutputKeys.ENCODING,"UTF-8");
Source source = new DOMSource(document);
Result result = new StreamResult(file);
transformer.transform(source,result);
input.close();
}
}
修改后的XML文件如下:
<shop>
<pet id="001">
<name>旺财name>
<species>拉布拉多species>
<age>2age>
<source>GUB宠物商店source>
pet>
<pet id="002">
<name>大明name>
<species>哈士奇species>
<age>0.5age>
<source>GUB宠物商店source>
pet>
shop>
删除XML元素与修改类似,但是要注意每次删除数据后,NodeList的长度都会动态的变化,因此我们只能循环删除第0个元素,以petshop.xml文件为例,假如想要删除所有的age元素,代码如下。
package xml;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
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;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
public class DeleteTest {
public static void main(String[] args) throws Exception {
File file = new File("src"+File.separator+"petshop.xml");
InputStream input = new FileInputStream(file);
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.parse(input);
NodeList petElements = document.getElementsByTagName("pet");
int len = petElements.getLength();
for(int x=0;x<len;x++){
Element petElement = (Element)petElements.item(x);
Element ageElement = (Element)petElement.getElementsByTagName("age").item(0);
ageElement.getParentNode().removeChild(ageElement);
}
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT,"yes");
transformer.setOutputProperty(OutputKeys.ENCODING,"UTF-8");
Source source = new DOMSource(document);
Result result = new StreamResult(file);
transformer.transform(source,result);
input.close();
}
}
<shop>
<pet id="001">
<name>旺财name>
<species>拉布拉多species>
<source>GUB宠物商店source>
pet>
<pet id="002">
<name>大明name>
<species>哈士奇species>
<source>GUB宠物商店source>
pet>
shop>