MyBatis 技术内幕 - 基础支持层 - 解析器模块 - XML

MyBatis 技术内幕 - 基础支持层 - 解析器模块 - XML


模块功能

  1. 对XPath进行封装,为MyBatis初始化时解析mybatis-config.xml配置文件及映射配置文件提供支持
  2. 处理动态SQL语句中的占位符

XML 简介1

  1. 简介:XML(全名:EXtensible Markup Language)可扩展标记性语言
  2. 目的:用于数据传输与存储
  3. 结构:XML 文档形成了一种树结构,它从“根部”开始,然后扩展到“枝叶”
  4. 组成:
    1. 文档声明:
      1. 定义版本及编码格式
        
        
      2. 引入文档类型定义
        
        
    2. 命名空间:
      1. 语法
        xmlns:namespace-prefix="namespaceURI"
        
        1. namespaceURI : 用于标示命名空间,命名空间中的地址不会被解析
        2. xmlns:(全名:XML NameSpace ,XML 命名空间)
      2. 作用
        1. 场景:当两个不同的XML中定义了相同的元素标签,比如table,在A文件中table表示表格,B文件中table表示桌子;当两个文件混合使用时会出现歧义;
        2. 解决:通过定义命名空间,设置空间的前缀名称,在 table 前通过前缀进行区分 h:table 与 f:table
    3. 元素:根元素、父元素、子元素
    4. 属性:描述元素的额外信心
    5. 实体:定义普通文本的变量(小于、大于、和、单引号、引号需要转义)
    6. 文本:XML 元素的开始标签与结束标签之间的文本,字符数据
      1. PCDATA:(全名:parsed character data,被解析的字符数据)
        1. 实体将会被转译,文本中不应包含 <、>、&、’、"
      2. CDATA: (全名:UnParsed character data ,不被解析的字符数据)
        1. 实体不会被转译,实体被当做普通文本处理
  5. 语言:
    1. 大小写敏感
    2. 属性值需要添加引号

XML 验证

  1. DTD 2

    1. 简介:DTD(全名:Document Type Defination ) 文档类型定义
    2. 作用:定义 XML 文档的合法构建模块
    3. 功能:
      1. 每一个XML文件都携带一个关于自身格式的描述
      2. 对内对外可以按照相同标准交换数据
    4. 示例
      1. XML 外部 DTD 引入

        1. animal.xml

          
          
          
          
          
          
          
              陆地动物
              大象
              雄性
              60
          
          
        2. animal_dtd_outside.dtd

          
          
          
          
          
          
      2. XML 内部 DTD 定义

        
        
        
        
        
        
        
                
                
                
                
                
                
                
                
                
                ]>
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
            陆地动物
            &elephant;
            雄性
            60
        
        
  2. XSD3

    1. 简介:XSD(全名:XML Schema Defination ,XML 纲要定义)
    2. 作用:描述XML文档结构;作为DTD的替代者
    3. 优势:相比与DTD
      1. 支持数据类型
      2. 支持命名空间

XML 解析

  1. DOM4(全名:Document Object Model ,文档对象模型)
    1. 实现原理:将XML文件解析成树形结构的DOM,即Document对象,将对XML各个属性节点的操作转为对DOM中各个节点(Node)的操作
      1. XML 文档 --> 文档节点
      2. XML 标签 --> 元素节点
      3. XML 属性 --> 属性节点
      4. XML 注释 --> 注释节点
    2. 方式优势
      1. 节点查询:DOM结构的特点能够定位根节点、兄弟节点、子节点
      2. 便于修改:DOM结构的特点能够增加或删除某个节点
      3. 配合XPath使用,能够查询到任意节点元素
    3. 方式劣势
      1. 内存消耗:需要一次性将整个XML文件加载到内存中并进行解析;当XML文档的数据量较大时,会造成较大的资源损耗
  2. SAX(全名:Simple API for XML)
    1. 实现原理:“推模式”,顺序读入XML文档内容,解析某一类型的节点时触发该类型节点的回调函数,即是将整个XML文档推给SAX进行处理
    2. 方式优势:
      1. 节省内存:无需加载整个XML文档,每次只加载XML文档的一部分;处理过程中内存不记录XML中的数据
    3. 方式劣势:
      1. 维护关系:因为加载过程中不记录XML文档中的内存,需要额外维护一份XML文档中各个节点之间的关系
      2. 单向处理:流式处理方式,只能从头到尾的单向处理
      3. 不支持XPath
  3. StAX(全名:Streaming API for XML)
    1. 实现原理:“拉模式”,应用程序通过StAX推进解析进程,控制整个解析进行,决定何时停止,可同时解析多个XML文档

XML 查询

  1. 语言名称:XPath5

  2. 语言语法

    表达式 含义
    nodename 选取指定节点的所有子节点
    / 从根节点选取指定节点
    // 根据指定的表达式,在整个文档中选取匹配的节点,不考虑匹配节点在文档中的位置
    . 选取当前节点
    . . 选取当前节点的父节点
    @ 选取属性
    * 匹配任何元素节点
    @* 匹配任何属性节点
    node() 匹配任何类型的节点
    text() 匹配文本节点
    [] 指定某个条件,用于查找某个特定节点或包含某个指定值的节点
  3. 代码示例

    1. XML 文档:book.xml

      
      
          
              Spring
              2018-11-11
          
          
              围城
              2014-10-10
          
          
              金融
              2018-12-12
          
      
      
      
      1. 注意事项
        1. XML 文档顶部不要加入,否则解析时会出现异常提示文档根元素 “book” 必须匹配 DOCTYPE 根 "null"

          
          
        2. 异常的原因在于XML文档不符合规范,需要标注文档所遵循的DTD(全名:Document Type Defination 文档类型定义),如:mapper.xml

            
          
    2. 查询测试

      package com.mybatis.test;
      
      import org.w3c.dom.Document;
      import org.w3c.dom.NodeList;
      import org.xml.sax.ErrorHandler;
      import org.xml.sax.SAXException;
      import org.xml.sax.SAXParseException;
      
      import javax.xml.parsers.DocumentBuilder;
      import javax.xml.parsers.DocumentBuilderFactory;
      import javax.xml.parsers.ParserConfigurationException;
      import javax.xml.xpath.*;
      import java.io.IOException;
      
      public class XPathTest {
      
          public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException, XPathExpressionException {
      
              DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
              // 开启验证
      
              /**
               * 功能:指定由此代码生成的解析器将验证被解析的文档
               * 解释:此处“验证”是指 xml 规范中定义的验证解析器,实际上仅控制 dtd 验证
               * 更改:要使用现代模式语言(如 w3c xml schema 或 relax ng)而不使用 dtd
               *      将解析器配置为非验证解析器,方法是将 setvalidating(boolean) 方法保留为 false,
               *      然后使用 setschema(schema) 方法将一个模式与解析器关联
               */
              documentBuilderFactory.setValidating(true);
              /**
               * 功能:指示是否将工厂配置为生成具有感知命名空间功能的解析器
               * 解释:XML Namespace (xmlns) 属性,XML文档的命名空间,其作用是区分不同文档中的相同元素名称的含义
               * 举例:A文档中table表示页面结果表格,B文档中table表示桌子,当A/B文档联合使用时会出现歧义,所以需要命名空间进行标识
               * 位置:命名空间放置在文档的开始位置
               * 作用:当命名空间被定义在元素的开始标签中时,所有带有相同前缀的子元素都会与同一个命名空间相关联
               * 链接:http://www.w3school.com.cn/xml/xml_namespaces.asp
               */
              documentBuilderFactory.setNamespaceAware(false);
              /**
               * 功能:指定由此代码生成的解析器将忽略注释
               */
              documentBuilderFactory.setIgnoringComments(true);
              /**
               * 功能:指定由此工厂创建的解析器在解析 xml 文档时,必须删除元素内容中的空格(有时也可以称作“可忽略空格”,请参阅 xml rec 2.10)。
               * 注意:只有在空格直接包含在元素内容中,并且该元素内容是只有一个元素的内容模式时,才能删除空格(请参阅 xml rec 3.2.1)。
               *      由于依赖于内容模式,因此此设置要求解析器处于验证模式。
               */
              documentBuilderFactory.setIgnoringElementContentWhitespace(false);
              /**
               * 功能:指示是否将工厂配置为生成满足以下条件的解析器:该解析器将 cdata 节点转换为 text 节点,并将其附加到相邻(如果有)的 text 节点。
               */
              documentBuilderFactory.setCoalescing(false);
              /**
               * 功能:指示是否将工厂配置为生成扩展实体引用节点的解析器
               */
              documentBuilderFactory.setExpandEntityReferences(true);
      
              // 设置 DocumentBuilder
              DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
              // 设置异常处理对象
              documentBuilder.setErrorHandler(new ErrorHandler() {
                  public void warning(SAXParseException exception) throws SAXException {
                      System.out.println("warning:"+exception.getMessage());
                  }
      
                  public void error(SAXParseException exception) throws SAXException {
                      System.out.println("exception:"+exception.getMessage());
                  }
      
                  public void fatalError(SAXParseException exception) throws SAXException {
                      System.out.println("fatal:"+exception.getMessage());
                  }
              });
      
              // 将文档加载到一个Document对象中,资源查找通过绝对路径
              String resource = "src\\main\\java\\com\\mybatis\\resources\\book.xml";
              Document document = documentBuilder.parse(resource);
      
              // 创建 XPathFactory
              XPathFactory xPathFactory = XPathFactory.newInstance();
              // 创建 XPath 对象
              XPath xPath = xPathFactory.newXPath();
              // 编译 XPath 表达式
              // 1.查询书名为Spring的购买时间
              System.out.println("查询书名为Spring的购买时间:");
              xPathEvaluateResult(xPath,document,"//category[name='Spring']/purchaseDate/text()");
              // 2.查询技术类型书籍名称
              System.out.println("查询技术类型书籍名称:");
              xPathEvaluateResult(xPath,document,"//category[@id='technology']/name/text()");
              // 3.查询所有书籍名称
              System.out.println("查询所有书籍名称:");
              xPathEvaluateResult(xPath,document,"//category/name/text()");
      
          }
      
          private static void xPathEvaluateResult(XPath xPath,Document document ,String expression) throws XPathExpressionException {
              XPathExpression xPathExpression = xPath.compile(expression);
              Object evaluate = xPathExpression.evaluate(document, XPathConstants.NODESET);
              NodeList nodeList = (NodeList) evaluate;
              for(int index = 0 ; index < nodeList.getLength() ; index++){
                  System.out.println(nodeList.item(index).getNodeValue());
              }
          }
      
      }
      
      

  1. XML教程 ↩︎

  2. DTD教程 ↩︎

  3. XSD教程 ↩︎

  4. DOM教程 ↩︎

  5. XPath语法教程 ↩︎

你可能感兴趣的:(#,MyBatis,技术内幕)