`
code727
  • 浏览: 66662 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

JAXP实现Schema和DTD验证

阅读更多

       在JAXP1.3以前的实现中,进行XML的约束验证都是调用SAXParserFactory或DocumentBuilderFactory对象的setValidating(true)方法来处理的。

       这种方式有许多不足的地方,它要求正在被验证的XML实例文档中必须要显示的引入相关的约束(Schema或DTD文件),这无形之中就产生了XML实例文档与约束之间的耦合。尤其在分布式或中间件技术应用中,往往在客户端提供的信息交换实体的描述中,并不一定会引入相关的约束,而在服务端进行实体处理之前又需要验证客户端发送来的实体描述是否合法。因此在这种情况下,采用这种老的验证方式就无法实现这一点。

 

一、 JAXP验证框架

       JAXP1.3以后推出了一个全新的验证框架,其核心的接口和实现类都主要在javax.xml.validation包中,最常用的有如下几个:

       1)SchemaFactory:创建某种模式(Schema)类型的工厂类。其模式类型需要在其静态的工厂方法newInstance(String schemaLanguage)方法的参数中指出,可用于验证的模式类型在XMLContants中有所提供,分别是XMLConstants.W3C_XML_SCHEMA_NS_URI和XMLConstants.RELAXNG_NS_URI。也就是说,SchemaFactory能用于Shchema和RELAX NG验证

       2)Schema:表示某种验证模式的对象;

       3)Validator:验证器。

       结合如上所述的三个核心类,其验证的一般步骤如下:

       1)创建某种模式类型的工厂类;

       2)指定模式的资源并调用工厂对象的newSchema()后获取Schema对象;

       3)从Schema对象中生成验证器;

       4)指定需要被验证的实例资源并调用验证器的validate()方法。

 

       方式一:利用Validator对象进行显示验证

package com.daniele.appdemo.xml.jaxp.validation;

import java.io.File;
import java.io.IOException;

import javax.xml.XMLConstants;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.xml.sax.SAXException;


/**
 * <p>XML Schema约束验证测试类</p> 
 * @author  <a href="mailto:code727@gmail.com">Daniele</a>
 * @version 1.0.0, 2013-7-14
 * @see     
 * @since   AppDemo1.0.0
 */
public class SchemaValidationTest {

	public static void main(String[] args) throws Exception {
		SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
		File schemaSource = new File("resource/xml/schema/schema_test_nns.xsd");
		try {
			Schema schema = factory.newSchema(schemaSource);
			// 从模式中生成验证器
			Validator validator = schema.newValidator();
			// 如果用于验证的Schema文件中定义了命名空间,则被验证的XML实例文件中必须要引用相同的空间
			Source source = new StreamSource(new File("resource/xml/schema/schema_test_copy.xml"));
			validator.validate(source);
			System.out.println("XML有效!");
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} 
	}

}      

 

      除了上述方式外,还可以将Schema对象与某一类型的JAXP解析器工厂(DocumentBuilderFactory或SAXParserFactory)建立联系后, 再让工厂后续创建的解析器在解析XML实例的过程中,隐式的进行验证。

 

       方式二:解析器隐式验证

package com.daniele.appdemo.xml.jaxp.validation;

import java.io.File;
import java.io.IOException;

import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;

import org.xml.sax.SAXException;


/**
 * <p>XML Schema约束验证测试类</p> 
 * @author  <a href="mailto:code727@gmail.com">Daniele</a>
 * @version 1.0.0, 2013-7-14
 * @see     
 * @since   AppDemo1.0.0
 */
public class SchemaValidationTest {

	public static void main(String[] args) throws Exception {
		SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
		File schemaSource = new File("resource/xml/schema/schema_test_nns.xsd");
		try {
			Schema schema = factory.newSchema(schemaSource);
			DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
			builderFactory.setSchema(schema);
			DocumentBuilder builder = builderFactory.newDocumentBuilder();
			builder.parse(new File("resource/xml/schema/schema_test_copy.xml"));
			System.out.println("XML有效!");
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} 
	}

}

二、验证错误后的处理

       在上述方式一中,当执行validate()后,如果发现被验证的实例不符合约束规范,则会抛出SAXException异常,从而被后续对应的catch块所捕获并在控制台中简单的显示出异常信息。如果需要集中处理显示出更多精确详细的异常信息,则直接在这里的catch块中进行显然是不合适的。

       在方式二中更为严重的问题是:当不符合约束规范时,parse()方法只是简单的显示一个错误信息,将不会抛出异常,因此不会被SAXException对应的catch块所捕获,从而仍然会提示“XML有效!”。

       为了解决方式一中集中处理错误和方式二中严重缺陷的问题,这时就需要用到org.xml.sax.ErrorHandler,它是一个接口,其作用在于当进行SAX解析的过程中,如果发生warning、error或

fatalError级别的错误时,则会回调此接口中相关的同名方法,用户需要提供一个实现类,实现对这三种错误类型的处理细节。

package com.daniele.appdemo.xml.sax.handler;

import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

/**
 * <p>SAX错误处理器示例类</p> 
 * @author  <a href="mailto:code727@gmail.com">Daniele</a>
 * @version 1.0.0, 2013-6-18
 * @see     
 * @since   AppDemo1.0.0
 */
public class SAXExampleErrorHandler implements ErrorHandler {

	/**
	 * <p>解析过程中遇到警告性错误时被触发</p> 
	 * @author <a href="mailto:code727@gmail.com">Daniele</a> 
	 * @param exception:SAXParseException对象,封装了异常产生时的所在行号和信息
	 * @throws SAXException:当遇到警告性错误要求停止解析时,可直接向上抛出此异常
	 * @since AppDemo1.0.0 
	 */
	public void warning(SAXParseException exception) throws SAXException {
		StringBuffer message = new StringBuffer();
		message.append("解析到第").append(exception.getLineNumber())
				.append("行时发生如下警告:\n").append("messge:")
				.append(exception.getMessage());
		System.out.println(message);
	}

	/**
	 * <p>解析过程中遇到可恢复性错误(如不符合约束规则)时被触发</p> 
	 * @author <a href="mailto:code727@gmail.com">Daniele</a> 
	 * @param exception:SAXParseException对象,封装了异常产生时的所在行号和信息
	 * @throws SAXException: 当遇到可恢复性错误要求停止解析时,可直接向上抛出此异常
	 * @since AppDemo1.0.0 
	 */
	public void error(SAXParseException exception) throws SAXException {
		StringBuffer message = new StringBuffer();
		message.append("解析到第").append(exception.getLineNumber())
				.append("行时发生如下错误:\n").append("messge:")
				.append(exception.getMessage());
		throw new SAXException(message.toString());
	}

	/**
	 * <p>解析过程中遇到不可恢复的致命错误(如不符合XML文档的基本规则)时被触发</p> 
	 * @author <a href="mailto:code727@gmail.com">Daniele</a> 
	 * @param exception:SAXParseException对象,封装了异常产生时的所在行号和信息
	 * @throws SAXException:当遇到不可恢复的严重错误要求停止解析时,可直接向上抛出此异常
	 * @since AppDemo1.0.0 
	 */
	public void fatalError(SAXParseException exception) throws SAXException {
		StringBuffer message = new StringBuffer();
		message.append("解析到第").append(exception.getLineNumber())
				.append("行时发生如下致命错误:\n").append("messge:")
				.append(exception.getMessage());
		throw new SAXException(message.toString());
	}

}

       这里需要重点关注的是error方法,因为验证错误一般都属于这类级别的。在此方法的最后一步抛出SAXException,其目的在于一旦发生错误就让解析器停止解析过程,从而可以解决方式二所述的缺陷并且可以在SAXException的catch块中捕获自定义的异常信息。

      上述实现类定义好后,就需要在验证或解析之前,设置这个错误处理器,可以设置错误处理器的对象有如下几种:

       1)SchemaFactory;

       2)Validator;

       3)DocumentBuilder;

       4)SAXParser;

       其中,SchemaFactory是全局的,即后续创建的schema所生成的Validator对象都采用这个全局的处理器来处理验证错误时的逻辑。另外,如果是用SAXParser对象来进行,则上述自定义的错误处理器就应该修改为通过继承org.xml.sax.helpers.DefaultHandler的方式来实现,因为它是在调用parse()方法时传递一个DefaultHandler对象来进行的,而DefaultHandler实现了org.xml.sax.ErrorHandler接口。例如:

       schemaFactory.setErrorHandler(new SAXExampleErrorHandler());   或

       saxParser.parse(source,new SAXExampleErrorHandler());

 

三、DTD验证       

SchemaFactory目前并不支持DTD的验证,当我们执行SchemaFactory.newInstance(XMLConstants.XML_DTD_NS_URI)时将会抛出java.lang.IllegalArgumentException。

       对于DTD验证,采用原有的验证方式,启用JAXP相关解析器工厂类的验证功能即可。

package com.daniele.appdemo.xml.jaxp.validation;

import java.io.File;
import java.io.IOException;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.SAXException;

import com.daniele.appdemo.xml.sax.handler.SAXExampleHandler;


/**
 * <p>XML DTD约束验证测试类</p> 
 * @author  <a href="mailto:code727@gmail.com">Daniele</a>
 * @version 1.0.0, 2013-7-16
 * @see     
 * @since   AppDemo1.0.0
 */
public class DTDValidationTester {

   public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException {
		
	SAXParserFactory factory = SAXParserFactory.newInstance();
	//  这里只需开启相关解析工厂的验证功能,并在后续的解析过程中隐式的执行验证
	factory.setValidating(true);
	SAXParser parser = factory.newSAXParser();
	parser.parse(new File("resource/xml/dtd/dtd_test.xml"), new SAXExampleHandler());
   }

}

       在XML1.0的规范中,没有考虑过要使用DTD之外的方式进行验证。即XML1.0规范硬性规定使用DTD进行验证,文档中必须使用DOCTYPE引入要用于验证的DTD文件。

 

分享到:
评论

相关推荐

    JAXP数据验证引擎 Serene

    其中,JAXP的数据验证引擎是用于确保XML文档符合特定XML Schema(XSD)或DTD(文档类型定义)的重要组成部分。Serene是一款高级的、高性能的JAXP数据验证引擎,专注于提供精确且可扩展的XML数据验证服务。 Serene的...

    基于Java的实例开发源码-JAXP数据验证引擎 Serene.zip

    - 了解XML基础知识,包括XML结构、DTD和XML Schema。 - 掌握Java编程,特别是JAXP API的使用。 - 熟悉Ant构建工具,能够阅读和理解`build.xml`脚本。 - 分析`testSuite`中的测试用例,理解Serene的验证过程。 ...

    基于Java的实例源码-JAXP数据验证引擎 Serene.zip

    2. **XML数据验证**: 数据验证是确保XML文档符合预定义的结构规则(如DTD、XML Schema或RELAX NG)的过程,以保证数据的准确性和一致性。 3. **Serene**: Serene作为一个高级的XML数据验证引擎,可能提供了更高级的...

    Working with XML

    JAXP支持XML Schema和DTD(Document Type Definition)验证。XML Schema是W3C推荐的更现代的验证方式,提供更丰富的数据类型和复杂结构。DTD是较早的验证机制,功能相对简单。通过`SchemaFactory`和`...

    Xerces-J-src.1.4.3.zip

    例如,`org.apache.xerces.impl.dv.xs`和`org.apache.xerces.impl.xs`包提供了扩展XML Schema验证的接口和实现。 与Hibernate的关联可能表明Xerces-J在ORM(对象关系映射)框架中的应用。在Hibernate中,XML配置...

    The Java XML Validation API

    而XML验证则是确保XML文档符合预定义的结构规则,如XML Schema或DTD(Document Type Definition),以保证数据的准确性和一致性。 Java的XML Validation API允许开发者集成XML验证功能到他们的应用程序中,以检查...

    Xerces-J-bin.1.4.4.zip

    Xerces-J作为JAXP的实现,可以被任何支持JAXP的Java应用程序使用,进行XML解析、验证和转换。 Xerces-1_4_4是这个压缩包内的主要文件,它可能包含了以下组件: - 解析器:用于解析XML文档,验证其是否符合XML规范。...

    dom4j解析XML的两个JAR包(dom4j-1.6.1.jar 和 jaxen.jar)

    4. **XML Schema和DTD处理**:DOM4J可以验证XML文档是否符合指定的XML Schema或者DTD,确保数据的准确性和一致性。 5. **便捷的API**:DOM4J的API设计得直观易用,使得XML编程变得更加友好,降低了学习曲线。 ...

    xml,sax,jdom,dom4j完全讲解

    XML作为数据交换和存储的标准,配合不同的解析策略(如SAX和DOM)以及验证工具(如DTD和Schema),在各种IT应用中广泛使用。理解并掌握XML的基础知识,以及与其相关的API如JDOM和DOM4J,对于进行XML处理和开发具有...

    基于java的XML解析器 Xerces.zip

    这个解析器不仅能够解析XML文档,还能验证文档是否符合其指定的Schema或DTD。 在Xerces中,解析XML有多种方式,包括DOM、SAX和StAX。DOM解析器将整个XML文档加载到内存中,形成一个树形结构,便于进行遍历和操作。...

    Java中关于XML的API

    - **DTD和Schema**:使用DTD或XML Schema定义数据结构,并通过binding schema来指定Java类与XML元素之间的映射关系。 - **动态生成**:根据DTD或Schema自动生成Java类。 然而,JAXB的一个局限性在于,如果XML结构...

    Xerces-J-tools.2.1.0.zip

    它提供了许多特性,例如命名空间支持、DTD验证、实体解析和XML Schema验证。此外,Xerces还包含了对XPath和XSLT的支持,使其成为一个功能强大的XML处理工具集。 压缩包中的"tools"目录可能包含了用于开发和测试的...

    xml终极教程

    5. **XML与Java**:Java提供了丰富的API来处理XML,如JAXB(Java Architecture for XML Binding)用于对象与XML之间的绑定,SAX和DOM的Java实现,以及JAXP(Java API for XML Processing)提供统一的接口处理XML。...

    使用Java技术的XML高级开发

    XML Schema和Document Type Definition(DTD)用于定义XML文档的结构和约束。Java的javax.xml.validation包提供了对XML Schema的支持,帮助开发者验证XML文档是否符合规定。 七、Spring框架中的XML配置 Spring框架...

    XML课件加例子源码

    紧接着,“Chapter3 XML底层数据结构—XML Schema.ppt”将引入更现代的XML Schema,它提供了一种更为强大且灵活的结构定义工具,支持数据类型和复杂的数据模型,可以替代DTD来验证XML文档。 “Chapter4 XML样式单...

    XML基础实例

    实践是学习的最佳途径,所以尝试编写XML文档,使用DTD或Schema进行验证,用Java实现DOM操作,利用XSLT进行转换,甚至在服务器端利用DSO进行动态处理,这些都是提升XML技能的有效方法。在实际项目中应用这些知识,你...

    xerces-j.apiDoc

    3. **DTD(Document Type Definition)和XML Schema处理**:Xerces-J不仅支持传统的DTD验证,还支持更强大的XML Schema验证,确保XML文档遵循预定义的结构和约束。 4. **XPath和XSLT**:Xerces-J集成了XPath引擎,...

    XML解析器 Xerces

    5. **XML Schema支持**:除了传统的DTD(Document Type Definition),Xerces还支持更强大的XML Schema,用于验证XML文档的结构和数据类型。 6. **API**:Xerces提供了丰富的API,包括SAX(Simple API for XML)、...

    Java and XML, 3rd Edition

    书中的主题如下: *XML基础,包括DTD、命名空间(namespace)、XML Schema和数据格式转换 (Transformation) *SAX应用程序编程接口,包括处理器接口、过滤器接口和写出接口 *DOM应用程序编程接口,...

Global site tag (gtag.js) - Google Analytics