zoukankan      html  css  js  c++  java
  • XML 解析 DOM SAX PULL 序列化 总结 [MD]

    博文地址

    我的GitHub 我的博客 我的微信 我的邮箱
    baiqiantao baiqiantao bqt20094 baiqiantao@sina.com

    目录

    XML 解析 总结 DOM SAX PULL MD

    JDOM 仓库地址
    DOM4j 仓库地址
    XmlPull 仓库地址

    Android 中默认已经引入 XmlPull,如果需要自己引入,需要同时添加以下两个jar包:

    几种解析方式简介

    • DOM 方式解析:将xml文件全部载入到内存,组装成一棵dom树,然后通过节点以及节点之间的关系来解析xml文件;理解较简单,但是由于整个文档都需要载入内存,不适用于文档较大时。
    • SAX 方式解析:基于事件驱动,逐条解析,适用于只处理xml数据;不易编码,而且很难同时访问同一个文档中的多处不同数据。
    • JDOM 方式解析:主要用来弥补 DOM 和 SAX 在实际应用当中的不足,比使用 DOM 实现更快,仅使用具体类而不使用接口,因此简化了API,并且易于使用。
    • DOM4j 方式解析:JDOM的一种智能分支,功能较强大,建议熟练使用。
    • Pull 方式解析:Android提供的一种解析方式,与 SAX 解析器相似,基于事件驱动逐条解析,但需要使用parser.next()方法来提取它们。

    Pull 解析和 Sax 解析比较

    • Pull 解析和 Sax 解析在运行方式上具有相似性,Pull 解析器也提供了类似 SAX 的事件,开始文档START_DOCUMENT和结束文档END_DOCUMENT,开始元素START_TAG和结束元素END_TAG等,但需要调用next()方法提取它们(主动提取事件)。
    • SAX 解析器的工作方式是自动将事件推入注册的事件处理器进行处理,因此你不能控制事件的处理主动结束;而Pull解析器的工作方式为允许你的应用程序代码主动从解析器中获取事件,正因为是主动获取事件,因此可以在满足了需要的条件后不再获取事件,结束解析。这是他们主要的区别。
    • 即:SAX 解析会对整个文档进行解析,而 Pull 解析可以在程序中控制解析到哪里就可以中途停止。

    要解析的内容

    <?xml version="1.0" encoding="utf-8"?>
    <class>
      <string name="user">包青天</string>
      <string name="job" id="10086">Android开发</string>
      <student id="10010">
        <string name="user">白乾涛</string>
        <string name="job" id="100">码农</string>
      </student>
    </class>
    

    DOM 解析

    代码

    public static void domParseXml(String path) throws Exception {
    	System.out.println("--------------------  DOM解析  --------------------");
    	Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(path);
    	NodeList stringList = document.getElementsByTagName("string");
    	domParseNode(stringList); //长度为4【user:包青天, null】【job:Android开发, 10086】【user:白乾涛, null】【job:码农, 100】
    
    	NodeList studentList = document.getElementsByTagName("student");
    	System.out.println("【" + studentList.getLength() + "】");
    
    	for (int i = 0; i < studentList.getLength(); i++) {
    		NamedNodeMap map = studentList.item(i).getAttributes();
    		String id = map != null && map.getNamedItem("id") != null ? map.getNamedItem("id").getNodeValue() : null;
    		System.out.println("id = " + id);
    
    		NodeList childNodeList = studentList.item(i).getChildNodes();
    		domParseNode(childNodeList); //长度为5(而不是2)【user:白乾涛, null】【job:码农, 100】
    	}
    }
    
    private static void domParseNode(@NotNull NodeList nodeList) {
    	System.out.println("【" + nodeList.getLength() + "】");
    	for (int i = 0; i < nodeList.getLength(); i++) {
    		Node node = nodeList.item(i);  //获取第i个节点
    		if (node != null && node.getFirstChild() != null) {
    			NamedNodeMap map = node.getAttributes(); //获取此节点的所有属性
    			if (map != null) {
    				Node nameNode = map.getNamedItem("name"); //获取名为name的属性
    				String nameNodeValue = nameNode != null ? nameNode.getNodeValue() : null; //获取属性的属性值,也可以使用getTextContent
    				String nodeValue = node.getFirstChild().getNodeValue(); //获取节点的值
    
    				Node idNode = map.getNamedItem("id"); //获取名为id的属性
    				String idNodeValue = idNode != null ? idNode.getNodeValue() : null;
    				System.out.println(nameNodeValue + ":" + nodeValue + ", " + idNodeValue);
    			}
    		}
    	}
    }
    

    输出

    --------------------  DOM 解析  --------------------
    【4】
    user:包青天, null
    job:Android开发, 10086
    user:白乾涛, null
    job:码农, 100
    【1】
    id = 10010
    【5】
    user:白乾涛, null
    job:码农, 100
    

    SAX 解析

    代码

    System.out.println("--------------------  SAX解析  --------------------");
    SAXParserFactory.newInstance().newSAXParser().parse(path, new SAXParseHandel());
    

    SAXParseHandel

    public class SAXParseHandel extends DefaultHandler {
    
        @Override
        public void startDocument() throws SAXException {
            super.startDocument();
            System.out.println("开始解析");
        }
    
        @Override
        public void endDocument() throws SAXException {
            super.endDocument();
            System.out.println("结束解析");
        }
    
        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            super.startElement(uri, localName, qName, attributes);
            //开始解析节点时调用此方法
            System.out.println("开始解析" + qName);
    
            for (int i = 0; i < attributes.getLength(); i++) {
                System.out.println("     " + attributes.getQName(i) + ":" + attributes.getValue(i));//此案例中:getLocalName和getQName一致 ,getType的值为CDATA
            }
    
            switch (qName) {
            case "student":
                int index = attributes.getIndex("id");//当节点名为student时,获取student的id属性
                System.out.println("   --" + attributes.getQName(index) + ":" + attributes.getValue(index));
                break;
            case "string":
                System.out.print("  -" + attributes.getValue(attributes.getIndex("name")) + ":");
                break;
            }
        }
    
        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
            super.endElement(uri, localName, qName);
            //节点解析完毕时调用此方法
            System.out.println("结束解析" + qName);
        }
    
        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            super.characters(ch, start, length);
            //此方法用来获取节点的值
            String value = new String(ch, start, length).trim();
            if (!value.equals("")) {
                System.out.println(value);
            }
        }
    }
    

    输出

    --------------------  SAX 解析  --------------------
    开始解析
    开始解析class
    开始解析string
         name:user
      -user:包青天
    结束解析string
    开始解析string
         name:job
         id:10086
      -job:Android开发
    结束解析string
    开始解析student
         id:10010
       --id:10010
    开始解析string
         name:user
      -user:白乾涛
    结束解析string
    开始解析string
         name:job
         id:100
      -job:码农
    结束解析string
    结束解析student
    结束解析class
    结束解析
    

    JDOM 解析

    代码

    public static void jdomParseXml(String path) throws Exception {
    	System.out.println("--------------------  JDOM解析  --------------------");
    	org.jdom2.Document document = new SAXBuilder().build(path);
    	List<org.jdom2.Element> elementList = document.getRootElement().getChildren();
    
    	for (org.jdom2.Element element : elementList) {
    		jdomParseNode(element);
    
    		//解析子节点
    		for (org.jdom2.Element chileElement : element.getChildren()) {
    			jdomParseNode(chileElement);
    		}
    	}
    }
    
    private static void jdomParseNode(@NotNull org.jdom2.Element element) {
    	System.out.println(element.getName() + ":" + element.getTextTrim());
    
    	//解析属性
    	List<org.jdom2.Attribute> attributeList = element.getAttributes();
    	for (org.jdom2.Attribute attribute : attributeList) {
    		System.out.println("    " + attribute.getName() + ":" + attribute.getValue());
    	}
    }
    

    输出

    --------------------  JDOM 解析  --------------------
    string:包青天
        name:user
    string:Android开发
        name:job
        id:10086
    student:
        id:10010
    string:白乾涛
        name:user
    string:码农
        name:job
        id:100
    

    DOM4J 解析

    代码

    public static void dom4JParseXml(String path) throws Exception {
    	System.out.println("--------------------  DOM4J解析  --------------------");
    	org.dom4j.Document document = new SAXReader().read(path);
    	Iterator iterator = document.getRootElement().elementIterator();
    
    	while (iterator.hasNext()) {
    		org.dom4j.Element element = (org.dom4j.Element) iterator.next();
    		dom4JParseNode(element);
    
    		//遍历子节点
    		Iterator childIterator = element.elementIterator();
    		while (childIterator.hasNext()) {
    			dom4JParseNode((org.dom4j.Element) childIterator.next());
    		}
    	}
    }
    
    private static void dom4JParseNode(@NotNull org.dom4j.Element element) {
    	System.out.println(element.getName() + ":" + element.getTextTrim());
    
    	//解析属性
    	for (Object object : element.attributes()) {
    		org.dom4j.Attribute attribute = (org.dom4j.Attribute) object;
    		System.out.println("    " + attribute.getName() + ":" + attribute.getValue());
    	}
    }
    

    输出

    --------------------  DOM4J 解析  --------------------
    string:包青天
        name:user
    string:Android开发
        name:job
        id:10086
    student:
        id:10010
    string:白乾涛
        name:user
    string:码农
        name:job
        id:100
    

    PULL 解析

    代码

    public static void pullParseXml(String path) throws Exception {
    	System.out.println("--------------------  PULL解析  --------------------");
    	InputStream inputStream = new FileInputStream(path);
    	XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
    
    	parser.setInput(inputStream, "UTF-8");
    	int eventType = parser.getEventType();
    	while (eventType != XmlPullParser.END_DOCUMENT) { //文档结束
    		switch (eventType) {
    		case XmlPullParser.START_TAG://开始标签
    			String name = parser.getName();
    			System.out.println("开始解析 " + name + ", 行列:" + parser.getLineNumber() + "-" + parser.getColumnNumber() + ", 深度:" + parser.getDepth());
    			for (int i = 0; i < parser.getAttributeCount(); i++) {
    				//getAttributeType为【CDATA】,getAttributePrefix为【null】,getAttributeNamespace为空【】
    				System.out.println("     " + parser.getAttributeName(i) + ":" + parser.getAttributeValue(i));//属性名及属性值
    			}
    
    			if ("string".equals(name)) {
    				System.out.println(parser.nextText()); //获取节点的值
    			}
    			break;
    		case XmlPullParser.END_TAG://结束标签
    			System.out.println("结束解析" + parser.getName());
    			break;
    		}
    		eventType = parser.next();//这一步很重要,该方法返回一个事件码,也是触发下一个事件的方法
    	}
    }
    

    输出

    --------------------  PULL 解析  --------------------
    开始解析 class, 行列:2-8, 深度:1
    开始解析 string, 行列:3-23, 深度:2
         name:user
    包青天
    开始解析 string, 行列:4-33, 深度:2
         name:job
         id:10086
    Android开发
    开始解析 student, 行列:5-23, 深度:2
         id:10010
    开始解析 string, 行列:6-25, 深度:3
         name:user
    白乾涛
    开始解析 string, 行列:7-33, 深度:3
         name:job
         id:100
    码农
    结束解析student
    结束解析class
    

    2019-11-23

  • 相关阅读:
    Feign客户端的重构,新建springcloud架构
    Feign客户端实现RPC 调用
    Ribbon负载均衡实现
    负载均衡器nginx和ribbon区别
    eureka和zookeeper注册中心的区别
    SpringCloud服务的注册发现--------consul实现服务与发现
    Consul+upsync+Nginx 动态负载均衡
    Java并发编程笔记之ConcurrentLinkedQueue源码探究
    Java并发编程笔记之StampedLock锁源码探究
    Java并发编程笔记之读写锁 ReentrantReadWriteLock 源码分析
  • 原文地址:https://www.cnblogs.com/baiqiantao/p/11919687.html
Copyright © 2011-2022 走看看