spring原始碼深度解析筆記(四)
DTD與XSD的區別 DTD(Document Type Definition)即文件型別定義,是一種XML約束模式語言,是XML檔案的驗證機制,是屬於XML檔案組成的一部分。DTD是一種保證XML文件格式正確的有效方法,可以通過比較XML文件和DTD檔案來看文件是否符合規範,元素和標籤使用是否正確。一個DTD文件包含:元素的定義規則,元素間關係的定義規則,元素可使用的屬性,可使用的屬性或者實體規則。 要使用DTD驗證模式的時候需要在XML檔案的頭部宣告,以下是Spring中使用DTD宣告方式的程式碼:
XML Schema語言就是XSD(XML Schema Definition)。XML Schema描述了XML文件的結構。可以用一個指定的XML Schema來驗證某個XML文件,以檢查該XML文件是否符合其要求。文件設計者可以通過XML Schema指定一個XML文件所允許的結構和內容,並可據此檢查一個XML文件是否有效。XML Schema本身就是一個XML文件,它符合XML語法結構。可以通過通用的XML解析器解析它。
在使用XML Schema文件對XML例項文件進行檢驗,除了要宣告名稱空間以外(xmlns=
protected int getValidationModeForResource (Resource resource) {
int validationModeToUse = getValidationMode();
//如果手動指定了驗證模式則使用指定的驗證模式
if (validationModeToUse != VALIDATION_AUTO) {
return validationModeToUse;
}
//如果未指定則使用自動驗證
int detectedMode = detectValidationMode(resource);
if (detectedMode != VALIDATION_AUTO) {
return detectedMode;
}
// Hmm, we didn't get a clear indication... Let's assume XSD,
// since apparently no DTD declaration has been found up until
// detection stopped (before finding the document's root tag).
return VALIDATION_XSD;
}
方法的實現挺簡單的。無非是如果設定了驗證模式則使用驗證模式(可以通過對呼叫XmlBeanDefinitionReader中的setValidationModel方法進行設定),否則使用自動檢測的方式。而自動檢測模式的功能是在函式detectValidationMode方法中實現的。在detectValidationMode函式中又將自動檢測驗證模式的工作委託給了專門處理類XmlValidationModelDetector,呼叫了XmlValidataionModelDetector的validationModeDetector方法。
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.");
}
InputStream inputStream;
try {
inputStream = resource.getInputStream();
}
catch (IOException ex) {
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?", ex);
}
try {
return this.validationModeDetector.detectValidationMode(inputStream);
}
catch (IOException ex) {
throw new BeanDefinitionStoreException("Unable to determine validation mode for [" +
resource + "]: an error occurred whilst reading from the InputStream.", ex);
}
}
public int detectValidationMode(InputStream inputStream) throws IOException {
// Peek into the file to look for DOCTYPE.
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
try {
boolean isDtdValidated = false;
String content;
while ((content = reader.readLine()) != null) {
content = consumeCommentTokens(content);
if (this.inComment || !StringUtils.hasText(content)) {
continue;
}
if (hasDoctype(content)) {
isDtdValidated = true;
break;
}
if (hasOpeningTag(content)) {
// End of meaningful data...
break;
}
}
return (isDtdValidated ? VALIDATION_DTD : VALIDATION_XSD);
}
catch (CharConversionException ex) {
// Choked on some character encoding...
// Leave the decision up to the caller.
return VALIDATION_AUTO;
}
finally {
reader.close();
}
}