2016-03-08 40 views
1

目前我正在使用PHSchematron库来验证Java中的schematron。如果我将<sch:p>标记作为<sch:pattern>的子标记,那么它会抛出NullPointerException,因为SchematronOutputType为null。 我试图把<sch:p>作为<sch:schema><sch:rule>孩子没有任何问题,尽管XSD表示该p元素可能是schema孩子,phasepattern。 我不确定问题在于PHSchematron的实施与否。 我假设xmlns:sch指向1.5 schematron XSD版本。PHSchematron无法通过`pattern`元素中的`p`元素验证schematron文件

schematron_1.5.xsd:

<?xml version="1.0" encoding="UTF-8"?> 
<!-- schemaVersion of 2001/02/15 --> 
<xs:schema xmlns:sch="http://www.ascc.net/xml/schematron" xmlns="http://www.ascc.net/xml/schematron" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.ascc.net/xml/schematron" version="+//IDN sinica.edu.tw//SGML W3C XML Schema for Schematron 1.5//EN"> 
    <xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2001/xml.xsd"> 
     <xs:annotation> 
      <xs:documentation> 
       Get access to the xml: attribute groups for xml:lang 
      </xs:documentation> 
     </xs:annotation> 
    </xs:import> 
    <xs:annotation> 
     <xs:documentation source="http://www.ascc.net/xml/resource/schematron/schematron.html" xml:lang="en"/> 
    </xs:annotation> 
    <xs:element name="active"> 
     <xs:complexType mixed="true"> 
      <xs:choice minOccurs="0" maxOccurs="unbounded"> 
       <xs:element ref="sch:dir"/> 
       <xs:element ref="sch:emph"/> 
       <xs:element ref="sch:span"/> 
      </xs:choice> 
      <xs:attribute name="pattern" type="xs:IDREF" use="required"/> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="assert"> 
     <xs:complexType mixed="true"> 
      <xs:choice minOccurs="0" maxOccurs="unbounded"> 
       <xs:element ref="sch:name"/> 
       <xs:element ref="sch:emph"/> 
       <xs:element ref="sch:dir"/> 
       <xs:element ref="sch:span"/> 
       <xs:any namespace="##other" processContents="lax"/> 
      </xs:choice> 
      <xs:attribute name="test" type="xs:string" use="required"/> 
      <xs:attribute name="role" type="xs:NMTOKEN"/> 
      <xs:attribute name="id" type="xs:string"/> 
      <xs:attribute name="diagnostics" type="xs:IDREFS"/> 
      <xs:attribute name="icon" type="xs:anyURI"/> 
      <xs:attribute name="subject" type="xs:string" default="."/> 
      <xs:attribute ref="xml:lang"/> 
      <xs:anyAttribute namespace="##other" processContents="lax"/> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="diagnostic"> 
     <xs:complexType mixed="true"> 
      <xs:choice minOccurs="0" maxOccurs="unbounded"> 
       <xs:element ref="sch:value-of"/> 
       <xs:element ref="sch:emph"/> 
       <xs:element ref="sch:dir"/> 
       <xs:element ref="sch:span"/> 
       <xs:any namespace="##other" processContents="lax"/> 
      </xs:choice> 
      <xs:attribute name="id" type="xs:ID" use="required"/> 
      <xs:attribute name="icon" type="xs:anyURI"/> 
      <xs:attribute ref="xml:lang"/> 
      <xs:anyAttribute namespace="##other" processContents="lax"/> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="diagnostics"> 
     <xs:complexType> 
      <xs:sequence> 
       <xs:element ref="diagnostic" minOccurs="0" maxOccurs="unbounded"/> 
      </xs:sequence> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="dir"> 
     <xs:complexType> 
      <xs:simpleContent> 
       <xs:extension base="xs:string"> 
        <xs:attribute name="value"> 
         <xs:simpleType> 
          <xs:restriction base="xs:NMTOKEN"> 
           <xs:enumeration value="ltr"/> 
           <xs:enumeration value="rtl"/> 
          </xs:restriction> 
         </xs:simpleType> 
        </xs:attribute> 
       </xs:extension> 
      </xs:simpleContent> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="emph" type="xs:string"/> 
    <xs:element name="extends"> 
     <xs:complexType> 
      <xs:attribute name="rule" type="xs:string" use="required"/> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="key"> 
     <xs:complexType> 
      <xs:attribute name="name" type="xs:NMTOKEN" use="required"/> 
      <xs:attribute name="path" type="xs:string" use="required"/> 
      <xs:attribute name="icon" type="xs:anyURI"/> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="name"> 
     <xs:complexType> 
      <xs:attribute name="path" type="xs:string" default="."/> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="ns"> 
     <xs:complexType> 
      <xs:attribute name="uri" type="xs:anyURI" use="required"/> 
      <xs:attribute name="prefix" type="xs:NCName"/> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="p"> 
     <xs:complexType mixed="true"> 
      <xs:choice minOccurs="0" maxOccurs="unbounded"> 
       <xs:element ref="sch:dir"/> 
       <xs:element ref="sch:emph"/> 
       <xs:element ref="sch:span"/> 
      </xs:choice> 
      <xs:attribute name="id" type="xs:string"/> 
      <xs:attribute name="class" type="xs:string"/> 
      <xs:attribute name="icon" type="xs:anyURI"/> 
      <xs:attribute ref="xml:lang"/> 
      <xs:anyAttribute namespace="##other" processContents="lax"/> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="pattern"> 
     <xs:complexType> 
      <xs:sequence> 
       <xs:element ref="p" minOccurs="0" maxOccurs="unbounded"/> 
       <xs:element ref="sch:rule" maxOccurs="unbounded"/> 
      </xs:sequence> 
      <xs:attribute name="name" type="xs:string" use="required"/> 
      <xs:attribute name="see" type="xs:anyURI"/> 
      <xs:attribute name="id" type="xs:string"/> 
      <xs:attribute name="icon" type="xs:anyURI"/> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="phase"> 
     <xs:complexType> 
      <xs:sequence> 
       <xs:element ref="sch:p" minOccurs="0" maxOccurs="unbounded"/> 
       <xs:element ref="sch:active" maxOccurs="unbounded"/> 
      </xs:sequence> 
      <xs:attribute name="id" type="xs:string" use="required"/> 
      <xs:attribute name="fpi" type="xs:string"/> 
      <xs:attribute name="icon" type="xs:anyURI"/> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="report"> 
     <xs:complexType mixed="true"> 
      <xs:choice minOccurs="0" maxOccurs="unbounded"> 
       <xs:element ref="sch:name"/> 
       <xs:element ref="sch:emph"/> 
       <xs:element ref="sch:dir"/> 
       <xs:element ref="sch:span"/> 
       <xs:any namespace="##other" processContents="lax"/> 
      </xs:choice> 
      <xs:attribute name="test" type="xs:string" use="required"/> 
      <xs:attribute name="role" type="xs:NMTOKEN"/> 
      <xs:attribute name="id" type="xs:string"/> 
      <xs:attribute name="diagnostics" type="xs:IDREFS"/> 
      <xs:attribute name="icon" type="xs:anyURI"/> 
      <xs:attribute name="subject" type="xs:string" default="."/> 
      <xs:attribute ref="xml:lang"/> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="rule"> 
     <xs:complexType> 
      <xs:choice maxOccurs="unbounded"> 
       <xs:element ref="sch:assert"/> 
       <xs:element ref="sch:report"/> 
       <xs:element ref="sch:key"/> 
       <xs:element ref="sch:extends"/> 
      </xs:choice> 
      <xs:attribute name="context" type="xs:string"/> 
      <xs:attribute name="abstract" type="xs:boolean" default="false"/> 
      <xs:attribute name="role" type="xs:NMTOKEN"/> 
      <xs:attribute name="id" type="xs:string"/> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="schema"> 
     <xs:complexType> 
      <xs:sequence> 
       <xs:element ref="sch:title" minOccurs="0"/> 
       <xs:element ref="sch:ns" minOccurs="0" maxOccurs="unbounded"/> 
       <xs:element ref="sch:p" minOccurs="0" maxOccurs="unbounded"/> 
       <xs:element ref="sch:phase" minOccurs="0" maxOccurs="unbounded"/> 
       <xs:element ref="sch:pattern" maxOccurs="unbounded"/> 
       <xs:element ref="sch:p" minOccurs="0" maxOccurs="unbounded"/> 
       <xs:element ref="sch:diagnostics" minOccurs="0"/> 
      </xs:sequence> 
      <xs:attribute name="id" type="xs:ID"/> 
      <xs:attribute name="fpi" type="xs:string"/> 
      <xs:attribute name="schemaVersion" type="xs:string"/> 
      <xs:attribute name="defaultPhase" type="xs:string"/> 
      <xs:attribute name="icon" type="xs:anyURI"/> 
      <xs:attribute name="ns" type="xs:anyURI"/> 
      <xs:attribute name="version" type="xs:string" default="1.5"/> 
      <xs:attribute ref="xml:lang"/> 
      <xs:anyAttribute namespace="##other" processContents="lax"/> 
     </xs:complexType> 
     <xs:unique name="assertId"> 
      <xs:selector xpath="sch:pattern/sch:rule/sch:assert"/> 
      <xs:field xpath="@id"/> 
     </xs:unique> 
     <xs:unique name="reportId"> 
      <xs:selector xpath="sch:pattern/sch:rule/sch:report"/> 
      <xs:field xpath="@id"/> 
     </xs:unique> 
     <xs:unique name="ruleId"> 
      <xs:selector xpath="sch:pattern/sch:rule"/> 
      <xs:field xpath="@id"/> 
     </xs:unique> 
     <xs:unique name="patternId"> 
      <xs:selector xpath="sch:pattern"/> 
      <xs:field xpath="@id"/> 
     </xs:unique> 
     <xs:unique name="pId"> 
      <xs:selector xpath=".//sch:p"/> 
      <xs:field xpath="@id"/> 
     </xs:unique> 
     <xs:key name="phaseId"> 
      <xs:selector xpath="sch:phase"/> 
      <xs:field xpath="@id"/> 
     </xs:key> 
     <xs:keyref name="activePattern" refer="patternId"> 
      <xs:selector xpath="sch:phase/sch:active"/> 
      <xs:field xpath="@pattern"/> 
     </xs:keyref> 
     <xs:keyref name="extendsRule" refer="ruleId"> 
      <xs:selector xpath="sch:pattern/sch:rule/sch:extends"/> 
      <xs:field xpath="@rule"/> 
     </xs:keyref> 
     <xs:keyref name="defaultPhase" refer="phaseId"> 
      <xs:selector xpath="."/> 
      <xs:field xpath="@defaultPhase"/> 
     </xs:keyref> 
     <!-- Define the identity constraints --> 
    </xs:element> 
    <xs:element name="span"> 
     <xs:complexType> 
      <xs:simpleContent> 
       <xs:extension base="xs:string"> 
        <xs:attribute name="class" type="xs:string"/> 
       </xs:extension> 
      </xs:simpleContent> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="title"> 
     <xs:complexType mixed="true"> 
      <xs:choice minOccurs="0" maxOccurs="unbounded"> 
       <xs:element ref="sch:dir"/> 
      </xs:choice> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="value-of"> 
     <xs:complexType> 
      <xs:attribute name="select" type="xs:string" use="required"/> 
     </xs:complexType> 
    </xs:element> 
</xs:schema> 

sample_schematron.sch

<?xml version="1.0" encoding="UTF-8"?> 
<sch:schema 
    xmlns:sch="http://purl.oclc.org/dsdl/schematron" 
    queryBinding="xslt2" 
    xmlns="http://purl.oclc.org/dsdl/schematron" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="http://purl.oclc.org/dsdl/schematron"> 
    <sch:pattern id="sampleValidation"> 
     <sch:title>PatternTitle</sch:title> 
     <sch:p>A paragraph</sch:p> 
     <sch:rule context="CCC"> 
      <assert test="normalize-space(.) and *">Source contains an empty element</assert> 
     </sch:rule> 
    </sch:pattern> 
</sch:schema> 

SchematronUtil.java:

public class SchematronUtil { 
    public static boolean validateXMLViaXSLTSchematron(@Nonnull final File aSchematronFile, 
      @Nonnull final File aXMLFile) throws Exception { 
     final ISchematronResource aResSCH = SchematronResourceSCH.fromFile(aSchematronFile); 
     if (!aResSCH.isValidSchematron()) 
      throw new IllegalArgumentException("Invalid Schematron!"); 
     return aResSCH.getSchematronValidity(new StreamSource(aXMLFile)).isValid(); 
    } 

    public static SchematronOutputType validateXMLViaXSLTSchematronFull(@Nonnull final File aSchematronFile, 
      @Nonnull final File aXMLFile) throws Exception { 
     final ISchematronResource aResSCH = SchematronResourceSCH.fromFile(aSchematronFile); 
     if (!aResSCH.isValidSchematron()) 
      throw new IllegalArgumentException("Invalid Schematron!"); 
     return aResSCH.applySchematronValidationToSVRL(new StreamSource(aXMLFile)); 
    } 

    public static boolean validateXMLViaPureSchematron(@Nonnull final File aSchematronFile, 
      @Nonnull final File aXMLFile) throws Exception { 
     final ISchematronResource aResPure = SchematronResourcePure.fromFile(aSchematronFile); 
     if (!aResPure.isValidSchematron()) 
      throw new IllegalArgumentException("Invalid Schematron!"); 
     return aResPure.getSchematronValidity(new StreamSource(aXMLFile)).isValid(); 
    } 

    public static boolean validateXMLViaPureSchematron2(@Nonnull final File aSchematronFile, 
      @Nonnull final File aXMLFile) throws Exception { 
     // Read the schematron from file 
     final PSSchema aSchema = new PSReader(new FileSystemResource(aSchematronFile)).readSchema(); 
     if (!aSchema.isValid(new DoNothingPSErrorHandler())) 
      throw new IllegalArgumentException("Invalid Schematron!"); 
     // Resolve the query binding to use 
     final IPSQueryBinding aQueryBinding = PSQueryBindingRegistry 
       .getQueryBindingOfNameOrThrow(aSchema.getQueryBinding()); 
     // Pre-process schema 
     final PSPreprocessor aPreprocessor = new PSPreprocessor(aQueryBinding); 
     aPreprocessor.setKeepTitles(true); 
     final PSSchema aPreprocessedSchema = aPreprocessor.getAsPreprocessedSchema(aSchema); 
     // Bind the pre-processed schema 
     final IPSBoundSchema aBoundSchema = aQueryBinding.bind(aPreprocessedSchema, null, null, null, null); 
     // Read the XML file 
     final Document aXMLNode = DOMReader.readXMLDOM(aXMLFile); 
     if (aXMLNode == null) 
      return false; 
     // Perform the validation 
     return aBoundSchema.validatePartially(aXMLNode).isValid(); 
    } 

    public static boolean readModifyAndWrite(@Nonnull final File aSchematronFile) throws Exception { 
     final PSSchema aSchema = new PSReader(new FileSystemResource(aSchematronFile)).readSchema(); 
     final PSTitle aTitle = new PSTitle(); 
     aTitle.addText("Created by ph-schematron"); 
     aSchema.setTitle(aTitle); 
     return MicroWriter.writeToFile(aSchema.getAsMicroElement(), aSchematronFile).isSuccess(); 
    } 
} 

主要方法:

SchematronOutputType outputType = SchematronUtil.validateXMLViaXSLTSchematronFull(schematronFile, xmlFile); 

      if (outputType == null){ 
       throw new Exception("SchematronOutputType null"); 
      } 

      List<SVRLSuccessfulReport> succeededList = SVRLHelper.getAllSuccessfulReports(outputType); 
      for (SVRLSuccessfulReport succeededReport : succeededList){ 
       System.out.println(succeededReport.getTest()); 
      } 

      int i = 1; 
      List<SVRLFailedAssert> failedList = SVRLHelper.getAllFailedAssertions(outputType); 
      for (SVRLFailedAssert failedAssert : failedList) { 
       System.out.println(i++ + ". Location:" + failedAssert.getLocation()); 
       System.out.println("Test: " + failedAssert.getTest()); 
       System.out.println("Text: " + failedAssert.getText()); 

       List<DiagnosticReference> diagnisticReferences = failedAssert.getDiagnisticReferences(); 
       for (DiagnosticReference diagnisticRef : diagnisticReferences) { 
        System.out.println("Diag ref: " + diagnisticRef.getDiagnostic()); 
        System.out.println("Diag text: " + diagnisticRef.getText()); 
       } 
      } 

      if (failedList.isEmpty()){ 
       System.out.println("PASS"); 
      } 
      else{ 
       System.out.println("FAIL"); 
      } 
+0

你为什么用'xslt'标记问题? –

+0

@MathiasMüller,因为我使用XSLT2进行验证,PHSchematron支持XSLT和纯Schematron验证 – Silentbang

回答

0

根据通用ISO Schematron规则进行测试,您的Schematron文档是正确的,但targetNamespace属性除外。由于所有元素都有前缀,所以在其中有一个默认名称空间xmlns="..."也没有多大意义。

的Schematron

<?xml version="1.0" encoding="UTF-8"?> 
<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron" queryBinding="xslt2"> 
    <sch:pattern id="sampleValidation"> 
     <sch:title>PatternTitle</sch:title> 
     <sch:p>A paragraph</sch:p> 
     <sch:rule context="CCC"> 
      <assert test="normalize-space(.) and *">Source contains an empty element</assert> 
     </sch:rule> 
    </sch:pattern> 
</sch:schema> 

然后,Schematron的是好的,但有一堆与XML模式的问题。首先,XML Schema文档中的名称空间是不同的。 Schematron文件有http://purl.oclc.org/dsdl/schematron,而在XSD中是http://www.ascc.net/xml/schematron。这很可能是因为您对Schematron的旧版本使用了历史悠久的XML Schema。

拥有正确的命名空间应该可以解决sch:p不允许在sch:pattern内部的问题。在XSD固定的命名空间问题后,以下问题仍然存在:

Attribute 'queryBinding' is not allowed to appear in element 'sch:schema'. 
Attribute 'name' must appear on element 'sch:pattern'. 
Invalid content was found starting with element '{"http://purl.oclc.org/dsdl/schematron":title}'. One of '{"http://purl.oclc.org/dsdl/schematron":p, "http://purl.oclc.org/dsdl/schematron":rule}' is expected. 

所有这一切都可以通过修改您的XML模式是固定的,下面是一个可行的版本:

XML模式

<?xml version="1.0" encoding="UTF-8"?> 
<!-- schemaVersion of 2001/02/15 --> 
<xs:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron" xmlns="http://purl.oclc.org/dsdl/schematron" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://purl.oclc.org/dsdl/schematron" version="+//IDN sinica.edu.tw//SGML W3C XML Schema for Schematron 1.5//EN"> 
    <xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2001/xml.xsd"> 
     <xs:annotation> 
      <xs:documentation> 
       Get access to the xml: attribute groups for xml:lang 
      </xs:documentation> 
     </xs:annotation> 
    </xs:import> 
    <xs:annotation> 
     <xs:documentation source="http://www.ascc.net/xml/resource/schematron/schematron.html" xml:lang="en"/> 
    </xs:annotation> 
    <xs:element name="active"> 
     <xs:complexType mixed="true"> 
      <xs:choice minOccurs="0" maxOccurs="unbounded"> 
       <xs:element ref="sch:dir"/> 
       <xs:element ref="sch:emph"/> 
       <xs:element ref="sch:span"/> 
      </xs:choice> 
      <xs:attribute name="pattern" type="xs:IDREF" use="required"/> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="assert"> 
     <xs:complexType mixed="true"> 
      <xs:choice minOccurs="0" maxOccurs="unbounded"> 
       <xs:element ref="sch:name"/> 
       <xs:element ref="sch:emph"/> 
       <xs:element ref="sch:dir"/> 
       <xs:element ref="sch:span"/> 
       <xs:any namespace="##other" processContents="lax"/> 
      </xs:choice> 
      <xs:attribute name="test" type="xs:string" use="required"/> 
      <xs:attribute name="role" type="xs:NMTOKEN"/> 
      <xs:attribute name="id" type="xs:string"/> 
      <xs:attribute name="diagnostics" type="xs:IDREFS"/> 
      <xs:attribute name="icon" type="xs:anyURI"/> 
      <xs:attribute name="subject" type="xs:string" default="."/> 
      <xs:attribute ref="xml:lang"/> 
      <xs:anyAttribute namespace="##other" processContents="lax"/> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="diagnostic"> 
     <xs:complexType mixed="true"> 
      <xs:choice minOccurs="0" maxOccurs="unbounded"> 
       <xs:element ref="sch:value-of"/> 
       <xs:element ref="sch:emph"/> 
       <xs:element ref="sch:dir"/> 
       <xs:element ref="sch:span"/> 
       <xs:any namespace="##other" processContents="lax"/> 
      </xs:choice> 
      <xs:attribute name="id" type="xs:ID" use="required"/> 
      <xs:attribute name="icon" type="xs:anyURI"/> 
      <xs:attribute ref="xml:lang"/> 
      <xs:anyAttribute namespace="##other" processContents="lax"/> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="diagnostics"> 
     <xs:complexType> 
      <xs:sequence> 
       <xs:element ref="diagnostic" minOccurs="0" maxOccurs="unbounded"/> 
      </xs:sequence> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="dir"> 
     <xs:complexType> 
      <xs:simpleContent> 
       <xs:extension base="xs:string"> 
        <xs:attribute name="value"> 
         <xs:simpleType> 
          <xs:restriction base="xs:NMTOKEN"> 
           <xs:enumeration value="ltr"/> 
           <xs:enumeration value="rtl"/> 
          </xs:restriction> 
         </xs:simpleType> 
        </xs:attribute> 
       </xs:extension> 
      </xs:simpleContent> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="emph" type="xs:string"/> 
    <xs:element name="extends"> 
     <xs:complexType> 
      <xs:attribute name="rule" type="xs:string" use="required"/> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="key"> 
     <xs:complexType> 
      <xs:attribute name="name" type="xs:NMTOKEN" use="required"/> 
      <xs:attribute name="path" type="xs:string" use="required"/> 
      <xs:attribute name="icon" type="xs:anyURI"/> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="name"> 
     <xs:complexType> 
      <xs:attribute name="path" type="xs:string" default="." /> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="ns"> 
     <xs:complexType> 
      <xs:attribute name="uri" type="xs:anyURI" use="required"/> 
      <xs:attribute name="prefix" type="xs:NCName"/> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="p"> 
     <xs:complexType mixed="true"> 
      <xs:choice minOccurs="0" maxOccurs="unbounded"> 
       <xs:element ref="sch:dir"/> 
       <xs:element ref="sch:emph"/> 
       <xs:element ref="sch:span"/> 
      </xs:choice> 
      <xs:attribute name="id" type="xs:string"/> 
      <xs:attribute name="class" type="xs:string"/> 
      <xs:attribute name="icon" type="xs:anyURI"/> 
      <xs:attribute ref="xml:lang"/> 
      <xs:anyAttribute namespace="##other" processContents="lax"/> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="pattern"> 
     <xs:complexType> 
      <xs:sequence> 
       <xs:element ref="sch:title" minOccurs="0"/> 
       <xs:element ref="sch:p" minOccurs="0" maxOccurs="unbounded"/> 
       <xs:element ref="sch:rule" maxOccurs="unbounded"/> 
      </xs:sequence> 
      <xs:attribute name="name" type="xs:string" use="optional"/> 
      <xs:attribute name="see" type="xs:anyURI"/> 
      <xs:attribute name="id" type="xs:string"/> 
      <xs:attribute name="icon" type="xs:anyURI"/> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="phase"> 
     <xs:complexType> 
      <xs:sequence> 
       <xs:element ref="sch:p" minOccurs="0" maxOccurs="unbounded"/> 
       <xs:element ref="sch:active" maxOccurs="unbounded"/> 
      </xs:sequence> 
      <xs:attribute name="id" type="xs:string" use="required"/> 
      <xs:attribute name="fpi" type="xs:string"/> 
      <xs:attribute name="icon" type="xs:anyURI"/> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="report"> 
     <xs:complexType mixed="true"> 
      <xs:choice minOccurs="0" maxOccurs="unbounded"> 
       <xs:element ref="sch:name"/> 
       <xs:element ref="sch:emph"/> 
       <xs:element ref="sch:dir"/> 
       <xs:element ref="sch:span"/> 
       <xs:any namespace="##other" processContents="lax"/> 
      </xs:choice> 
      <xs:attribute name="test" type="xs:string" use="required"/> 
      <xs:attribute name="role" type="xs:NMTOKEN"/> 
      <xs:attribute name="id" type="xs:string"/> 
      <xs:attribute name="diagnostics" type="xs:IDREFS"/> 
      <xs:attribute name="icon" type="xs:anyURI"/> 
      <xs:attribute name="subject" type="xs:string" default="."/> 
      <xs:attribute ref="xml:lang"/> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="rule"> 
     <xs:complexType> 
      <xs:choice maxOccurs="unbounded"> 
       <xs:element ref="sch:assert"/> 
       <xs:element ref="sch:report"/> 
       <xs:element ref="sch:key"/> 
       <xs:element ref="sch:extends"/> 
      </xs:choice> 
      <xs:attribute name="context" type="xs:string"/> 
      <xs:attribute name="abstract" type="xs:boolean" default="false"/> 
      <xs:attribute name="role" type="xs:NMTOKEN"/> 
      <xs:attribute name="id" type="xs:string"/> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="schema"> 
     <xs:complexType> 
      <xs:sequence> 
       <xs:element ref="sch:title" minOccurs="0"/> 
       <xs:element ref="sch:ns" minOccurs="0" maxOccurs="unbounded"/> 
       <xs:element ref="sch:p" minOccurs="0" maxOccurs="unbounded"/> 
       <xs:element ref="sch:phase" minOccurs="0" maxOccurs="unbounded"/> 
       <xs:element ref="sch:pattern" maxOccurs="unbounded"/> 
       <xs:element ref="sch:p" minOccurs="0" maxOccurs="unbounded"/> 
       <xs:element ref="sch:diagnostics" minOccurs="0"/> 
      </xs:sequence> 
      <xs:attribute name="id" type="xs:ID"/> 
      <xs:attribute name="fpi" type="xs:string"/> 
      <xs:attribute name="schemaVersion" type="xs:string"/> 
      <xs:attribute name="defaultPhase" type="xs:string"/> 
      <xs:attribute name="icon" type="xs:anyURI"/> 
      <xs:attribute name="ns" type="xs:anyURI"/> 
      <xs:attribute name="version" type="xs:string" default="1.5"/> 
      <xs:attribute ref="xml:lang"/> 
      <xs:attribute name="queryBinding" type="xs:string"/> 
      <xs:anyAttribute namespace="##other" processContents="lax"/> 
     </xs:complexType> 
     <xs:unique name="assertId"> 
      <xs:selector xpath="sch:pattern/sch:rule/sch:assert"/> 
      <xs:field xpath="@id"/> 
     </xs:unique> 
     <xs:unique name="reportId"> 
      <xs:selector xpath="sch:pattern/sch:rule/sch:report"/> 
      <xs:field xpath="@id"/> 
     </xs:unique> 
     <xs:unique name="ruleId"> 
      <xs:selector xpath="sch:pattern/sch:rule"/> 
      <xs:field xpath="@id"/> 
     </xs:unique> 
     <xs:unique name="patternId"> 
      <xs:selector xpath="sch:pattern"/> 
      <xs:field xpath="@id"/> 
     </xs:unique> 
     <xs:unique name="pId"> 
      <xs:selector xpath=".//sch:p"/> 
      <xs:field xpath="@id"/> 
     </xs:unique> 
     <xs:key name="phaseId"> 
      <xs:selector xpath="sch:phase"/> 
      <xs:field xpath="@id"/> 
     </xs:key> 
     <xs:keyref name="activePattern" refer="patternId"> 
      <xs:selector xpath="sch:phase/sch:active"/> 
      <xs:field xpath="@pattern"/> 
     </xs:keyref> 
     <xs:keyref name="extendsRule" refer="ruleId"> 
      <xs:selector xpath="sch:pattern/sch:rule/sch:extends"/> 
      <xs:field xpath="@rule"/> 
     </xs:keyref> 
     <xs:keyref name="defaultPhase" refer="phaseId"> 
      <xs:selector xpath="."/> 
      <xs:field xpath="@defaultPhase"/> 
     </xs:keyref> 
     <!-- Define the identity constraints --> 
    </xs:element> 
    <xs:element name="span"> 
     <xs:complexType> 
      <xs:simpleContent> 
       <xs:extension base="xs:string"> 
        <xs:attribute name="class" type="xs:string"/> 
       </xs:extension> 
      </xs:simpleContent> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="title"> 
     <xs:complexType mixed="true"> 
      <xs:choice minOccurs="0" maxOccurs="unbounded"> 
       <xs:element ref="sch:dir"/> 
      </xs:choice> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="value-of"> 
     <xs:complexType> 
      <xs:attribute name="select" type="xs:string" use="required"/> 
     </xs:complexType> 
    </xs:element> 
</xs:schema> 

但请记住:此XSD文档已过时,并未反映对Schematron规范的最新更改。它很可能会有其他问题。

作为一种替代方法,您可以使用最近的ISO Schematron and SQF schemas from Schematron Quickfix。确保您下载所有模式组件,然后根据iso-schematron.xsd进行验证。

+0

谢谢您将ISO Schematron XSD文件指向我。你如何用Notepad ++测试它的验证? – Silentbang

+0

@Silentbang我已经使用Oxygen进行测试,但我确定您也可以使用Notepad ++或命令行工具(如xmllint)进行测试。不过,您需要一个能够理解XSD和Schematron的工具。 –

+0

@Silentbang那么,这是否解决了你的问题?我的答案是否有缺失?请接受这个答案,或者让我知道是否有问题。 –