XML解析为Document对象

2023-05-16

XML解析为Document对象

我们在上一篇Spring源码分析中有提到,Spring是将xml文件的InputStream转换为DOM树,然后在将DOM树解析转换为BeanDefinition从而注册bean,那么这一篇,我们就来介绍一些Spring如何将xml文件转换为Document
首选DOM解析XML文件的官方标准,DOM解析就是将整个XML文件转换为一个DOM节点树,然后通过遍历和查找节点来读取XML文件中定义的数据。

源码分析

Document doc = doLoadDocument(inputSource, resource);

protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
		return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
				getValidationModeForResource(resource), isNamespaceAware());
	}

可以看到解析xml文件的核心方法就是doLoadDocument(inputSource, resource);需要将xml文件对应的inputSource对象,以及存储需解析的xml相关信息的resource对象传入从而进行解析。在实际起作用的loadDocument的方法中有还有四个个参数是不需要我们传入的,他们分布代表解析文件的解析器,处理加载 Document 对象的过程的错误,XML的验证模式以及是否支持命名空间。在spring中存在两种验证模式分布是DTD和XSD,spring会根据你的xml文件获取到正确的模式进行赋值,一般我们使用的都是XSD模式。

protected EntityResolver getEntityResolver() {
		if (this.entityResolver == null) {
			// Determine default EntityResolver to use.
			ResourceLoader resourceLoader = getResourceLoader();
			if (resourceLoader != null) {
				this.entityResolver = new ResourceEntityResolver(resourceLoader);
			}
			else {
				this.entityResolver = new DelegatingEntityResolver(getBeanClassLoader());
			}
		}
		return this.entityResolver;
	}

如果 ResourceLoader 不为 null,则根据指定的 ResourceLoader 创建一个 ResourceEntityResolver。如果 ResourceLoader 为null,则创建 一个 DelegatingEntityResolver,该 Resolver 委托给默认的 BeansDtdResolver 和 PluggableSchemaResolver 。
那么这个EntityResolver到底是做上面用的呢?其实这个对象就是用来处理文件的验证方式的。
一般进行xml验证时会读取xml文档上的声明,并根据声明去运行相应的dtd定义,以便对文档进行验证,默认寻找规则去通过(即:通过网络,实现上就是声明DTD的地址URI地址来下载DTD声明),
并进行认证,下载的过程是一个漫长的过程,而且当网络不可用时,这里会报错,就是因为相应的dtd没找到,而 EntityResolver 的作用就是项目本身就可以提供一个如何寻找DTD 的声明方法,
即:由程序来实现寻找DTD声明的过程,比如我们将DTD放在项目的某处在实现时直接将此文档读取并返回,避免了通过网络来寻找DTD声明。

public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,
			ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {

		DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
		if (logger.isTraceEnabled()) {
			logger.trace("Using JAXP provider [" + factory.getClass().getName() + "]");
		}
		DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
		return builder.parse(inputSource);
	}

从源码中可以看出,解析xml文件主要为三步:
1、创建DocumentBuilderFactory对象
2、创建DocumentBuilder对象
3、将inputSource解析为Document对象
那么我们先来看第一步创建DocumentBuilderFactory对象

protected DocumentBuilderFactory createDocumentBuilderFactory(int validationMode, boolean namespaceAware)
			throws ParserConfigurationException {
		//获取DocumentBuilderFactory实例
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		factory.setNamespaceAware(namespaceAware);
		//如果开启xml验证的话,验证xml
		if (validationMode != XmlValidationModeDetector.VALIDATION_NONE) {
			factory.setValidating(true);
         //如果xml验证模式为XSD的话,则需强制指定由此代码生成的解析器将提供对XML名称空间的支持
			if (validationMode == XmlValidationModeDetector.VALIDATION_XSD) {
				// Enforce namespace aware for XSD...
				factory.setNamespaceAware(true);
				try {
					factory.setAttribute(SCHEMA_LANGUAGE_ATTRIBUTE, XSD_SCHEMA_LANGUAGE);
				}
				catch (IllegalArgumentException ex) {
					ParserConfigurationException pcex = new ParserConfigurationException(
							"Unable to validate using XSD: Your JAXP provider [" + factory +
							"] does not support XML Schema. Are you running on Java 1.4 with Apache Crimson? " +
							"Upgrade to Apache Xerces (or Java 1.5) for full XSD support.");
					pcex.initCause(ex);
					throw pcex;
				}
			}
		}

		return factory;
	}
protected DocumentBuilder createDocumentBuilder(DocumentBuilderFactory factory,
			@Nullable EntityResolver entityResolver, @Nullable ErrorHandler errorHandler)
			throws ParserConfigurationException {
		//创建DocumentBuilder对象
		DocumentBuilder docBuilder = factory.newDocumentBuilder();
        // 2、尝试设置entityResolver
		if (entityResolver != null) {
			docBuilder.setEntityResolver(entityResolver);
		}
        // 3、尝试设置errorHandler
		if (errorHandler != null) {
			docBuilder.setErrorHandler(errorHandler);
		}
		return docBuilder;
	}

最后一步的builder.parse(inputSource);就是调用jdk的相关接口,这里我们就不详细来讲了

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

XML解析为Document对象 的相关文章

随机推荐

  • ThingsBoard—自定义规则节点

    一般的功能 xff0c 可以使用现有的节点来完成 但如果有比较复杂 xff0c 或有自己特殊业务需求的 xff0c 可能就需要自定义了 按官方教程来基本就可以入门 xff0c 如果需要深入 xff0c 可以参考ThingsBoard自有节点
  • Thingsboard 报错 Cannot resolve symbol ‘TransportProtos‘

    本人idea 版本为 2021 1 xff0c 顺利编译 thingsboard 打开进行源码阅读时 xff0c 发现报 Cannot resolve symbol 39 TransportProtos 39 xff0c 如下图 xff1a
  • ThingsBoard 规则引擎-邮件通知

    之前我们已经学习了Thingsboard安装 设备接入 简单的数据可视化内容 xff0c 今天来继续学习下thingsboard其他特性 规则引擎 应用场景 ThingsBoard规则引擎是一个支持高度可定制复杂事件处理的框架 xff0c
  • ThingsBoard编译报错:Failure to find org.gradle:gradle-tooling-api:jar:6.3

    删除本地仓库未下载完成的缓存文件 xff08 删除像图片显示这样以 lastUpdated结尾的文件 xff09 执行mvn v确保maven命令可以正常执行执行下面命令 xff0c 将下载的jar安装到本地仓库 注意 xff1a 将 Df
  • Thingsboard3.4-OTA升级

    背景 在做设备端对接thingsboard平台得时候 xff0c 去研究设备端对接平台的过程中 xff0c 花了不少时间 xff0c 在此之前也没有找到相关的文档 xff0c 于是出于减少大家去研究的时间 xff0c 写了这篇博客 xff0
  • PyCharm更换pip源为国内源、模块安装、PyCharm依赖包导入导出教程

    一 更换pip为国内源 1 使用PyCharm创建一个工程 2 通过File gt Setting 选择解释器为本工程下的Python解释器 3 单击下图中添加 43 xff0c 4 单击下图中的 Manage Repositories 按
  • Pycharm没有找到manage repositories按钮解决方案

    问题描述 xff1a 不知道是因为版本原因还是其他 xff0c pycharm没有找到manage repositories按钮 xff0c 无法更改下载源 xff0c 导致安装库的速度会很慢 解决办法 xff1a 1 点击左下角的pyth
  • 通过改变JVM参数配置降低内存消耗

    有个项目 xff0c 其服务器端原本内存占用很大 xff0c 16G内存几乎都用光了 原先的JVM参数配置是这样的 xff1a Xms16384m Xmx16384m XX PermSize 61 64m XX MaxPermSize 61
  • NodeJS yarn 或 npm如何切换淘宝或国外镜像源

    一 查看当前的镜像源 npm config get registry 或 yarn config get registry 二 设置为淘宝镜像源 xff08 全局设置 xff09 npm config set registry https
  • Centos7 部署InfluxDB

    因为目前网络上关于InfluxDB的资料并不多 xff0c 所以这里建议多参考官网 官网 xff1a Home InfluxData 点击此处的Docs xff1a 这里选择 InfluxDB OSS xff1a 使用文档时根据需求选择查看
  • SpringBoot 集成 Emqx 发布/订阅数据

    最近项目中用到Emqx发布 订阅数据 xff0c 特此记录便于日后查阅 ThingsboardEmqxTransportApplication Copyright 2016 2023 The Thingsboard Authors lt p
  • Centos7部署Minio集群

    1 地址规划 minio1 span class token number 10 0 span 0 200 minio2 span class token number 10 0 span 0 201 minio3 span class t
  • Centos7 部署单机 Minio 对象存储服务

    MinIO 是一款基于 Go 语言发开的高性能 分布式的对象存储系统 xff0c 客户端支持 Java xff0c Net xff0c Python xff0c Javacript xff0c Golang语言 MinIO 的主要目标是作为
  • Netty源码解读

    Netty源码解读 Netty线程模型 1 定义了两组线程池BossGroup和WorkerGroup xff0c BossGroup专门负责接收客户端的连接 WorkerGroup专门负责网络的读写 2 BossGroup和WorkerG
  • Springboot Netty 实现自定义协议

    Netty是由JBOSS提供的一个java开源框架 xff0c 现为 Github上的独立项目 Netty提供异步的 事件驱动的网络应用程序框架和工具 xff0c 用以快速开发高性能 高可靠性的网络服务器和客户端程序 也就是说 xff0c
  • Netty 单机百万连接测试

    1 Netty框架简介 1 1 Netty简介 netty是jboss提供的一个java开源框架 xff0c netty提供异步的 事件驱动的网络应用程序框架和工具 xff0c 用以快速开发高性能 高可用性的网络服务器和客户端程序 也就是说
  • Grafana 可视化展示容器日志

    1 进入 dashboard 2 选择对应模板 3 选择相应的服务 4 关键词检索
  • 云服务的三种模式:SaaS、PaaS、IaaS

    云服务的三种模式 1 SaaS xff08 软件即服务 xff09 SaaS xff08 Software as a Service xff09 xff0c 即软件即服务 提供给消费者完整的软件解决方案 xff0c 你可以从软件服务商处以租
  • 三种方式实现Java生产者与消费者

    一 什么是生产者与消费者 生产者与消费者是java并发环境下常见的设计模式 xff0c 一个线程负责生产数据 xff0c 一个线程负责消费数据 xff0c 两个线程同时去操作这个变量 xff0c 但是这是两个相互互斥的操作 二 代码演示 1
  • XML解析为Document对象

    XML解析为Document对象 我们在上一篇Spring源码分析中有提到 xff0c Spring是将xml文件的InputStream转换为DOM树 xff0c 然后在将DOM树解析转换为BeanDefinition从而注册bean x