`
marb
  • 浏览: 422267 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

schema学习系列五: schema校验

阅读更多

检查文档是否遵循了模式中规定的规则。不同的解析器和工具支持不同的模式语言如  DTD W3C XML Schema  语言、 RELAX NG   Schematron Java 5™  增加了统一的验证应用程序编程接口( API ),可以 把文档和用这种或那种语言编写的模式作比较。了解这种  XML  验证  API

验证是一种强大的工具。它可以快速检查输入是否大体上符合预期的形式,立刻拒绝与处理目标相距甚远的文档。如果数据中存在问题,早发现要比晚发现好。  

于可扩展标记语言( XML )来说,验证一般意味着用各种模式语言为文档内容编写详细的规范,这些语言包括万维网联盟( W3C )的  XML Schema Language (XSD) RELAX NG 、文档类型定义( DTD )和  Schematron  等。有时候验证在解析的同 时进行,有时候在解析完成后立刻进行。但一般在对输入的其他处理之前完成。(这一段描述只是粗略来说,因为存在例外。)  

直到最近,程序 请求验证的具体应用程序编程接口( API )还随着模式语言和解析器的不同而不同。 DTD   XSD   Simple API for XML  (SAX) 、文档对象模型( DOM )和  Java™ API for XML Processing (JAXP)  常见的配置选项。 RELAX NG  需要自定义的库和  API Schematron  可以使用  Transformations API for XML(TrAX) ,还有其他模式也要求 程序员学习更多的  API ,尽管执行的操作基本相同。  

Java 5 
引入了  javax.xml.validation  包,提供了独立于模式语言的验证服务接口。这个包也可用于  Java 1.3  及更高版本,不过要单独安装  JAXP 1.3 。其他产品中, Xerces 2.8  包含了这个库的实现。  

验证

javax.xml.validation API 
使用三个类来验证文档: SchemaFactory Schema   Validator 。还大量使用了  TrAX   javax.xml.transform.Source  接口来表示  XML  文档。简言之, SchemaFactory  读取模式文档(通常是  XML  文件)并创建  Schema  对象。 Schema  创建一个  Validator  对象。最后, Validator  对象验证表示为  Source   XML  文档。  

清单  1.  验证可扩展超文本标记语言( XHTML )文档

import java.io.*;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.*;
import org.xml.sax.SAXException;

public class DocbookXSDCheck {

    public static void main(String[] args) throws SAXException, IOException {

        // 1. Lookup a factory for the W3C XML Schema language
        SchemaFactory factory = 
            SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
        
        // 2. Compile the schema. 
        // Here the schema is loaded from a java.io.File, but you could use 
        // a java.net.URL or a javax.xml.transform.Source instead.
        File schemaLocation = new File("/opt/xml/docbook/xsd/docbook.xsd");
        Schema schema = factory.newSchema(schemaLocation);
    
        // 3. Get a validator from the schema.
        Validator validator = schema.newValidator();
        
        // 4. Parse the document you want to check.
        Source source = new StreamSource(args[0]);
        
        // 5. Check the document
        try {
            validator.validate(source);
            System.out.println(args[0] + " is valid.");
        }
        catch (SAXException ex) {
            System.out.println(args[0] + " is not valid because ");
            System.out.println(ex.getMessage());
        }  
        
    }

} 
 


下面是用捆绑到  Java 2 Software Development Kit (JDK) 5.0   Xerces  版本检查一个无效文档时的典型输出。  

file:///Users/elharo/CS905/Course_Notes.xml is not valid because cvc-complex-type.2.3: Element 'legalnotice' cannot have character [children], because the type's content type is element-only. 
改变验证所依据的模式、要验证的文档甚至使用的模式语言都很简单。但无论什么情况,验证都需要经过下列五个步骤:  

1. 为编写模式所用的语言加载一个模式工厂。  
2. 编译源文件中的模式。  
3. 用编译后的模式创建一个验证程序。  
4. 为需要验证的文档创建  Source  对象。 StreamSource  通常最简单。  
5. 验证输入的源文档。如果文档无效, validate()  方法将抛出  SAXException
。否则什么也不显示。  
可以反复使用同一个验证程序和同一个模式多次。但是所有类都不是线程安全的或者可重入的。如果用多个线程同时验证,一定要保证每个线程有自己的  Validator   Schema  对象。  

用文档指定的模式验证

有些文档指定了希望作为验证基础的模式,一般使用  xsi:noNamespaceSchemaLocation  /  xsi:schemaLocation  属性来指定,比如:  

<document xmlns:xsi="http: www.w3.org="" 2001="" xmlschema-instance="">
  xsi:noNamespaceSchemaLocation="http://www.example.com/document.xsd">
  ... 

 
如果创建的模式没有指定  URL 、文件或者源,则  Java  语言就会创建一个这样的东西,用于在要验证的文档中查找应该使用的模式。比如:  

SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
Schema schema = factory.newSchema();

 

不过通常不希望这样做。一般应该由文档的消费者而不是生产者选择模式。另外,这种方法仅适用于  XSD 。其他模式语言都需要明确指定模式的位置。

抽象工厂

SchemaFactory 
是一个抽象工厂。抽象工厂设计模式使得这种  API  能够支持多种不同的模式语言和对象模型。一种实现通常只能支持多种语言和模型的一部分。但是,一旦掌 握了用  RELAX NG  模式(比方说)验证  DOM  文档的  API ,就能用相同的  API   W3C  模式验证  JDOM  文档。  

比如,清单  2  中的程序使用  DocBook   RELAX NG  模式验证  DocBook  文档。基本上与   清单  1  相同。惟一的变化是模式位置和标识模式语言的  URL  


清单  2.  使用  RELAX NG  验证  DocBook  文档

import java.io.*;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.*;
import org.xml.sax.SAXException;

public class DocbookRELAXNGCheck {

    public static void main(String[] args) throws SAXException, IOException {

        // 1. Specify you want a factory for RELAX NG
        SchemaFactory factory 
         = SchemaFactory.newInstance("http://relaxng.org/ns/structure/1.0");
        
        // 2. Load the specific schema you want. 
        // Here I load it from a java.io.File, but we could also use a 
        // java.net.URL or a javax.xml.transform.Source
        File schemaLocation = new File("/opt/xml/docbook/rng/docbook.rng");
        
        // 3. Compile the schema.
        Schema schema = factory.newSchema(schemaLocation);
    
        // 4. Get a validator from the schema.
        Validator validator = schema.newValidator();
        
        // 5. Parse the document you want to check.
        String input 
         = "file:///Users/elharo/Projects/workspace/CS905/build/Java_Course_Notes.xml";
        
        // 6. Check the document
        try {
            validator.validate(source);
            System.out.println(input + " is valid.");
        }
        catch (SAXException ex) {
            System.out.println(input + " is not valid because ");
            System.out.println(ex.getMessage());
        }  
        
    }

} 
 


如果用普通的  Sun JDK  不增加其他库,运行该程序时可能会看到如下所示的结果:  

Exception in thread "main" java.lang.IllegalArgumentException: 
http://relaxng.org/ns/structure/1.0
    at javax.xml.validation.SchemaFactory.newInstance(SchemaFactory.java:186)
    at DocbookRELAXNGCheck.main(DocbookRELAXNGCheck.java:14) 


是因为, JDK  本身没有带  RELAX NG  验证程序。如果不能识别模式语言, SchemaFactory.newInstance()  就会抛出  IllegalArgumentException 。但是如果安装了  RELAX NG  库,比如  Jing   JAXP 1.3  适配程序,就会与  W3C  模式显示同样的结果。  

确定模式语言

javax.xml.constants 
类定义了几个常量来标识模式语言:  

XMLConstants.W3C_XML_SCHEMA_NS_URI
http://www.w3.org/2001/XMLSchema 
XMLConstants.RELAXNG_NS_URI
http://relaxng.org/ns/structure/1.0 
XMLConstants.XML_DTD_NS_URI
http://www.w3.org/TR/REC-xml 

是一个不完全的列表。实现可以随时向该表增加其他  URL  来标识其他的模式语言。 URL  通常是模式语言的名称空间统一资源标识符( URI )。比如, URL http://www.ascc.net/xml/schematron  标识了  Schematron  模式。  

Sun 
 JDK 5  仅支持  XSD  模式。虽然也支持  DTD  验证,但是它不能通过  javax.xml.validation API  使用。对于  DTD ,必须使用常规的  SAX XMLReader  类。不过可以另外安装支持不同模式语言的其他库。  

如何定位模式工厂

Java 
编程语言没有限制模式工厂只能有一种。可以把标识某种模式语言的  URI  传递给  SchemaFactory.newInstance() ,它按照下列顺序搜索匹配的工厂:

 "javax.xml.validation.SchemaFactory:schemaURL"  系统属性命名的类  
 $java.home/lib/jaxp.properties  文件中的  "javax.xml.validation.SchemaFactory:schemaURL"  属性命名的类  
在任何  Java Archive (JAR)  文件的  META-INF/services  目录中发现的  javax.xml.validation.SchemaFactory  服务提供程序  
平台默认的  SchemaFactory JDK 5  中为  com.sun.org.apache.xerces.internal.jaxp.validation.xs.SchemaFactoryImpl 
支持自定义的模式语言和对应的验证程序,只需要编写  SchemaFactory Schema   Validator (它们知道如何处理模式语言)的 子类。然后将您的  JAR  文件安装到上述四个位置中的一个。对于添加与  W3C XML Schema  语言这类声明性语言相比更适合用  Java  类的图灵完整语言检查的约束,这一点很重要。可以定义一种微模式语言,编写简单的实现,然后将其插入到验证层。  



错误处理

式的默认响应方式是,如果遇到问题则抛出  SAXException ,否则什么也不做。但是,可以提供  SAX ErrorHandler  来接收关于文 档问题的更详尽的信息。比方说,假设要记录所有验证错误,但又不希望遇到错误时停止处理。可以安装一个像   清单  3  那样的错误处理程序。  


清单  3.  使用  RELAX NG  验证  DocBook  文档

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

public class ForgivingErrorHandler implements ErrorHandler {

    public void warning(SAXParseException ex) {
        System.err.println(ex.getMessage());
    }

    public void error(SAXParseException ex) {
        System.err.println(ex.getMessage());
    }

    public void fatalError(SAXParseException ex) throws SAXException {
        throw ex;
    }

} 
 




要安装该错误处理程序,需要创建它的一个实例并传递给  Validator   setErrorHandler()  方法:  

  ErrorHandler lenient = new ForgivingErrorHandler();
  validator.setErrorHandler(lenient); 

模式扩充

些模式不仅仅执行验证。除了用是否回答文档有效与否的问题外,还为文档补充   其他信息。比方说,可以提供默认的属性值。还可以给元素或属性赋予  int   gYear  这样的类型。验证程序可以创建这种补充了类型信息的文档,并写入  javax.xml.transform.Result  对象。只需要 传递  Result  作为验证的第二个参数。比如,清单  4  在验证输入文档的同时,还创建结合有模式输入的扩展后的  DOM  文档。  


清单  4.  用模式扩充文档

import java.io.*;
import javax.xml.transform.dom.*;
import javax.xml.validation.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.SAXException;

public class DocbookXSDAugmenter {

    public static void main(String[] args) 
      throws SAXException, IOException, ParserConfigurationException {

        SchemaFactory factory 
         = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
        File schemaLocation = new File("/opt/xml/docbook/xsd/docbook.xsd");
        Schema schema = factory.newSchema(schemaLocation);
        Validator validator = schema.newValidator();
        
        DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
        domFactory.setNamespaceAware(true); // never forget this
        DocumentBuilder builder = domFactory.newDocumentBuilder();
        Document doc = builder.parse(new File(args[0]));
        
        DOMSource source = new DOMSource(doc);
        DOMResult result = new DOMResult();
        
        try {
            validator.validate(source, result);
            Document augmented = (Document) result.getNode();
            // do whatever you need to do with the augmented document...
        }
        catch (SAXException ex) {
            System.out.println(args[0] + " is not valid because ");
            System.out.println(ex.getMessage());
        }  
        
    }

} 

 


个过程的输入和输出都有一定的限制。不能用于所有的流输入和输出。 SAX  源可以扩展成  SAX  结果, DOM  源扩展成  DOM  结果,但是  SAX  源不能扩展成  DOM  结果,反之亦然。如果需要这么做,首先扩展成匹配的结果: SAX   SAX  DOM   DOM ,然后使用  TrAX  的恒等 转换改变模型。  

但不建议使用这种技术。将文档需要的全部信息放在一个实例中,要比分解成实例和模式更可靠。您可以验证,但并非所有的人都能验证。  


类型信息

W3C XML Schema Language 
在很大程度上依赖于类型   这一概念。元素和属性被声明为  int double date duration person PhoneNumber  其他您能够想到的类型。 Java Validation API  提供了一种手段来报告这些类型,虽然令人吃惊的是该特性独立于包的其他部分。  

型用  org.w3c.dom.TypeInfo  对象表示。这个简单的接口通过   清单  5  来说明,它给出了类型的本地名和名称空间  URI 。还可以告 诉您它是否派生自其他类型。除此以外,理解这种类型就是您的程序的任务了。 Java  语言没有说明它的含义,或者将其转化成  double   java.util.Date  这样的  Java  类型。  


清单  5. DOM TypeInfo  接口

package org.w3c.dom;

public interface TypeInfo {

  public static final int DERIVATION_RESTRICTION;
  public static final int DERIVATION_EXTENSION;
  public static final int DERIVATION_UNION;

  public String  getTypeName();
  public String  getTypeNamespace()
  public boolean isDerivedFrom(String namespace, String name, int derivationMethod);

} 
 


获得  TypeInfo  对象,需要向  Schema  对象请求  ValidatorHandler  而不是  Validator ValidatorHandler  实现了  SAX   ContentHandler  接口。然后将该处理程序安装到  SAX  解析器中。  

还要在  ValidatorHandler (不是解析器)中安装您自己的  ContentHandler ValidatorHandler  将把扩展的事件转发到您的  ContentHandler  

ValidatorHandler 
提供了  TypeInfoProvider ContentHandler  可以随时调用查看当前元素或其属性的类型。它还可以告诉您该属性是否是  ID ,属性是在文档中明确指定的还是模式中的默认值。清单  6  对这个类作了概括。  


清单  6. TypeInfoProvider 

package javax.xml.validation;

public abstract class TypeInfoProvider {

  public abstract TypeInfo getElementTypeInfo();
  public abstract TypeInfo getAttributeTypeInfo(int index);
  public abstract boolean  isIdAttribute(int index);
  public abstract boolean  isSpecified(int index);

} 

 

最后,用  SAX XMLReader  解析文档。清单  7  是一个简单的程序,它利用了所有这些类和接口打印出文档所有元素的类型名。  


清单  7.  列举元素类型

import java.io.*;
import javax.xml.validation.*;

import org.xml.sax.*;
import org.xml.sax.helpers.*;

public class TypeLister extends DefaultHandler {

    private TypeInfoProvider provider;
    
    public TypeLister(TypeInfoProvider provider) {
        this.provider = provider;
    }

    public static void main(String[] args) throws SAXException, IOException {

        SchemaFactory factory 
         = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
        File schemaLocation = new File("/opt/xml/docbook/xsd/docbook.xsd");
        Schema schema = factory.newSchema(schemaLocation);
    
        ValidatorHandler vHandler = schema.newValidatorHandler();
        TypeInfoProvider provider = vHandler.getTypeInfoProvider();
        ContentHandler   cHandler = new TypeLister(provider);
        vHandler.setContentHandler(cHandler);
        
        XMLReader parser = XMLReaderFactory.createXMLReader();
        parser.setContentHandler(vHandler);
        parser.parse(args[0]);
        
    }
    
    public void startElement(String namespace, String localName,
      String qualifiedName, Attributes atts) throws SAXException {
        String type = provider.getElementTypeInfo().getTypeName();
        System.out.println(qualifiedName + ": " + type);
    }

} 
 


下面列出了对典型的  DocBook  文档运行上述代码的结果的开始部分:  

book: #AnonType_book
title: #AnonType_title
subtitle: #AnonType_subtitle
info: #AnonType_info
copyright: #AnonType_copyright
year: #AnonType_year
holder: #AnonType_holder
author: #AnonType_author
personname: #AnonType_personname
firstname: #AnonType_firstname
othername: #AnonType_othername
surname: #AnonType_surname
personblurb: #AnonType_personblurb
para: #AnonType_para
link: #AnonType_link 


可以看到, DocBook  模式赋予大多数元素以匿名的复杂类型。显然,结果会随着模式的不同而变化。  

结束语

果所有人都说同一种语言,世界会变得更加单调。如果只有一种编程语言可以选择,程序员也会感到不高兴。不同的语言更适合不同的任务,有些任务需要不只一种 语言。 XML  模式也不例外。您可以从各种各样的模式语言中选择。拥有了  Java 5  及其  javax.xml.validation ,就能用一种  API  处理所有这些模式语言。 </document xmlns:xsi="http:>

分享到:
评论

相关推荐

    schema校验问题

    8. **错误处理和调试**:在遇到schema校验失败时,学习如何解读错误信息,定位问题所在,以及调试和修复是十分重要的技能。 9. **最佳实践**:在设计schema时,应遵循简洁、可扩展和易于理解的原则,同时考虑未来...

    Schema校验java

    在Java开发中,Schema校验是一项重要的任务,它主要用于确保数据符合特定的结构或格式,以保证数据的准确性和一致性。Schema通常用于XML、JSON等数据格式,它定义了一组规则,用来验证输入的数据是否符合这些规则。...

    JSON Schema 校验库——json-schema-validator(java版本).rar

    在给定的压缩包中,`JSON Schema 校验库——json-schema-validator(java版本).pdf`可能是该库的使用指南或API文档,可以帮助开发者深入理解如何在Java项目中有效利用`json-schema-validator`进行JSON数据验证。...

    IEC61850 SCL文件Schema校验

    IEC61850 SCL文件Schema校验 1、支持Schema1.0和Schema2.0版本 2、支持自定义Schema版本 3、支持信息输出,格式包括PDF,CSV,TXT

    JSON Schema验证规范-中文版

    #### 五、数字型验证关键字 针对数字类型的实例,有以下关键字用于验证: - `multipleOf`:实例值必须是给定数值的倍数。 - `maximum`:实例值的最大允许值。 - `exclusiveMaximum`:实例值不能等于最大允许值。 - ...

    schema校验所需要的jar包

    在IT行业中,尤其是在软件开发和数据处理领域,schema校验是一项至关重要的任务。它涉及到对XML文档或数据结构的有效性检查,确保它们符合预定义的规则和格式,这些规则通常以XML Schema(XSD)的形式存在。XML ...

    添加jPDL4Schema校验.doc

    jPDL4Schema 校验 jPDL(Java Process Definition Language)是一种流程定义语言,由 jBPM(Java Business Process Management)开发。jPDL 用于描述业务流程,并以 XML 文件的形式存储。在 jBPM3 中,需要两个文件...

    Java通过XML Schema校验XML

    ### Java通过XML Schema校验XML #### 背景与挑战 XML(可扩展标记语言)作为一种标准的数据交换格式,在Web服务、配置文件以及其他多种应用领域有着广泛的应用。随着XML的普及,对于XML数据有效性的校验变得越来越...

    JSON-Schema定义规范

    ### JSON-Schema定义规范 #### 前言 在现代软件开发中,数据交换与处理是必不可少的一部分。随着Web服务的普及以及API的发展,JSON(JavaScript Object Notation)作为一种轻量级的数据交换格式,因其简单易读且...

    rapidjson schema 校验

    总结来说,RapidJSON的JSON Schema校验功能结合C++和Linux环境,为我们提供了一种强大的方式来验证和约束JSON数据。通过处理远程$ref,我们可以将Schema设计得更加灵活和模块化。对于大型项目而言,这种能力至关重要...

    通过Schema验证XML格式是否正确

    5. **XmlSchema类**:该类用于加载和处理XML Schema文件,可以创建一个XmlSchema对象来读取XSD文件,并构建出XML文档必须遵循的结构模型。 6. **XmlDocument类**:此类代表XML文档,提供加载XML数据、验证文档以及...

    XML Schema

    - **数据一致性**:通过XML Schema,可以定义一组固定的模式来校验XML文档,确保其符合特定的要求。 - **提高数据质量**:通过对文档中的元素进行严格定义,减少错误和不一致的可能性。 - **增强应用程序集成能力...

    php json schema 参数校检库

    这类库通常提供一系列函数或类,可以解析JSON Schema定义,并对输入的JSON数据进行验证,返回是否符合规则的结果。 描述中提到,这个库是精简版的,意味着它专注于核心的校验功能,不包含不必要的额外组件,旨在...

    前端开源库-js-schema

    `js-schema` 是一个专门用于JavaScript对象验证的开源库,它为开发者提供了简单且直观的API,使得在前端进行数据校验变得更加便捷。本文将深入探讨`js-schema`的核心功能、使用方法以及其在实际开发中的应用场景。 ...

    前端开源库-schema-inspector

    2. **API数据校验**:在接收到服务器响应或发送请求前,验证数据的正确性。 3. **数据迁移**:在数据迁移过程中,确保源数据符合目标系统的要求。 4. **数据处理**:在处理用户上传的JSON数据时,确保其结构合法。 ...

    schema-validator:针对预定义架构的 YAMLJSON 文件的架构验证实用程序

    用法它的方法validateSchema可以被导入和使用,如下所示: const validateSchema = require ( 'yaml-schema-validator' )// validate a json OR yml filevalidateSchema ( 'path/to/target-file.yml' , { ...

    php使用json-schema模块实现json校验示例

    本文实例讲述了php使用json-schema模块实现json校验。分享给大家供大家参考,具体如下: 客户端和服务端的http信息传递,采用json几乎成了标配。json格式简单,易于处理,不过由于没有格式规定,无法校验。 好在php...

    java中实现xmlschema验证文件借鉴.pdf

    XML Schema文档使用XML语法定义了一系列规则,这些规则描述了有效XML文档应该具有的元素、属性、数据类型以及它们之间的关系。在处理XML数据时,进行XML Schema验证是至关重要的步骤,它可以帮助开发者检测并防止不...

    schema-form-components:json schema form 表单通用组件

    2. **数据验证**:内置JSON Schema的验证规则,自动进行数据校验,确保用户输入的数据符合业务要求。 3. **丰富的组件库**:提供多种常见的表单组件,如输入框、选择器、日期选择器等,满足不同类型的表单需求。 4. ...

Global site tag (gtag.js) - Google Analytics