Как я могу определить ВСЕ нарушения 'key / keyref' ограничения документа XML с его XSD, используя JAXP (xerces) - PullRequest
5 голосов
/ 21 марта 2012

Мне нужно проверить XML на соответствие его XSD-схеме, где я определил несколько ограничений «ключ / ключ» для определения всех существующих нарушений. Но валидатор JAXP XML после первого определения такого нарушения ключа пропускает другие, даже если они присутствуют.

XML-файл с двумя нарушениями ключей:

<?xml version="1.0" encoding="UTF-8"?>
<relations>
<keys>
    <key id="1"/>
    <key id="2"/>       
</keys>     
<refs>      
    <ref to="2"/><!-- This is valid because key with id 2 present -->

      <!-- This two xml elements have 'keyref' constraint violation because there aren't        coresponding keys with id 3,4-->
    <ref to="3"/>
    <ref to="4"/>
</refs>
</relations>

Схема xsd:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
 <xs:element name="relations">
<xs:complexType>
  <xs:all>
    <xs:element ref="keys"/>
    <xs:element ref="refs"/>
  </xs:all>
</xs:complexType>
<!-- Constraints Section -->    
<xs:key name="key-pk">
    <xs:selector xpath="keys/key" />
    <xs:field xpath="@id" />
</xs:key>
<xs:keyref name="ref-key-pk" refer="key-pk">
    <xs:selector xpath="refs/ref" />
    <xs:field xpath="@to" />        
</xs:keyref>    
 </xs:element>
<xs:element name="keys">
<xs:complexType>
  <xs:sequence>
    <xs:element maxOccurs="unbounded" ref="key"/>
  </xs:sequence>      
 </xs:complexType>
</xs:element>
<xs:element name="refs">
<xs:complexType>
  <xs:sequence>
    <xs:element maxOccurs="unbounded" ref="ref"/>
  </xs:sequence>      
</xs:complexType>
</xs:element>
<xs:element name="key">
<xs:complexType>
  <xs:attribute name="id" type="xs:long"/>      
</xs:complexType>
</xs:element>
<xs:element name="ref">
<xs:complexType>
  <xs:attribute name="to" type="xs:long"/>      
</xs:complexType>
</xs:element>
</xs:schema>

Java-код, который выполняет такую ​​проверку:

 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.InputStream;
 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.ErrorHandler;
 import org.xml.sax.SAXException;
 import org.xml.sax.SAXParseException;

 public class LayoutXmlValidator {

private static final String XSD = "/examp.xsd";
private File xml = null;
private Validator validator;
private Schema schema;
private ErrorHandler errorHandler;

private static class ErrorReporter implements ErrorHandler{
    private int errorCounter;       
    @Override
    public void warning(SAXParseException exception) throws SAXException {
        final String tag = "warning";
        out(tag, exception);        
    }       
    @Override
    public void fatalError(SAXParseException exception) throws SAXException {
        final String tag = "fatal";
        out(tag, exception);
    }       
    @Override
    public void error(SAXParseException exception) throws SAXException {            
        final String tag = "error";
        out(tag, exception);
    }

    private void out(String tag, SAXParseException e){          
        errorCounter++;         
        String msg = e.getMessage()+"\n";
        msg +="    "+tag+" at "+e.getSystemId()+":"+e.getLineNumber();
        System.out.println(errorCounter+")"+msg);
    }
}


public LayoutXmlValidator() {
    try{
        SchemaFactory factory = 
            SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
        InputStream xsd = getClass().getResourceAsStream(XSD);
        schema = factory.newSchema(new StreamSource(xsd));            
        validator = schema.newValidator();
        errorHandler = new ErrorReporter();
    }catch(Throwable e){
        e.printStackTrace();
    }       
}       

public void setErrorHandler(ErrorHandler errorHandler) {
    this.errorHandler = errorHandler;
}

private void validate(){
    try{                                                                                    
        validator.setErrorHandler(errorHandler);            
        Source source = new StreamSource(xml);            
        try {                                               
            validator.validate(source);             
        }
        catch (SAXException ex) {
            System.out.println(xml + " is not valid because ");
            System.out.println(ex.getMessage());
        }           
    }catch(Exception e){
        e.printStackTrace();
    }
}

public static void main(String[] args) {                                                                
    LayoutXmlValidator v = new LayoutXmlValidator();
    v.xml = new File("examp.xml");
    v.validate();                                  
}
  }

Я ожидаю 2 ошибки для <ref to="3"/> и <ref to="4"/>, но средство проверки может определить только первую из этих ошибок для <ref to="3"/>. Когда я изменю <ref to="3"/> на <ref to="2"/>, проблемный узел будет определен. Как я могу получить все такие ссылочные ошибки за одну обработку XML?

...