Java 如何在不编组的情况下验证 JAXB 2.0 中的模式?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1560422/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to validate against schema in JAXB 2.0 without marshalling?
提问by Joel
I need to validate my JAXB objects before marshalling to an XML file. Prior to JAXB 2.0, one could use a javax.xml.bind.Validator. But that has been deprecated so I'm trying to figure out the proper way of doing this. I'm familiar with validating at marshall time but in my case I just want to know if its valid. I suppose I could marshall to a temp file or memory and throw it away but wondering if there is a more elegant solution.
我需要在编组到 XML 文件之前验证我的 JAXB 对象。在 JAXB 2.0 之前,可以使用 javax.xml.bind.Validator。但这已被弃用,所以我试图找出这样做的正确方法。我熟悉在马歇尔时间进行验证,但就我而言,我只想知道它是否有效。我想我可以编组到临时文件或内存并将其丢弃,但想知道是否有更优雅的解决方案。
采纳答案by skaffman
Firstly, javax.xml.bind.Validator
has been deprecated in favour of javax.xml.validation.Schema
(javadoc). The idea is that you parse your schema via a javax.xml.validation.SchemaFactory
(javadoc), and inject that into the marshaller/unmarshaller.
首先,javax.xml.bind.Validator
已被弃用以支持javax.xml.validation.Schema
( javadoc)。这个想法是您通过javax.xml.validation.SchemaFactory
(javadoc)解析您的架构,并将其注入编组器/解组器。
As for your question regarding validation without marshalling, the problem here is that JAXB actually delegates the validation to Xerces (or whichever SAX processor you're using), and Xerces validates your document as a stream of SAX events. So in order to validate, you need to perform somekind of marshalling.
至于您关于没有编组的验证的问题,这里的问题是 JAXB 实际上将验证委托给 Xerces(或您使用的任何 SAX 处理器),而 Xerces 将您的文档验证为 SAX 事件流。因此,为了验证,您需要执行某种编组。
The lowest-impact implementation of this would be to use a "/dev/null" implementation of a SAX processor. Marshalling to a null OutputStream would still involve XML generation, which is wasteful. So I would suggest:
对此影响最小的实现是使用 SAX 处理器的“/dev/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
will discard all the events, and the marshal()
operation will throw a JAXBException if validation against the schema fails.
DefaultHandler
将丢弃所有事件,marshal()
如果对架构的验证失败,则操作将抛出 JAXBException。
回答by Pat B
This how we did it. I had to find a way to validate the xml file versus an xsd corresponding to the version of the xml since we have many apps using different versions of the xml content.
我们就是这样做的。我必须找到一种方法来验证 xml 文件与对应于 xml 版本的 xsd,因为我们有许多应用程序使用不同版本的 xml 内容。
I didn't really find any good examples on the net and finally finished with this. Hope this will help.
我真的没有在网上找到任何好的例子,最后完成了这个。希望这会有所帮助。
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);
}
}
}
回答by bdoughan
You could use a javax.xml.bind.util.JAXBSource
(javadoc) and a javax.xml.validation.Validator
(javadoc), throw in an implementation of org.xml.sax.ErrorHandler
(javadoc) and do the following:
你可以使用一个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);
}
}
For More Information, See My Blog
有关更多信息,请参阅我的博客