使用DOM解析XML

使用DOM解析XML

DOM在内存中属于树形结构,当应用程序使用DOM解析时,首先要将读取到程序中的XML文件转换为DOM树,因此使用DOM解析的并不是文件本身,而是读取到内存中的DOM树。

DOM标准接口

在XML解析的过程中,最大的接口为org.w3c.dom.Node接口,在Node接口中提供有如下主要方法:

No返回值方法名称描述
1NodeappendChild(Node newChild)将节点 newChild添加到此节点的子节点列表的末尾
2NodeListgetChildNodes()取得当前节点下的所有子节点
3NodegetFirstChild()取得当前节点下的第一个子节点
4StringgetNodeName()取得节点名称
5StringgetNodeValue()取得节点内容
6NodegetParentNode()取得当前节点的父节点
7StringgetTextContent()取得节点中的文本内容
8NoderemoveChild(Node oldChild)删除当前节点中的指定子节点
9NodereplaceChild(Node newChild, Node oldChild)替换子节点
10voidsetNodeValue(String nodeValue)设置节点内容
11voidsetTextContent(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返回值方法名称描述
1StringgetAttribute(String name)取得该元素中指定属性的内容
2voidsetAttribute(String name, String value)设置该元素中的属性名称以及内容
3NodeListgetElementsByTagName(String name)取得指定元素中指定名称的所有子元素
4StringgetTagName()取得指定元素的指定标签名称
5voidremoveAttribute(String name)删除指定元素的属性信息

Document接口用来描述整个文档,即一个Document包含了多个Element,在Document中定义了如下主要方法:

No返回值方法名称描述
1ElementcreateElement(String tagName)创建新元素
2TextcreateTextNode(String data)创建文本节点
3NodeListgetElementsByTagName(String tagname)取得文中所有的指定元素的节点对象
DOM解析流程

如果要进行DOM的处理操作,首先要启动其核心接口Document,若想得到Docuemnt接口对象可以通过文件解析或者自行创建。
javax.xml.parsers.DocumentBuilderFactory有如下主要方法:

No返回值方法名称描述
1DocumentBuilderFactorynewInstance()获得一个新的一个 DocumentBuilderFactory实例
2DocumentBuildernewDocumentBuilder()创建一个新的DocumentBuilder实例

javax.xml.parsers.DocumentBuilder有如下主要方法:

No返回值方法名称描述
1DocumentnewDocument()创建一个新的文档
2Documentparse(InputStream is)将指定的XML输入流变为DOM树

DOM解析

1.创建petshop.xml文件

<?xml encoding="UTF-8"  version="1.0" ?>
<shop>
    <pet id="001">
        <name>旺财</name>
        <species>拉布拉多</species>
        <age>2</age>
    </pet>
    <pet id="002">
        <name>大明</name>
        <species>哈士奇</species>
        <age>0.5</age>
    </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返回值方法名称描述
1TransformerFactorynewInstance()取得TransformerFactory类对象
2TransformernewTransformer()取得Transformer类对象

javax.xml.transform.Transformer有如下主要方法:

No返回值方法名称描述
1voidsetOutputProperty(String name, String value)设置输出属性
2voidtransform()转换输出

javax.xml.transform.OutputKeys有如下主要属性:

No属性名称取值描述
1ENCODING字符编码指定了encoding应用于将字符序列编码为字节序列的首选字符编码
2INDENTyes或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文件。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<phones>
    <phone id="1">
        <name>拉布拉多</name>
        <tel>156078945</tel>
    </phone>
    <phone id="2">
        <name>大明狗</name>
        <tel>gou-98745115</tel>
    </phone>
    <phone id="3">
        <name>大郎狗</name>
        <tel>gou-98665115</tel>
    </phone>
    <phone id="4">
        <name>大捞狗</name>
        <tel>gou-52565115</tel>
    </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文件如下:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<shop>
    <pet id="001">
        <name>旺财</name>
        <species>拉布拉多</species>
        <age>2</age>
        <source>GUB宠物商店</source>
    </pet>
    <pet id="002">
        <name>大明</name>
        <species>哈士奇</species>
        <age>0.5</age>
        <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();
    }
}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<shop>
    <pet id="001">
        <name>旺财</name>
        <species>拉布拉多</species>
        
        <source>GUB宠物商店</source>
    </pet>
    <pet id="002">
        <name>大明</name>
        <species>哈士奇</species>
        
        <source>GUB宠物商店</source>
    </pet>
</shop>

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值