XMLファイルにマーシャリングする前に、JAXBオブジェクトを検証する必要があります。 JAXB 2.0より前は、javax.xml.bind.Validatorを使用できました。しかし、これは廃止されているため、これを行う適切な方法を見つけようとしています。私はマーシャル時に検証に精通していますが、私の場合は、それが有効かどうかを知りたいだけです。一時ファイルまたはメモリにマーシャリングして破棄することはできますが、よりエレガントな解決策があるかどうか疑問に思います。
まず、_javax.xml.bind.Validator
_は非推奨になり、_javax.xml.validation.Schema
_( javadoc )が採用されました。アイデアは、_javax.xml.validation.SchemaFactory
_( javadoc )を介してスキーマを解析し、それをmarshaller/unmarshallerに挿入することです。
マーシャリングなしの検証に関する質問については、ここでの問題は、JAXBが実際に検証をXerces(または使用しているSAXプロセッサ)に委任し、XercesがドキュメントをSAXイベントのストリームとして検証することです。したがって、検証するには、some種類のマーシャリングを実行する必要があります。
これの最も影響の少ない実装は、SAXプロセッサの「/ dev/null」実装を使用することです。 null OutputStreamへのマーシャリングには、XMLの生成が含まれますが、これは無駄です。だから私はお勧めします:
_SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = schemaFactory.newSchema(locationOfMySchema);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setSchema(schema);
marshaller.marshal(objectToMarshal, new DefaultHandler());
_
DefaultHandler
はすべてのイベントを破棄し、スキーマに対する検証が失敗した場合、marshal()
操作はJAXBExceptionをスローします。
javax.xml.bind.util.JAXBSource
( javadoc )とjavax.xml.validation.Validator
( javadoc )を使用して、org.xml.sax.ErrorHandler
の実装をスローできます(- javadoc )そして以下を実行します。
import Java.io.File;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.util.JAXBSource;
import javax.xml.validation.*;
public class Demo {
public static void main(String[] args) throws Exception {
Customer customer = new Customer();
customer.setName("Jane Doe");
customer.getPhoneNumbers().add(new PhoneNumber());
customer.getPhoneNumbers().add(new PhoneNumber());
customer.getPhoneNumbers().add(new PhoneNumber());
JAXBContext jc = JAXBContext.newInstance(Customer.class);
JAXBSource source = new JAXBSource(jc, customer);
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(new File("customer.xsd"));
Validator validator = schema.newValidator();
validator.setErrorHandler(new MyErrorHandler());
validator.validate(source);
}
}
詳細については、マイブログを参照してください
これが私たちのやり方です。さまざまなバージョンのxmlコンテンツを使用する多くのアプリがあるため、xmlファイルとxmlのバージョンに対応するxsdを検証する方法を見つける必要がありました。
ネット上で良い例が実際に見つからなかったので、最終的にこれで終了しました。これが役立つことを願っています。
ValidationEventCollector vec = new ValidationEventCollector();
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
URL xsdURL = getClass().getResource("/xsd/" + xsd);
Schema schema = sf.newSchema(xsdURL);
//You should change your jaxbContext here for your stuff....
Unmarshaller um = (getJAXBContext(NotificationReponseEnum.NOTIFICATION, notificationWrapper.getEnteteNotification().getTypeNotification()))
.createUnmarshaller();
um.setSchema(schema);
try {
StringReader reader = new StringReader(xml);
um.setEventHandler(vec);
um.unmarshal(reader);
} catch (javax.xml.bind.UnmarshalException ex) {
if (vec != null && vec.hasEvents()) {
erreurs = new ArrayList < MessageErreur > ();
for (ValidationEvent ve: vec.getEvents()) {
MessageErreur erreur = new MessageErreur();
String msg = ve.getMessage();
ValidationEventLocator vel = ve.getLocator();
int numLigne = vel.getLineNumber();
int numColonne = vel.getColumnNumber();
erreur.setMessage(msg);
msgErreur.setCode(ve.getSeverity())
erreur.setException(ve.getLinkedException());
erreur.setPosition(numLigne, numColonne);
erreurs.add(erreur);
logger.debug("Erreur de validation xml" + "erreur : " + numLigne + "." + numColonne + ": " + msg);
}
}
}