XSDスキーマに対してXMLを検証する必要があります。ここでは、既存のすべての違反を判別するために、いくつかの「key/keyref」制約を定義しています。ただし、そのようなkeyref違反が最初に決定された後のJAXP XMLバリデーターは、他のものが存在する場合でもスキップします。
2つの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();
}
}
との2つのエラーが予想され<ref to="3"/>
ます<ref to="4"/>
が、バリデーターはこれらのエラーの最初のエラーのみを判別でき<ref to="3"/>
ます。問題のあるノードに変更<ref to="3"/>
すると決定されます。<ref to="2"/>
1つのxml処理ごとにこのような参照エラーをすべて取得するにはどうすればよいですか?