DOM方式解析及生成XML
可扩展标记语言XML,Extensible Markup Language),一种标记性语言,被设计来用于数据的存储及传输。XML 无所不在。XML 是各种应用程序之间进行数据传输的最常用的工具,并且在信息存储和描述领域变得越来越流行。

下面转入正题:Java中DOM方式解析和生成XML文件
DOM方式是一种与平台无关的解析方式,也就是说其他一些语言如Javascript也支持DOM解析,其特点是一次性读取,即一次性将整个XML文档读取到内存,然后再逐个节点进行解析。是一种比较基础的方式,在Java中无需导入第三方的jar包即可完成解析和创建。

下面总结一下解析过程:(1)通过DocumentBuilderFactory的静态方法获取DocumentBuilderFactory实例。 (2)通过获取的DocumentBuilderFactory实例获得DocumentBuilder实例 。(3)通过DocumentBuilder获取Document实例。  (4)开始解析

解析过程中对于每个节点Node来说比较常用的方法: 获取节点名--> getNodeName(),  获取节点值--> getNodeValue(),   获取子节点列表 --> getChildNodes();   获取节点类型 --> getNodeType();  获取属性列表 --> getAttributes()等。

值得注意的一点是,对于Element类型的节点,使用其getNodeValue()方法获得的值为null,并且通过setNodeValue()方法设置其值也是不行的。下面是三种节点类型的对比(Element, Attribute, Text)。
文章正文图片

接下来简单写一个Demo,另外解析XML文件一般是从中获取某些信息,对象属性等。通常需要和Java实体类对应起来,为方便Demo编写,此处简单写了一个XML文件,如下:(language.xml)
< xml version="1.0" encoding="utf-8" >
<language cat="IT" count="3">
    <lan id="1">
        <name>Java</name>
        <IDE>eclipse</IDE>
        <filename_extension>.java</filename_extension>
    </lan>
    <lan id="2">
        <name>C++</name>
        <IDE>Cline</IDE>
        <filename_extension>.cpp</filename_extension>
    </lan>
    <lan id="3">
        <name>PHP</name>
        <IDE>PhpStorm</IDE>
        <filename_extension>.php</filename_extension>
        <description>the best language in the world.. </description>
    </lan>
</language>

然后新建一个实体类与之对应,便于存储至对象: 新建Language.java
package org.devsong.entity;

public class Language {

    private String name;
    private long id;
    private String IDE;
    private String nameExt;      //文件扩展名
    private String description;

    public Language() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getIDE() {
        return IDE;
    }

    public void setIDE(String iDE) {
        IDE = iDE;
    }

    public String getNameExt() {
        return nameExt;
    }

    public void setNameExt(String nameExt) {
        this.nameExt = nameExt;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    @Override
    public String toString() {
        return "Language [name=" + name + ", id=" + id + ", IDE=" + IDE + ", nameExt=" + nameExt + ", description=" + description
                + "]";
    }
}

为方便演示,在解析完成之后做一个输出,并且紧接着将存储到实体类中的对象重新构建生成与与解析文件同样的XML文件,先说一些构建过程,然后一并做示例,构建过程同样需要获取DocumentBuilder实例,所以: (1)获取documentBuilder; (2)创建一个document实例; (3)创建根节点(到达这一步之后,后面的子节点创建过程与创建根节点类似), (4)前面是构建文件结构的过程,并没有真正地生成XML文件,所以下一步为:获取TransformerFactory实例; (5)通过TransformerFactory实例获取Transformer, (6)通过Transformer的transform方法生成XML文件。看代码比较直观,下面是示例代码,解析与构建。
package org.devsong.xmlload.test;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.devsong.entity.Language;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class DomTest {

    private String typedItem = "lan";
    private ArrayList<Language> list = new ArrayList<>();
    private Language language = null;

    public static void main(String[] args) {
        DomTest test = new DomTest();
        test.startParse();
        test.genXML();
    }


    /**
     * 获取DocumentBuilder对象
     */
    public DocumentBuilder getDocumentBuilder() {
        // 通过DocumentBuilderFactory的静态方法获取实例
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = null;
        try {
            builder = factory.newDocumentBuilder();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        }
        return builder;
    }

    /**
     * 开始解析
     */
    private void startParse() {
        try {
            Document document = getDocumentBuilder().parse(new File("./src/res/language.xml"));
            Element root = document.getDocumentElement(); // 根节点
            // 调用parseNode方法开始递归解析
            parseNode(root);
            // 结束解析后存储最后一个未保存的实例对象
            list.add(language);

        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 输出 list 中的内容以便查看从 XML 中解析的内容是否正确对应到 language 实例
        System.out.println("\n\n=========================list=======================");
        for (Language lan : list) {
            System.out.println(lan);
        }
    }

    /**
     * 递归解析每一个节点
     */
    public void parseNode(Node root) {
        if (root == null)
            return;
        String nodeName = root.getNodeName();
        if (nodeName.equals(typedItem)) {
            // 如果当前条目名等于实例分类条目名,则输出换行以便观察
            System.out.println();
            // 如果对象language不为空,则表示已经存储了一个完整的对象,所以放入list中
            if (language != null) {
                list.add(language);
            }
            language = new Language();
        }

        // 输出节点名
        System.out.print(nodeName + ":");

        // 获取当前节点的所有属性
        NamedNodeMap nodeMap = root.getAttributes();
        if (nodeMap != null) {
            for (int i = 0; i < nodeMap.getLength(); i++) {
                Node node = nodeMap.item(i);
                // 输出属性信息
                System.out.print("[attr]" + node.getNodeName() + ":" + node.getNodeValue() + "   ");
                // 若当前节点名对应分类节点,且若当前属性名对应分类节点的 id 属性,则将属性存储至language实例对应属性
                if (nodeName.equals(typedItem) && node.getNodeName().equals("id")) {
                    language.setId(Long.parseLong(node.getNodeValue()));
                }
            }
        }

        // 剔除冗余内容:空格和换行
        // 在避免空指针异常的情况下如果当前获得的节点文本经过trim()之后不为空,则输出当前节点内容
        if (root.getFirstChild() != null && root.getFirstChild().getNodeValue() != null
                && !(root.getFirstChild().getNodeValue()).trim().equals("")) {
            String nodeValue = root.getFirstChild().getNodeValue();
            System.out.print(nodeValue + "   ");
            // 将节点名和节点值传递到store方法,以便存储至实例
            store(nodeName, nodeValue);
        }

        // 获取当前节点的所有子节点
        NodeList nodeList = root.getChildNodes();
        if (nodeList != null) {
            for (int i = 0; i < nodeList.getLength(); i++) {
                Node node = nodeList.item(i);
                // 剔除冗余节点(空文本段)
                if (node.getNodeType() != Node.TEXT_NODE) {
                    // 进行递归解析每一个节点
                    parseNode(node);
                }
            }
        }
    }

    /**
     * 存储属性到实体
     */
    public void store(String name, String value) {
        if (language == null)
            return;
        if ("name".equals(name)) {
            language.setName(value);
        } else if ("IDE".equals(name)) {
            language.setIDE(value);
        } else if ("filename_extension".equals(name)) {
            language.setNameExt(value);
        } else if ("description".equals(name)) {
            language.setDescription(value);
        }
    }

    /**
     * 生成XML文件
     */
    public void genXML() {
        // 获取documentBuilder
        DocumentBuilder db = getDocumentBuilder();
        // 创建一个document实例
        Document doc = db.newDocument();
        doc.setXmlStandalone(true);
        // 创建根节点
        Element language = doc.createElement("language");
        // 设置根节点属性
        language.setAttribute("CAT", "IT");
        language.setAttribute("count", "3");

        // 循环将每一个实例对应到 xml 节点
        for (int i = 0; i < list.size(); i++) {
            Language listEle = list.get(i);
            Element lan = doc.createElement("lan");
            lan.setAttribute("id", listEle.getId() + "");
            if (listEle.getName() != null) {
                Element name = doc.createElement("name");
                name.setTextContent(listEle.getName()); // 设置name节点内容
                lan.appendChild(name);
            }
            if (listEle.getIDE() != null) {
                Element IDE = doc.createElement("IDE");
                IDE.setTextContent(listEle.getIDE());
                lan.appendChild(IDE);
            }
            if (listEle.getNameExt() != null) {
                Element nameExt = doc.createElement("filename_extension");
                nameExt.setTextContent(listEle.getNameExt());
                lan.appendChild(nameExt);
            }
            if (listEle.getDescription() != null) {
                Element description = doc.createElement("description");
                description.setTextContent(listEle.getDescription());
                lan.appendChild(description);
            }
            language.appendChild(lan);
        }

        // 准备创建真实文件
        TransformerFactory tff = TransformerFactory.newInstance();
        try {
            Transformer tf = tff.newTransformer();
            // 设置每个节点之后输出换行
            tf.setOutputProperty(OutputKeys.INDENT, "yes");
            tf.transform(new DOMSource(language), new StreamResult(new File("./src/res/language_dom.xml")));
            System.out.println("generate xml: complete...");

        } catch (TransformerConfigurationException e) {
            e.printStackTrace();
        } catch (TransformerException e) {
            e.printStackTrace();
        }
    }
}


执行结果如下:

language:[attr]cat:IT   [attr]count:3   
lan:[attr]id:1   name:Java   IDE:eclipse   filename_extension:.java   
lan:[attr]id:2   name:C++   IDE:Cline   filename_extension:.cpp   
lan:[attr]id:3   name:PHP   IDE:PhpStorm   filename_extension:.php   description:the best language in the world..    

=========================list=======================
Language [name=Java, id=1, IDE=eclipse, nameExt=.java, description=null]
Language [name=C++, id=2, IDE=Cline, nameExt=.cpp, description=null]
Language [name=PHP, id=3, IDE=PhpStorm, nameExt=.php, description=the best language in the world.. ]
generate xml: complete...

可见正确解析并存储了XML文件内容,并且打开新创建的XML文件可以看到新文件创建无误,只是没有合理的缩进,所以看起来有些别扭,可以利用Eclipse的快捷键: Ctrl + Shift + f格式化代码,方便对比查看。

另外,由于当前只是一个简单的XML文件,暂时没有用到文档类型定义(DTD, Document Type Definition)或者可用于代替DTD的XML Schema,所以在代码中处理了一下,有一句doc.setXmlStandalone(true);若不这样设置,生成的XML文件头可能会显示Standalone="no"。之所以说可能是因为我在测试的时候不写这一句也不会出现Standalone="no", 但是网络上的教程的确或显示,可能是Java版本的不同吧。。。

 
It's
欢迎访问本站,欢迎留言、分享、点赞。愿您阅读愉快!
*转载请注明出处,严禁非法转载。
https://www.devsong.org
QQ留言 邮箱留言
头像
引用:
取消回复
提交
涂鸦
涂鸦
热门