如何使用JAXP(xerces)确定其XSD的所有'key / keyref'约束违反XML文档

时间:2012-03-21 16:18:39

标签: java xml validation xsd jaxp

我需要针对其XSD架构验证XML,我已经定义了几个“key / keyref”约束来确定所有现有的违规。但是,在首次确定此类keyref违规后,JAXP XML验证程序将跳过其他人,即使它们存在。

包含两个keyref违规的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();                                  
}
  }

我预计<ref to="3"/><ref to="4"/>会出现2个错误,但验证者只能确定<ref to="3"/>的第一个错误。当我将<ref to="3"/>更改为<ref to="2"/>时,将确定有问题的节点。如何在每个xml处理中获得所有此类引用错误?

0 个答案:

没有答案