Tôi cần xác thực các đối tượng JAXB của mình trước khi sắp xếp một tập tin XML. Trước JAXB 2.0, người ta có thể sử dụng một javax.xml.bind.Validator. Nhưng điều đó đã không được chấp nhận nên tôi đang cố gắng tìm ra cách làm đúng đắn. Tôi quen thuộc với việc xác nhận thời gian marshall nhưng trong trường hợp của tôi, tôi chỉ muốn biết nếu nó hợp lệ. Tôi cho rằng tôi có thể sắp xếp một tập tin tạm thời hoặc bộ nhớ và vứt nó đi nhưng tự hỏi liệu có một giải pháp thanh lịch hơn không.Làm cách nào để xác thực hợp lệ đối với lược đồ trong JAXB 2.0 mà không cần marshalling?
Trả lời
Trước hết, javax.xml.bind.Validator
đã không được chấp nhận vì lợi ích của javax.xml.validation.Schema
(javadoc). Ý tưởng là bạn phân tích cú pháp lược đồ của mình thông qua một số javax.xml.validation.SchemaFactory
(javadoc) và đưa vào lược đồ/unmarshaller.
Đối với câu hỏi của bạn liên quan đến xác nhận mà không marshalling, vấn đề ở đây là JAXB thực sự đại biểu xác nhận để Xerces (hoặc bất cứ bộ xử lý SAX bạn đang sử dụng), và Xerces xác nhận tài liệu của bạn dưới dạng một dòng sự kiện SAX. Vì vậy, để xác thực, bạn cần thực hiện một số loại loại marshalling.
Việc triển khai tác động thấp nhất này sẽ là sử dụng triển khai "/ dev/null" của bộ xử lý SAX. Marshalling đến một OutputStream null sẽ vẫn liên quan đến việc tạo ra XML, đó là lãng phí. Vì vậy, tôi xin đề nghị:
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
sẽ loại bỏ tất cả các sự kiện, và các hoạt động marshal()
sẽ ném một JAXBException nếu xác nhận dựa trên giản đồ thất bại.
Cách thức chúng tôi đã thực hiện. Tôi đã phải tìm cách xác thực tệp xml so với xsd tương ứng với phiên bản xml vì chúng tôi có nhiều ứng dụng sử dụng các phiên bản khác nhau của nội dung xml.
Tôi thực sự không tìm thấy bất kỳ ví dụ hay nào trên mạng và cuối cùng đã kết thúc với điều này. Hy vọng điều này sẽ giúp.
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);
}
}
}
Bạn có thể sử dụng một javax.xml.bind.util.JAXBSource
(javadoc) và một javax.xml.validation.Validator
(javadoc), ném vào một thực hiện org.xml.sax.ErrorHandler
(javadoc) và làm như sau:
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);
}
}
Để biết thêm thông tin, Xem My Blog
- 1. Cách viết Kiểm tra Đơn vị cho JAXB 2.0 Marshalling
- 2. Có thể xác nhận hợp lệ XML được trộn lẫn với JAXB 2.0 không?
- 3. Xác nhận hợp lệ chống lại một Schema với JAXB
- 4. Làm cách nào để xác thực tài liệu đối với các lược đồ Schematron trong Java?
- 5. Sử dụng .NET để xác nhận hợp lệ XML đối với lược đồ
- 6. Làm cách nào để tắt xác thực yêu cầu mà không cần đặt RequestValidationMode thành 2.0?
- 7. Xác thực lược đồ JSON với PHP
- 8. Làm cách nào để xác thực xml lớn đối với lược đồ xsd?
- 9. Xác thực lược đồ XSD trong Ruby
- 10. JAXB Marshalling and Polymorphism
- 11. Xác nhận hợp lệ nhiều thuộc tính lược đồ Mongoose?
- 12. Xác thực lược đồ XML của XElement
- 13. JAXB Marshalling Objects với trường java.lang.Object
- 14. Tôi làm cách nào để sử dụng xác thực lược đồ hiện đại/khác với .Net?
- 15. xác thực lược đồ XML
- 16. Cách tìm nút XML không hợp lệ trong XDocument được xác nhận hợp lệ đối với một lược đồ (XmlSchemaValidationException.SourceObject là null)
- 17. Google API: Cách xác thực mà không cần chuyển hướng?
- 18. Xác thực thực tế dữ liệu JAXB với JAX-RS?
- 19. Cách xác thực id email trong lược đồ xml
- 20. xác thực lược đồ với msxml trong delphi
- 21. Xác nhận hợp lệ một XML dựa vào XSD trong Java/Bắt giữ lược đồ Location
- 22. Xác thực lược đồ JSON bằng cách sử dụng java
- 23. Tạo các lớp jaxb từ lược đồ
- 24. Làm cách nào để xác thực đầu ra của XmlSerializer?
- 25. Sử dụng BigDecimal trong JAXB marshalling
- 26. Ràng buộc JAXB đối với các lược đồ trong một JAR
- 27. JAXB marshalling Java để xuất tệp XML
- 28. Làm cách nào để xác thực với Google qua OAuth 2.0 trong cửa sổ bật lên?
- 29. Xác thực lược đồ JSON với các khóa tùy ý
- 30. JAXB marshalling cho BigDecimal sử dụng fractionDigits
Một vấn đề với cách tiếp cận này: bạn không nhận được thông tin số dòng/cột về lỗi xác thực bằng phương pháp này, do đó rất khó để theo dõi vấn đề. –
Cách tiếp cận đó có thể áp dụng cho Unmarchalling không. Tôi không thể tạo đối tượng JAXBSource. – Xelian