• xml解析


     

    XML解析

    1、XML概述

    • XML 指可扩展标记语言(EXtensible Markup Language)

    • XML 是一种标记语言,很类似 HTML

    • XML 的设计宗旨是传输数据,而非显示数据

    • XML 标签没有被预定义。您需要自行定义标签

    • XML 被设计为具有自我描述性

    • XML 是 W3C 的推荐标准

    2、XML组成

    2.1、标签

    1. 标签是由尖括号 包围的关键词,比如

      <book/>
    2. 标签通常是成对出现 的,比如

       <b></b>
    3. 标签对中的第一个标签是开始标签 ,第二个标签是结束标签 ,开始和结束标签也被称为开放标签闭合标签

    4. 空标签 由 一些标签没有内容,可以用一个标签来表示,比如setting标签

      <settings>
              <setting name="useGeneratedKeys" value="true"/>
              <setting name="mapUnderscoreToCamelCase" value="true"/>
              <setting name="logImpl" value="LOG4J"/>
      </settings>

    2.2、属性

    标签可以拥有属性 。属性提供了有关 HTML 元素的更多的信息

    属性总是以名称/值对的形式出现,比如:name="value"

    属性总是在 HTML 元素的开始标签 中规定。

    实例如下

    <a href="http://www.w3school.com.cn">This is a link</a>

    2.3、文本内容

    在开始标签与结束标签中可以存放文本内容

    2.4、XML 元素

    xml元素指的是从(且包括)开始标签直到(且包括)结束标签的部分。

    2.5、XML 文档形成一种树结构

    下面的 XML 文档表示书店中有的书

    <bookstore>
    <book category="COOKING">
      <title lang="en">Everyday Italian</title> 
      <author>Giada De Laurentiis</author> 
      <year>2005</year> 
      <price>30.00</price> 
    </book>
    <book category="CHILDREN">
      <title lang="en">Harry Potter</title> 
      <author>J K. Rowling</author> 
      <year>2005</year> 
      <price>29.99</price> 
    </book>
    <book category="WEB">
      <title lang="en">Learning XML</title> 
      <author>Erik T. Ray</author> 
      <year>2003</year> 
      <price>39.95</price> 
    </book>
    </bookstore>

    上述XML文档可以表示成一个树形结构

     

    3、xml基础语法

    1. XML 文档必须包含根元素 。该元素是所有其他元素的父元素。

    2. 所有 XML 元素都须有关闭标签。

    3. XML 标签对大小写敏感

    4. XML 的属性值须加引号

    5. XML 必须正确地嵌套

    6. 实体引用

      在 XML 中,一些字符拥有特殊的意义。

      如果你把字符 "<" 放在 XML 元素中,会发生错误,这是因为解析器会把它当作新元素的开始。

      这样会产生 XML 错误

      <message>if salary < 1000 then</message>

      为了避免这个错误,请用实体引用 来代替 "<" 字符:

      <message>if salary &lt; 1000 then</message> 

      在 XML 中,有 5 个预定义的实体引用:

      &lt; < 小于
      &gt; > 大于
      &amp; &
      &apos; ' 单引号
      &quot; " 引号
    7. XML 中的注释

      在 XML 中编写注释的语法与 HTML 的语法很相似:

      <!-- This is a comment -->
    8. 在 XML 中,空格会被保留

      HTML 会把多个连续的空格字符裁减(合并)为一个:

      HTML:   Hello           my name is David.
      输出: Hello my name is David.
      ​

      在 XML 中,文档中的空格不会被删节。

    9. xml文档声明

      一个 XML 文档实例

    <?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
    <note>
        <to>George</to>
        <from>John</from>
        <heading>Reminder</heading>
        <body>Don't forget the meeting!</body>
    </note>

     

    第一行:

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>

    语法要求<,?,xml之间不能有空格, ?>之间不能有空格,standalone="no"?两者之间可以有一个或多个空格。

    encoding=”utf-8”:那么解析器读到该属性,那么会以utf-8解码,如果不写呢?XML解析器通过寻找XML文档开始处的字节序列,能够自动检测出文档中的Unicode编码是UTF-8还是UTF-16.也就是说encoding属性的默认值是Unicode编码,如果文档是以UTF-8/UTF-16编码那么可以不设置该属性.

    standalone属性用于说明文档是否独立(该文档没有依赖外面的任何文件而可以单独存在(例如依赖dtd文件) 所以值是yes,)。独立的文档是yes, 依赖外部文件的文档是no。standalone属性位于encoding属性之后。

     

    4、XML文档解析

    XML的解析方式分为两种:1、DOM解析;2、SAX解析

    4.1、DOM解析

    **DOM的全称是Document Object Model,也即文档对象模型。在应用程序中,基于DOM的XML分析器将一个XML文档转换成一个对象模型的集合(通常称DOM树),应用程序正是通过对这个对象模型的操作,来实现对XML文档数据的操作。通过DOM接口,应用程序可以在任何时候访问XML文档中的任何一部分数据,因此,这种利用DOM接口的机制也被称作随机访问机制。** 
    ​
    **DOM接口提供了一种通过分层对象模型来访问XML文档信息的方式,这些分层对象模型依据XML的文档结构形成了一棵节点树。无论XML文档中所描述的是什么类型的信息,即便是制表数据、项目列表或一个文档,利用DOM所生成的模型都是节点树的形式。也就是说,DOM强制使用树模型来访问XML文档中的信息。由于XML本质上就是一种分层结构,所以这种描述方法是相当有效的。**

     

      DOM树所提供的随机访问方式给应用程序的开发带来了很大的灵活性,它可以任意地控制整个XML文档中的内容。然而,由于DOM分析器把整个XML文档转化成DOM树放在了内存中,因此,当文档比较大或者结构比较复杂时,对内存的需求就比较高。而且,对于结构复杂的树的遍历也是一项耗时的操作。所以,DOM分析器对机器性能的要求比较高,实现效率不十分理想。不过,由于DOM分析器所采用的树结构的思想与XML文档的结构相吻合,同时鉴于随机访问所带来的方便,因此,DOM分析器还是有很广泛的使用价值的。

    优点:

    1、形成了树结构,有助于更好的理解、掌握,且代码容易编写。

    2、解析过程中,树结构保存在内存中,方便修改。

    缺点:

    1、由于文件是一次性读取,所以对内存的耗费比较大。

    2、如果XML文件比较大,容易影响解析性能且可能会造成内存溢出。

    xml实例

    <?xml version="1.0" encoding="UTF-8"?>
    <bookstore>
        <book id="1">
            <name>冰与火之歌</name>
            <author>乔治马丁</author>
            <year>2014</year>
            <price>89</price>
        </book>
        <book id="2">
            <name>安徒生童话</name>
            <year>2004</year>
            <price>77</price>
            <language>English</language>
        </book>    
    </bookstore>
    ​
    public class DOMTest {
        public static void main(String[] args) {
            //创建一个DocumentBuilderFactory的对象
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            //创建一个DocumentBuilder的对象
            try {
                //创建DocumentBuilder对象
                DocumentBuilder db = dbf.newDocumentBuilder();
                //通过DocumentBuilder对象的parser方法加载books.xml文件到当前项目下
                Document document = db.parse("books.xml");
                //获取所有book节点的集合
                NodeList bookList = document.getElementsByTagName("book");
                //通过nodelist的getLength()方法可以获取bookList的长度
                System.out.println("一共有" + bookList.getLength() + "本书");
                //遍历每一个book节点
                for (int i = 0; i < bookList.getLength(); i++) {
                    System.out.println("=================下面开始遍历第" + (i + 1) + "本书的内容=================");
                    //通过 item(i)方法 获取一个book节点,nodelist的索引值从0开始
                    Node book = bookList.item(i);
                    //获取book节点的所有属性集合
                    NamedNodeMap attrs = book.getAttributes();
                    System.out.println("第 " + (i + 1) + "本书共有" + attrs.getLength() + "个属性");
                    //遍历book的属性
                    for (int j = 0; j < attrs.getLength(); j++) {
                        //通过item(index)方法获取book节点的某一个属性
                        Node attr = attrs.item(j);
                        //获取属性名
                        System.out.print("属性名:" + attr.getNodeName());
                        //获取属性值
                        System.out.println("--属性值" + attr.getNodeValue());
                    }
                    //解析book节点的子节点
                    NodeList childNodes = book.getChildNodes();
                    //遍历childNodes获取每个节点的节点名和节点值
                    System.out.println("第" + (i+1) + "本书共有" + 
                    childNodes.getLength() + "个子节点");
                    for (int k = 0; k < childNodes.getLength(); k++) {
                        //区分出text类型的node以及element类型的node
                        if (childNodes.item(k).getNodeType() == Node.ELEMENT_NODE) {
                            //获取了element类型节点的节点名
                            System.out.print("第" + (k + 1) + "个节点的节点名:" 
                            + childNodes.item(k).getNodeName());
                            //获取了element类型节点的节点值
                            System.out.println("--节点值是:" + childNodes.item(k).getFirstChild().getNodeValue());
                            //System.out.println("--节点值是:" + childNodes.item(k).getTextContent());
                        }
                    }
                    System.out.println("======================结束遍历第" + (i + 1) + "本书的内容=================");
                }
            } catch (ParserConfigurationException e) {
                e.printStackTrace();
            } catch (SAXException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }        
        }
    }
    ​

    上述代码把XML解析成Document ,对XML元素的访问太过麻烦,还有一种通过XPaht方式的访问方式,在Mybatis中也是采取这种方式

    实例如下

    <?xml version="1.0" encoding="UTF-8" ?>
    <users>
        <user id = "1">
            <name>张三</name>
            <createTime>2018-06-06 00:00:00</createTime>
            <passward>admin</passward>
            <phone>180000000</phone>
            <nickName>阿毛</nickName>
        </user>
        <user id = "2">
            <name>李四</name>
            <createTime>2018-06-06 00:00:00</createTime>
            <passward>admin</passward>
            <phone>180000001</phone>
            <nickName>明明</nickName>
        </user>
    </users>
    ​

    xml对应的java类

    package com.blog4java.mybatis.xpath;
    ​
    import lombok.Data;
    ​
    import java.util.Date;
    ​
    @Data
    public class UserEntity {
        private Long id;
        private String name;
        private Date createTime;
        private String password;
        private String phone;
        private String nickName;
    }
    ​

    java解析代码

    package com.blog4java.mybatis.xpath;
    ​
    import com.alibaba.fastjson.JSON;
    import org.apache.commons.beanutils.BeanUtils;
    import org.apache.commons.beanutils.ConvertUtils;
    import org.apache.commons.beanutils.converters.DateConverter;
    import org.apache.ibatis.builder.BuilderException;
    import org.apache.ibatis.io.Resources;
    import org.junit.Test;
    import org.w3c.dom.Document;
    import org.w3c.dom.NodeList;
    ​
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.xpath.XPath;
    import javax.xml.xpath.XPathConstants;
    import javax.xml.xpath.XPathFactory;
    import java.io.InputStream;
    import java.lang.reflect.InvocationTargetException;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.List;
    ​
    public class XPathExample {
    ​
        @Test
        public void testXPathParser() {
            try {
                // 创建DocumentBuilderFactory实例    Jdk内部的类
                DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
                // 创建DocumentBuilder实例
                DocumentBuilder builder = factory.newDocumentBuilder();
                InputStream inputSource = Resources.getResourceAsStream("users.xml");
                Document doc = builder.parse(inputSource);
                // 获取XPath实例    Jdk内部的类
                XPath xpath = XPathFactory.newInstance().newXPath();
                // 执行XPath表达式,获取节点信息
                NodeList nodeList = (NodeList)xpath.evaluate("/users/*", doc, XPathConstants.NODESET);
                List<UserEntity> userList = new ArrayList<>();
                for(int i=1; i < nodeList.getLength() + 1; i++) {
                    String path = "/users/user["+i+"]";
                    String id = (String)xpath.evaluate(path + "/@id", doc, XPathConstants.STRING);
                    String name = (String)xpath.evaluate(path + "/name", doc, XPathConstants.STRING);
                    String createTime = (String)xpath.evaluate(path + "/createTime", doc, XPathConstants.STRING);
                    String passward = (String)xpath.evaluate(path + "/passward", doc, XPathConstants.STRING);
                    String phone = (String)xpath.evaluate(path + "/phone", doc, XPathConstants.STRING);
                    String nickName = (String)xpath.evaluate(path + "/nickName", doc, XPathConstants.STRING);
                    // 调用buildUserEntity()方法,构建UserEntity对象
                    UserEntity userEntity = buildUserEntity(id,name, createTime, passward, phone, nickName);
                    userList.add(userEntity);
                }
                System.out.println(JSON.toJSONString(userList));
            } catch (Exception e) {
                throw new BuilderException("Error creating document instance.  Cause: " + e, e);
            }
        }
    ​
        private UserEntity buildUserEntity(String id,String name,
                                           String createTime, String passward,
                                           String phone, String nickName)
                throws IllegalAccessException, InvocationTargetException {
            UserEntity userEntity = new UserEntity();
            DateConverter dateConverter = new DateConverter(null);
            dateConverter.setPattern("yyyy-MM-dd HH:mm:ss");
            ConvertUtils.register(dateConverter,Date.class);
            BeanUtils.setProperty(userEntity,"id",id);
            BeanUtils.setProperty(userEntity,"name",name);
            BeanUtils.setProperty(userEntity,"createTime",createTime);
            BeanUtils.setProperty(userEntity,"passward",passward);
            BeanUtils.setProperty(userEntity,"phone",phone);
            BeanUtils.setProperty(userEntity,"nickName",nickName);
            return userEntity;
        }
    }
    ​
  • 相关阅读:
    困难4. 寻找两个正序数组的中位数
    6. Z 字形变换
    学习mysql176. 第二高的薪水
    竞赛6194. 最小 XOR
    中等856. 括号的分数
    竞赛6193. 沙漏的最大总和
    竞赛2430. 对字母串可执行的最大删除数
    困难927. 三等分
    困难1235. 规划兼职工作
    学习下mysql175. 组合两个表
  • 原文地址:https://www.cnblogs.com/cplinux/p/15310283.html
Copyright © 2020-2023  润新知