XML解析之DOM二

      前面写过一个解析DOM的例子,但是例子比较简单,今天详细的来说一下这个DOM的解析。DOM解析是将XML文件解析为一棵DOM树加载到内存中,所以处理过程会比较快,但是耗费的内存也是很大的。如果文件大小很大的xml文件还是使用SAX处理比较好。

    下面来说说DOM的处理,我们有一个XML文件如下:

<?xml version="1.0" encoding="utf-8" ?>
<persons>
	<person>
	  <name>zhangsan</name>
	  <age>28</age>
	  <gender>boy</gender>
	  <job>Software Develper</job>
	</person>
	<person>
	  <name>lisi</name>
	  <age>26</age>
	  <gender>girl</gender>
	  <job>UI Develper</job>
	</person>
</persons>

    使用DOM处理这个文件步骤如下:

  1. 获取DocumentBuilderFacotry实例,使用DocumentBuilderFactory的newInstance()方法可以获取一个实例。

  2. 获取DocumentBuild实例,使用factory的newDocumentBuilder()获取实例。

  3. 获取Document实例,使用DocumentBuilder的parse()方法可以获取实例。

  4. 迭代处理每一个元素。

package com.app.dom;

import org.w3c.dom.*;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

/**
 * Created by Charles on 2015/12/14.
 */
public class DomParseMotion {

    public static void main(String[] args) {
        File f = new File("D:\\webservice\\dtd\\person.xml");
        try {
            InputStream ins = new FileInputStream(f);
            //第一步,获取DocumentBuilderFactory
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            //第二步,获取DocumentBuilder
            DocumentBuilder builder = factory.newDocumentBuilder();
            //第三步,获取Document
            Document doc = builder.parse(f);
            //获取根节点
            Element root = doc.getDocumentElement();
            //获取根节点下的每一个子节点
            NodeList list = root.getChildNodes();
            for (int i = 0; i < list.getLength(); i++) {
                Node node = list.item(i);
                //对于换行符等空白符节点,不是Element元素
                if (node instanceof Element) {
                    Element personElement = (Element) node;
                    NodeList childNodeList = personElement.getChildNodes();
                    for (int j = 0; j < childNodeList.getLength(); j++) {
                        Node childNode = childNodeList.item(j);
                        if(childNode instanceof Element){
                            Element childElement = (Element)childNode;
                            String tagName = childElement.getTagName();
                            //获取文本节点的元素
                            String value = ((Text)childElement.getFirstChild()).getData().trim();
                            switch(tagName){
                                case "name":
                                    System.out.println("name:"+value);
                                    break;
                                case "age":
                                    System.out.println("age:"+value);
                                    break;
                                case "gender":
                                    System.out.println("gender:"+value);
                                    break;
                                case "job":
                                    System.out.println("job:"+value);
                                    System.out.println("=====================");
                                    break;
                            }
                        }
                    }
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

     使用DOM处理XML文件是可以按照特定的步骤来操作的。但是也存在比较头疼的部分:1)对于带有换行符等易于阅读格式的XML文件来说,元素与元素之间的空格也会被当作Node结点来处理。2)对于格式统一的XML文件来说,数据的嵌套不宜太深,这样通过for循环迭代的层数就会越来越深。

    对于第一种空白符的问题,我们可以利用DTD等验证工具来简化我们的操作。依然同上述的XML文件,我们引进一个DTD的约束文件。

<!DOCTYPE persons SYSTEM "person.dtd">

    这个DTD文件如下:

<!ELEMENT persons (person+) >
<!ELEMENT person (name, age, gender, job)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ELEMENT gender (#PCDATA)>
<!ELEMENT job (#PCDATA)>

    再用DOM去解析如下:

package com.app.dom;

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;

/**
 * Created by Charles on 2015/12/15.
 */
public class DomDTDParseMOtion {

    public static void main(String args[]) {
        File f = new File("D:\\webservice\\dtd\\person.xml");
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            //使用DTD验证文档正确性
            factory.setValidating(true);
            //忽略空白节点
            factory.setIgnoringElementContentWhitespace(true);
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document doc = builder.parse(f);
            Element root = doc.getDocumentElement();
            NodeList list = root.getChildNodes();
            for (int i = 0; i < list.getLength(); i++) {
                Element parentElement = (Element) list.item(i);
                for (int j = 0; j < parentElement.getChildNodes().getLength(); j++) {
                    Element ele =(Element)parentElement.getChildNodes().item(j);
                    System.out.println(ele.getTagName());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

    使用了DTD验证,这样就忽略了空白节点的干扰,代码也就简单多了。这里有一个需要注意的地方,如果我们XML文件中引入的DTD验证的路径是通过相对路径来取得的,那么我们在传递给DocumentBuilder的参数中必须使用File,而不能使用流,不然DOM解析器是不能找到该DTD文件的。

   

   

你可能感兴趣的:(java,dom,dtd)