XML解析 验证之XSD和DTD验证以及 SpringXML验证源码分析
1.DTD(Documnet Type Definition)
DTD即文档类型定义,是一种XML约束模式语言,是XML文件的验证机制,属于XML文件组成的一部分。
DTD 是一种保证XML文档格式正确的有效方法,可以通过比较XML文档和DTD文件来看文档是否符合规范,元素和标签使用是否正确。
一个 DTD文档包含:
元素的定义规则,元素间关系的定义规则,元素可使用的属性,可使用的实体或符号规则。 DTD和XSD相比:DTD 是使用非 XML 语法编写的。 DTD 不可扩展,不支持命名空间,只提供非常有限的数据类型 .
2.XSD(XML Schemas Definition)
XML Schema语言也就是XSD。XML Schema描述了XML文档的结构。 可以用一个指定的XML Schema来验证某个XML文档,以检查该XML文档是否符合其要求。文档设计者可以通过XML Schema指定一个XML文档所允许的结构和内容,并可据此检查一个XML文档是否是有效的。XML Schema本身是一个XML文档,它符合XML语法结构。可以用通用的XML解析器解析它。 一个XML Schema会定义:文档中出现的元素、文档中出现的属性、子元素、子元素的数量、子元素的顺序、元素是否为空、元素和属性的数据类型、元素或属性的默认 和固定值。
XSD是DTD替代者的原因,一是据将来的条件可扩展,二是比DTD丰富和有用,三是用XML书写,四是支持数据类型,五是支持命名空间。
XML Schema的优点:
- XML Schema基于XML,没有专门的语法
- XML Schema可以象其他XML文件一样解析和处理
- XML Schema比DTD提供了更丰富的数据类型.
- XML Schema提供可扩充的数据模型。
- XML Schema支持综合命名空间
- XML Schema支持属性组。
3 XSD验证
XML文件
<?xml version="1.0"?>
<note xmlns="http://adcoup.baidu.com/schema/note">
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
XSD文件
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://adcoup.baidu.com/schema/note" xmlns="http://adcoup.baidu.com/schema/note"
elementFormDefault="qualified">
<xs:element name="note">
<xs:complexType>
<xs:sequence>
<xs:element name="to" type="xs:string" />
<xs:element name="from" type="xs:string" />
<xs:element name="heading" type="xs:string" />
<xs:element name="body" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
JAVA验证代码
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.dom4j.io.SAXValidator;
import org.dom4j.util.XMLErrorHandler;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.IOException;
import java.net.URL;
import java.util.List;
public class XsdXmlValidator {
public static void main(String[] args) throws IOException, SAXException, ParserConfigurationException {
validateXMLByXSD();
}
public static void validateXMLByXSD() {
// 从类路径下读取文件
URL xmlFileName = XsdXmlValidator.class.getClassLoader().getResource("note.xml");
// 输出为file:/D:/MyWorkSpace/FirstWorkSpace/validate-xml-test/target/classes/test_schema.xsd
String xsdFileName = XsdXmlValidator.class.getClassLoader().getResource("note.xsd").toString();
try {
//创建默认的XML错误处理器
XMLErrorHandler errorHandler = new XMLErrorHandler();
//获取基于 SAX 的解析器的实例
SAXParserFactory factory = SAXParserFactory.newInstance();
//解析器在解析时验证 XML 内容。
factory.setValidating(true);
//指定由此代码生成的解析器将提供对 XML 名称空间的支持。
factory.setNamespaceAware(true);
//使用当前配置的工厂参数创建 SAXParser 的一个新实例。
SAXParser parser = factory.newSAXParser();
//创建一个读取工具
SAXReader xmlReader = new SAXReader();
//获取要校验xml文档实例
Document xmlDocument = (Document) xmlReader.read(xmlFileName);
//设置 XMLReader 的基础实现中的特定属性。核心功能和属性列表可以在 [url]http://sax.sourceforge.net/?selected=get-set[/url] 中找到。
parser.setProperty("http://java.sun.com/xml/jaxp/properties/schemaLanguage",
"http://www.w3.org/2001/XMLSchema");
parser.setProperty("http://java.sun.com/xml/jaxp/properties/schemaSource",xsdFileName);
//创建一个SAXValidator校验工具,并设置校验工具的属性
SAXValidator validator = new SAXValidator(parser.getXMLReader());
//设置校验工具的错误处理器,当发生错误时,可以从处理器对象中得到错误信息。
validator.setErrorHandler(errorHandler);
//校验
validator.validate(xmlDocument);
StringBuilder errorMsg = new StringBuilder();
//如果错误信息不为空,说明校验失败,打印错误信息
if (errorHandler.getErrors().hasContent()) {
List<Element> elements = errorHandler.getErrors().elements();
for (Element element : elements) {
String line = String.valueOf(Integer.parseInt(element.attributeValue("line")) - 1);
String text = element.getText();
errorMsg.append("(第 " + line + "行出现错误) " + text+"\r\n");
}
errorMsg.append("XML文件通过XSD文件校验失败!");
System.out.println(errorMsg.toString());
}else {
System.out.println("XML文件通过XSD文件校验成功!");
}
} catch (Exception ex) {
System.out.println("XML文件: " + xmlFileName + " 通过XSD文件:" + xsdFileName + "检验失败。/n原因: " + ex.getMessage());
ex.printStackTrace();
}
}
}
4 关于Spring对XML解析的验证源码分析
源码在DefaultDocumentLoader类的createDocumentBuilderFactory()方法:
1 下面使用了javax.xml获取DocumenBuildFactory.这行代码是原生的Java对xml的解析!
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
2 createDocumentBuilderFactory方法传递了两个参数
1)int validationMode:XML验证模式
/**
* 0表示禁用验证XML
*/
public static final int VALIDATION_NONE = 0;
/**
* 1表示根据XML文件格式自动验证
*/
public static final int VALIDATION_AUTO = 1;
/**
* DTD方式验证XML
*/
public static final int VALIDATION_DTD = 2;
/**
* XSD方式验证XML
*/
public static final int VALIDATION_XSD = 3;
boolean namespaceAware 是否设置命名空间。在XML解析过程中依情况而定。我在上述XSD代码验证过程中设置了true
protected DocumentBuilderFactory createDocumentBuilderFactory(int validationMode, boolean namespaceAware);
流程如下:
1 根据DocumentBuilderFactory静态工厂实例化DocumentBuilderFactory对象
2 设置命名空间
3 如果验证模式不等于0,表示需要验证XML,设置验证为true
4 如果等于3,设置验证属性进行验证。验证过程出现异常,直接捕获,并且记录验证失败。
5 返回DocumentBuilderFactory工厂实例对象!
如下的源码我做了注释以及稍微改动!
protected DocumentBuilderFactory createDocumentBuilderFactory
(int validationMode, boolean namespaceAware) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
/** namespaceAware 是否需要设置命名空间*/
factory.setNamespaceAware(namespaceAware);
/**
* validationMode=0 不验证
* validationMode=1 自动验证
* validationMode=2 DTD验证
* validationMode=3 XSD验证
* 从代码可以看出Spring使用XSD验证
*/
if (validationMode != XmlValidationModeDetector.VALIDATION_NONE) {
/** 如果不等于0,表示XML需要验证*/
factory.setValidating(true);
/** 等于3,表示使用XSD验证*/
if (validationMode == XmlValidationModeDetector.VALIDATION_XSD) {
// XSD验证,强制使用命名空间,设置为true
factory.setNamespaceAware(true);
try {
/** 设置XML属性 java XML以及w3c
* SCHEMA_LANGUAGE_ATTRIBUTE=http://java.sun.com/xml/jaxp/properties/schemaLanguage
* XSD_SCHEMA_LANGUAGE=http://www.w3.org/2001/XMLSchema
* */
factory.setAttribute(SCHEMA_LANGUAGE_ATTRIBUTE, XSD_SCHEMA_LANGUAGE);
}
catch (IllegalArgumentException ex) {
System.out.println("验证失败");
}
}
}
return factory;
}
上一篇: XML文档--DTD
下一篇: XML中DTD,XSD的区别与应用