跳转到内容

XQuery/使用 Schematron 进行验证

来自维基教科书,开放的书籍,面向开放的世界

您希望根据一组业务规则检查您的 XML 文档。这些规则可能比单次传递 XML 架构可以执行的规则更复杂。

Schematron 提供了与标准 Schema 不同的验证方法。它不是规定文档的正确形式,而是允许您定义可以根据需要应用的规则。您还可以使用 XPath 表达式在文档的一部分中指定引用文档其他部分的规则。当文档分阶段创建,并且需要在使用数据之前检查特定的业务规则时,这非常有用。

Schematron 也可以与传统的 XML 架构一起工作。您可以使用 XML 架构检查文档的整体结构和数据类型,并使用 Schematron 表达可以用 XPath 规则完成的规则。

Schematron 也是理想的,因为它允许规则设计者为规则指定确切的错误消息。XML 架构错误消息通常不容易被用户理解。

这是一个示例:在发送“学校预订”的确认电子邮件之前,预订必须包含学校/ID、教师的电子邮件地址和预订日期。日期必须在未来。

   let $schema := 
   <sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron" queryBinding="xslt2">
     <sch:title>School-booking Prior to Send-by-email</sch:title>
     <sch:pattern id="Send-email-check">
         <sch:rule context="school/id">
             <sch:assert test=". ne ''">Missing School ID</sch:assert>
         </sch:rule>
         <sch:rule context="school/teacher-email">
             <sch:assert test=". ne ''">Missing Teach-Email</sch:assert>
         </sch:rule>
         <sch:rule context="day">
             <sch:assert test="date">Missing booking Date</sch:assert>
         </sch:rule>
         <sch:rule context="day/date">
             <sch:assert test=". castable as xs:date and xs:date(.) gt current-date()">The Date must be in the future</sch:assert>
         </sch:rule>
     </sch:pattern>
   </sch:schema>

要从 XQuery 应用此架构

  xquery version "1.0"
   let $send-email-validator := 
      transform:transform(
         $schema,
         xs:anyURI("xmldb:///db/iso-schematron-xslt2/iso_svrl_for_xslt2.xsl"),() )
   return transform:transform(
      $the-data,
      $send-email-validator,() )

以及结果(为了清楚起见而编辑)

   <schematron-output  title="School-booking Prior to Send-by-email" >
     <failed-assert test=". ne ''" location="/school-booking[1]/school[1]/teacher-email[1]">
        <text>Missing Teach-Email</svrl:text>
     </failed-assert>
     <failed-assert test=". castable as xs:date and xs:date(.) gt current-date()" location="/school-booking[1]/day[1]/date[1]">
        <text>The Date must be in the future</svrl:text>
     </failed-assert>
   </schematron-output>

结果可用于突出显示错误并向用户显示消息。

在 eXist-db 中设置

[编辑 | 编辑源代码]

我选择了 Schematron 验证的 XSLT 2.0 版本 - 所以 eXist-db 需要安装 Saxon 9。(...)

  1. 获取 iso-schematron-xslt2 并将(解压缩)内容上传到您的数据库。
  2. 在数据库中创建一个架构
  3. 编译并对您的数据运行架构

用于 ISO Schematron 的 XQuery 模块

[编辑 | 编辑源代码]

Jing 只支持 Schematron 1.5。Schematron 的一个更高级的版本是 ISO Schematron,Jing 无法运行它。要使其工作,您必须使用 XSLT“编译”您的 Schematron 规则。

以下是一个执行此编译的示例 XQuery 模块。

module namespace v="http://gspring.com.au/pekoe/validator";

declare variable $v:schematron-compiler := xs:anyURI("xmldb:///db/iso-schematron-xslt2/iso_svrl_for_xslt2.xsl");

(: Call like this: v:validate($xml, xs:anyURI("/db/path/to/schema.sch") ) :)

declare function v:validate($doc as node(), $schematron as xs:anyURI ) {
    let $validator := local:get-compiled-validator($schematron)
    return transform:transform(
        $doc,
        $validator,()
        )
};

 declare function local:get-compiled-validator($schematron-path as xs:anyURI) {
    let $s-path := xs:string($schematron-path)
    let $xsl-path := concat(substring-before($s-path,"."),".xsl")
    return  (: check that the compiled version is up-to-date :)
        if (exists(doc($xsl-path)) and 
            xmldb:last-modified(util:collection-name($xsl-path), util:document-name($xsl-path)) gt 
            xmldb:last-modified(util:collection-name($s-path), util:document-name($s-path))) 
        then doc($xsl-path) 
        else local:compile-schematron($s-path,$xsl-path)
 };
 
 declare function local:compile-schematron($schematron-path, $xsl-path) {
    let $compiled := transform:transform(
                    doc($schematron-path), 
                    $v:schematron-compiler, ())
    let $stored := xmldb:store(util:collection-name($schematron-path), $xsl-path, $compiled)
    return doc($stored)
 };

请注意,xslt 假设包含文件。

华夏公益教科书