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的优点:

  1. XML Schema基于XML,没有专门的语法
  2. XML Schema可以象其他XML文件一样解析和处理
  3. XML Schema比DTD提供了更丰富的数据类型.
  4. XML Schema提供可扩充的数据模型。
  5. XML Schema支持综合命名空间
  6. 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;
   }

 

 

 

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java 中可以使用一些库来实现 JSON 和 XML 文件的验证,比如: 1. JSON 验证器:可以使用 json-schema-validator 库来验证 JSON 文件是否符合指定的 JSON Schema。以下是一个简单的示例: ```java import com.github.fge.jsonschema.core.exceptions.ProcessingException; import com.github.fge.jsonschema.main.JsonSchema; import com.github.fge.jsonschema.main.JsonSchemaFactory; import com.github.fge.jsonschema.core.report.ProcessingReport; import com.github.fge.jsonschema.core.report.ProcessingMessage; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.net.URL; public class JsonValidator { public static void main(String[] args) throws IOException, ProcessingException { // 读取 JSON 文件和 JSON Schema 文件 String jsonData = "{ \"name\": \"John\", \"age\": 30 }"; String schemaData = "{ \"type\": \"object\", \"properties\": { \"name\": { \"type\": \"string\" }, \"age\": { \"type\": \"integer\" } } }"; ObjectMapper mapper = new ObjectMapper(); JsonNode json = mapper.readTree(jsonData); JsonNode schema = mapper.readTree(schemaData); // 创建 JSON Schema 验证器 JsonSchemaFactory factory = JsonSchemaFactory.byDefault(); JsonSchema jsonSchema = factory.getJsonSchema(schema); // 验证 JSON 文件是否符合 JSON Schema ProcessingReport report = jsonSchema.validate(json); // 打印验证结果 if (report.isSuccess()) { System.out.println("JSON 文件符合 JSON Schema!"); } else { for (ProcessingMessage message : report) { System.out.println(message.getMessage()); } } } } ``` 2. XML 验证器:可以使用 javax.xml.validation 包中提供的 API 来验证 XML 文件是否符合指定的 XSD Schema。以下是一个简单的示例: ```java import java.io.File; import javax.xml.XMLConstants; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import javax.xml.validation.Validator; import org.xml.sax.SAXException; public class XmlValidator { public static void main(String[] args) { // 读取 XML 文件和 XSD Schema 文件 File xmlFile = new File("example.xml"); File xsdFile = new File("example.xsd"); try { // 创建 XML 验证SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); Schema schema = factory.newSchema(xsdFile); Validator validator = schema.newValidator(); // 验证 XML 文件是否符合 XSD Schema validator.validate(new StreamSource(xmlFile)); // 打印验证结果 System.out.println("XML 文件符合 XSD Schema!"); } catch (SAXException e) { System.out.println("XML 文件不符合 XSD Schema:" + e.getMessage()); } catch (IOException e) { System.out.println("无法读取 XML 文件或 XSD Schema 文件:" + e.getMessage()); } } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值