本文共 3822 字,大约阅读时间需要 12 分钟。
目录
DefaultDocumentLoader#loadDocument方法是标准的 SAX 解析xml文件的代码,没有什么特殊处理的地方。
1.创建DocumentBuilderFactory 2.根据 DocumentBuilderFactory 创建 DocumentBuilder 3.DocumentBuilder 解析 InputSource 为 DocumentEntityResolver 解决 DTD 或XSD文件通过网络下载比较慢的问题,解决方案是本地获取 DTD或 XSD 文件。
详细看代码中注释
package org.springframework.beans.factory.xml;import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;import javax.xml.parsers.ParserConfigurationException;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.springframework.lang.Nullable;import org.w3c.dom.Document;import org.xml.sax.EntityResolver;import org.xml.sax.ErrorHandler;import org.xml.sax.InputSource;public class DefaultDocumentLoader implements DocumentLoader { private static final String SCHEMA_LANGUAGE_ATTRIBUTE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage"; private static final String XSD_SCHEMA_LANGUAGE = "http://www.w3.org/2001/XMLSchema"; private static final Log logger = LogFactory.getLog(DefaultDocumentLoader.class); public DefaultDocumentLoader() { } /** * 这里是标准的 SAX 解析xml文件的代码,没有什么特殊处理的地方。 * 1.创建DocumentBuilderFactory * 2.根据 DocumentBuilderFactory 创建 DocumentBuilder * 3.DocumentBuilder 解析 InputSource 为 Document * * */ public Document loadDocument(InputSource inputSource, EntityResolver entityResolver, ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception { // SAX, validationMode:2表示DTD,3表示XSD, // namespaceAware 这里为false,表示是否可以处理命名空间,false为不可以 DocumentBuilderFactory factory = this.createDocumentBuilderFactory(validationMode, namespaceAware); if(logger.isTraceEnabled()) { logger.trace("Using JAXP provider [" + factory.getClass().getName() + "]"); } // 创建 DocumentBuilder DocumentBuilder builder = this.createDocumentBuilder(factory, entityResolver, errorHandler); // 解析xml文件,文件通过 ClassPathResource --> EncodedResource --> InputSource return builder.parse(inputSource); } protected DocumentBuilderFactory createDocumentBuilderFactory(int validationMode, boolean namespaceAware) throws ParserConfigurationException { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(namespaceAware); if(validationMode != 0) { factory.setValidating(true); if(validationMode == 3) { factory.setNamespaceAware(true); try { factory.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema"); } catch (IllegalArgumentException var6) { 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(var6); throw pcex; } } } return factory; } /** * 1.创建 DocumentBuilder * 2.配置 EntityResolver ,这是获取 DTD、XSD的方法,具体参考:https://blog.csdn.net/ruanhao1203/article/details/103489931 */ protected DocumentBuilder createDocumentBuilder(DocumentBuilderFactory factory, @Nullable EntityResolver entityResolver, @Nullable ErrorHandler errorHandler) throws ParserConfigurationException { DocumentBuilder docBuilder = factory.newDocumentBuilder(); if(entityResolver != null) { docBuilder.setEntityResolver(entityResolver); } if(errorHandler != null) { docBuilder.setErrorHandler(errorHandler); } return docBuilder; }}