Xml文件的读取

1.Xml的验证模式

Xml文件的验证模式保证了Xml文件的正确性,常用的两种验证模式有DTD和XSD。
DTD(Document Type Definition):文档类型定义,是一种Xml约束模式语言,是Xml文件的验证机制,属于Xml文件组成的一部分。DTD是一种保证XML文档格式正确的有效方法,可以通过比较XML文档和DTD文件来看文档是否符合规范,元素和标签使用是否正确。一个DTD文档包含:元素的定义规则,元素间关系的定义规则,元素可使用的属性,可以使用的实体或符号规则。
使用DTD验证模式,需要在XML文件的头部声明:



< beans>
        ...
< /beans>

具体的Spring-beans-2.0dtd:

 





Xml Sechema语言XSD(XML Schemas Definition)。XSD描述了XML文档的结构,可以使用一个指定的XSD 来验证某个XML文档,以检查XML 文档是否符合要求。文档设计者可以通过XSD 指定XML文档所允许的结构和内容,并可以根据此检查XML文档是否有效,XSD本身是XML文档,符合XML语法结构,可以通过XML解析器进行解析。
使用XML Sechema 文档对XML文档进行检验时,除了要声明空间外(xmlns=http://www.Springframework.org/schema/beans),还必须指定该名称空间所对应的XML Schema文档的存储位置,通过schemaLocation属性来指定名称空间所对应的XML Schema文档的存储位置,它包含两部分,一部分是名称空间的uri,另一部分是该名称空间所标识的XML Schema’文件位置或者URL地址。(xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd)
eg:


< beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:util="http://www.springframework.org/schema/util"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/util 
		http://www.springframework.org/schema/util/spring-util-4.0.xsd">
	
< /beans>

2.验证模式的读取

Spring通过getValidationModeForResource方法来获取对应资源的验证模式:

protected int getValidationModeForResource(Resource resource) {
        int validationModeToUse = this.getValidationMode();
//如果手动指定了验证模式则使用指定的验证模式
        if (validationModeToUse != 1) {
            return validationModeToUse;
        } else {
//如果没有手动则使用自动检测
            int detectedMode = this.detectValidationMode(resource);
            return detectedMode != 1 ? detectedMode : 3;
        }

如果设定了验证模式则使用验证模式(可以通过调用XmlBeanDefinitionReader中的setValidationMode方法进行设定),否则使用自动检测的方式。自动检测验证模式的功能是在函数detectValidationMode方法中实现的,在detectValidationMode函数中又将自动检测模式的工作委托给了专门的处理类XmlValidationModeDetector,调用了XmlValidationModeDetector中的validationModeDetector方法:
XmlBeanDefinitionReader.java中的detectValidationMode方法:

protected int detectValidationMode(Resource resource) {
        if (resource.isOpen()) {
            throw new BeanDefinitionStoreException("Passed-in Resource [" + resource + "] contains an open stream: cannot determine validation mode automatically. Either pass in a Resource that is able to create fresh streams, or explicitly specify the validationMode on your XmlBeanDefinitionReader instance.");
        } else {
            InputStream inputStream;
            try {
                inputStream = resource.getInputStream();
            } catch (IOException var5) {
                throw new BeanDefinitionStoreException("Unable to determine validation mode for [" + resource + "]: cannot open InputStream. Did you attempt to load directly from a SAX InputSource without specifying the validationMode on your XmlBeanDefinitionReader instance?", var5);
            }

            try {
                return this.validationModeDetector.detectValidationMode(inputStream);
            } catch (IOException var4) {
                throw new BeanDefinitionStoreException("Unable to determine validation mode for [" + resource + "]: an error occurred whilst reading from the InputStream.", var4);
            }
        }
}

XmlValidationModeDetector.java中的detectValidationMode方法:

public int detectValidationMode(InputStream inputStream) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));

        byte var4;
        try {
            boolean isDtdValidated = false;

            while(true) {
                String content;
                if ((content = reader.readLine()) != null) {
                    content = this.consumeCommentTokens(content);
//如果是空行或者是注释则略过
                    if (this.inComment || !StringUtils.hasText(content)) {
                        continue;
                    }

                    if (this.hasDoctype(content)) {
                        isDtdValidated = true;
//读取到<开始之前,模式验证一定会在符号之前
                    } else if (!this.hasOpeningTag(content)) {
                        continue;
                    }
                }

                int var5 = isDtdValidated ? 2 : 3;
                return var5;
            }
        } catch (CharConversionException var9) {
            var4 = 1;
        } finally {
            reader.close();
        }

        return var4;
    }


//判断是否包含DOCTYPE
private boolean hasDoctype(String content) {
        return content.contains("DOCTYPE");
    }


//判断是否到了结束判断的条件 即有没有”<”
private boolean hasOpeningTag(String content) {
        if (this.inComment) {
            return false;
        } else {
            int openTagIndex = content.indexOf(60);
            return openTagIndex > -1 && content.length() > openTagIndex + 1 && Character.isLetter(content.charAt(openTagIndex + 1));
        }
    }

Spring验证是XSD还是DTD的方法就是在“<”之前判断是否包含DOCTYPE,如果包含,就是DTD,不包含就是XSD。

你可能感兴趣的:(Java,Spring)