zoukankan      html  css  js  c++  java
  • XML文件解析之DOM解析

    XML文件是一种通用的数据交换格式,它的平台无关性,语言无关性,系统无关性,给数据集成与交互带来了极大的方便。基本的解析方式包括DOM解析和SAX解析,具体来说包括DOM解析,SAX解析,DOM4J解析以及JDOM解析,首先来讲下DOM解析的具体实现方式:

    1.重要的对象

    DocumentBuilderFactory: 创建文档解析器的工厂对象

    DocumentBuilder :得到文档解析器对象,由工长对象获取

    Document :文档对象

    2.解析XML实现方式

    XML文件:

    <?xml version="1.0" encoding="UTF-8"?>
    <world>
        <comuntry id="1">
            <name>China</name>
            <capital>Beijing</capital>
            <population>1234</population>
            <area>960</area>
        </comuntry>
        <comuntry id="2">
            <name id="">America</name>
            <capital>Washington</capital>
            <population>234</population>
            <area>900</area>
        </comuntry>
        <comuntry id="3">
            <name >Japan</name>
            <capital>Tokyo</capital>
            <population>234</population>
            <area>60</area>
        </comuntry>
        <comuntry id="4">
            <name >Russia</name>
            <capital>Moscow</capital>
            <population>34</population>
            <area>1960</area>
        </comuntry>
    </world>

    3.解析XML实现方式

           1.获得DocumentBuilderFactory 

          2.获得DocumentBuilder

         3.读取文件的输入流

         4.获得文档的根元素调用递归函数进行处理

    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.parsers.ParserConfigurationException;
    
    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 DOMParse {
    
        /**
         * 1.获得DocumentBuilderFactory
         * 2.获得DocumentBuilder
         * 3.读取文件的输入流
         * 4.获得文档的根元素调用递归函数进行处理
         * @param args
         */
        public static void main(String[] args) {
            
            //获得DocumentBuilderFactory
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            try {
                //获得DocumentBuilder 
                DocumentBuilder documentBuilder = factory.newDocumentBuilder();
                //读取文件的输入流
                InputStream inputStream = new FileInputStream(new File("world.xml")); 
                //获得文档对象
                Document document = documentBuilder.parse(inputStream);
                //获得文档的根元素
                Element rootElement = document.getDocumentElement();  
                listChildNodes(rootElement,0);
            } catch (ParserConfigurationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (SAXException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }
    
        
        /**
         * 递归遍历并打印所有的ElementNode(包括节点的属性)
         * 1.首先处理该节点信息
         * 2.处理节点的属性信息
         * 3.处理子节点(递归方法实现)
         * @param node   表示节点对象
         * @param level  节点所处的层次(从第一层根节点开始1)
         */
        public static void listChildNodes(Node node, int level) {
            //只处理ElementNode类型的节点
            if(level==0){
                System.out.println("<?xml version="1.0" encoding="UTF-8"?> ");
            }
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                boolean hasTextChild = false;
                String levelSpace = "";
                for (int i = 0; i < level; i++) {
                    levelSpace += "    ";
                }
                //先打印ElementNode的开始标签
                System.out.print(levelSpace + "<" + node.getNodeName()
                        + (node.hasAttributes() ? " " : ">"));// 有属性的话节点的开始标签后面的尖括号">"就留待属性打印完再打印
                if (node.hasAttributes()) {// 遍历打印节点的所有属性
                    NamedNodeMap namedNodeMap = node.getAttributes();
                    for (int i = 0; i < namedNodeMap.getLength(); i++) {
                        System.out.print(namedNodeMap.item(i).getNodeName()
                                + "=""// 字符串里含双引号要用到转义字符
                                + namedNodeMap.item(i).getNodeValue() + """
                                + (i == (namedNodeMap.getLength() - 1) ? "" : " "));// 不是最后一个属性的话属性之间要留空隙
                    }
                    System.out.print(">");// 开始标签里的属性全部打印完加上尖括号">"
                }
                // 该ElementNode包含子节点时候的处理
                if (node.hasChildNodes()) {
                    level++;// 有下一级子节点,层次加1,新的层次表示的是这个子节点的层次(递归调用时传给了它)
                    // 获得所有的子节点列表
                    NodeList nodelist = node.getChildNodes();
                    // 循环遍历取到所有的子节点
                    for (int i = 0; i < nodelist.getLength(); i++) {
                        //子节点为TextNode类型,并且包含的文本内容有效
                        if (nodelist.item(i).getNodeType() == Node.TEXT_NODE
                                && (!nodelist.item(i).getTextContent().matches("\s+"))) {// 用正则选取内容包含非空格的有效字符的文本节点
                            hasTextChild = true;// 该ElementNode的一级子节点是存在有效字符的文本节点
                            System.out.print(nodelist.item(i).getTextContent());// 在开始标签后面添加文本内容
                            //子节点是正常的ElementNode的处理
                        } else if (nodelist.item(i).getNodeType() == Node.ELEMENT_NODE) {
                            System.out.println();
                            // 递归调用方法 - 以遍历该节点下面所有的子节点
                            listChildNodes(nodelist.item(i), level);// level表示该节点处于第几个层次(相应空格)
                        }
                    }
                    level--;// 遍历完所有的子节点,层次变量随子节点的层数,依次递减,回归到该节点本身的层次
                    // level++ 和 level--对于该节点的子节点影响的是子节点的初值
                }
                //打印元素的结束标签.如果它的第一个一级子节点是有效文本的话,文本和结束标签添加到开始标签后面,
                //层次什么的就作废用不上了,否则,才按层次打印结束标签.
                System.out.print(((hasTextChild) ? "" : "
    " + levelSpace) + "</"+ node.getNodeName() + ">");
            }
        }
    }

    4.大功告成,这就是通过DOM方式实现了XML文件的解析,需要注意的地方就是那个递归调用函数,这个事实现动态解析的关键。用过知道了XML文件的内容,可以讲解析出来的具体对象封装起来,以便入库或者其他用处。有机会好好分享下。

  • 相关阅读:
    ConcurrentHashMap总结
    HashMap在多线程环境下操作可能会导致程序死循环
    oracle数据库的 to char 和to date 区别(时间格式化)
    SQL中的cast()函数用法
    常见的垃圾收集器有3类-java面试一
    mybatis中sql引用
    mysql find_in_set 查询
    用Redis实现微博关注关系的分析
    C#与C++相比较之STL篇(续一)
    Vite2.0 入门
  • 原文地址:https://www.cnblogs.com/zhangminghui/p/4067682.html
Copyright © 2011-2022 走看看