使用DOM解析XML

使用DOM解析XML

DOM在内存中属于树形结构,当应用程序使用DOM解析时,首先要将读取到程序中的XML文件转换为DOM树,因此使用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解析流程

如果要进行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树

使用DOM解析XML_第1张图片

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();
    }
}

3.观察程序输出,发现解析成功

使用DOM创建XML文件

因为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 输出时是否添加空格

使用DOM解析XML_第2张图片

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>

修改XML文件

以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元素

删除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>

你可能感兴趣的:(Ajax异步交互)