Reputation: 1518
I've spent a long time trying to figure out how to validate a XML file, and I've got it working with a pre-generated XSD schema. However, I wish to dynamically generate a schema without creating a file, based on the annotation class I have specified, I've tried to not specify any parameters to SchemaFactory, but then it seems to just create an empty schema (see comments below).
Here are the two classes I use for my JAXB reading and writing of a XML file.
This is the code for the class XMLTranslationWrapper:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(namespace = "my.package.namespace")
public class XMLTranslationWrapper {
@XmlElementWrapper(name = "TRANSLATIONS")
@XmlElement(name = "TRANSL")
public ArrayList<XMLTranslationNode> translations;
public XMLTranslationWrapper(){
translations = new ArrayList<XMLTranslationNode>();
}
public void setTranslations(ArrayList<XMLTranslationNode> translations){
this.translations = translations;
}
public XMLTranslationNode getTranslation(String code){
for(XMLTranslationNode transl : translations){
if(transl.getCode().equals(code))
return transl;
}
return null;
}
public void addTranslation(XMLTranslationNode translation){
this.translations.add(translation);
}
}
This is the code for the class XMLTranslationNode:
@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlRootElement(name = "TRANSL")
@XmlType(propOrder = { "severity", "translation" })
public class XMLTranslationNode {
private String severity;
private String code;
private String translation;
@XmlElement(name="SEVERITY")
public String getSeverity(){
return this.severity;
}
public void setSeverity(String severity){
this.severity = severity;
}
@XmlAttribute(name="CODE")
public String getCode(){
return this.code;
}
public void setCode(String code){
this.code = code;
}
@XmlElement(name="TRANSLATION")
public String getTranslation(){
return this.translation;
}
public void setTranslation(String translation){
this.translation = translation;
}
}
This is the code I used to generate the pre-generated XSD schema:
public class generateSchema {
public static void main(String[] args) {
JAXBContext jaxbContext;
try {
jaxbContext = JAXBContext.newInstance(XMLTranslationWrapper.class);
SchemaOutputResolver sor = new MySchemaOutputResolver();
jaxbContext.generateSchema(sor);
} catch (JAXBException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
static class MySchemaOutputResolver extends SchemaOutputResolver {
public Result createOutput(String namespaceURI, String suggestedFileName) throws IOException {
File file = new File(suggestedFileName);
StreamResult result = new StreamResult(file);
System.out.println(file.toURI().toURL().toString());
result.setSystemId(file.toURI().toURL().toString());
return result;
}
}
}
Finally here is a sample XML which can be used to test the code:
<?xml version="1.0" encoding="US-ASCII" standalone="yes"?>
<ns2:xmlTranslationWrapper xmlns:ns2="my.package.namespace">
<TRANSLATIONS>
<TRANSL CODE="123">
<SEVERITY>Information</SEVERITY>
<TRANSLATION>ABC</TRANSLATION>
</TRANSL>
</TRANSLATIONS>
</ns2:xmlTranslationWrapper>
How can I dynamically generate my XSD schema without creating a file equivalent to using a pre-generated XSD schema?
Upvotes: 0
Views: 2451
Reputation: 43709
As promised. The idea is simple:
I don't think you can do it much better than that. JAXB's schemagen
internal structures do not seem to be compatible with javax.xml.validation.Schema
. So creating DOM and then parsing it back is the easiest way.
public class DynamicSchemaTest {
@XmlRootElement
public static class A {
@XmlAttribute(required = true)
public String name;
public A() {
}
public A(String name) {
this.name = name;
}
}
@Test(expected = MarshalException.class)
public void generatesAndUsesSchema() throws JAXBException, IOException,
SAXException {
final JAXBContext context = JAXBContext.newInstance(A.class);
final DOMResult result = new DOMResult();
result.setSystemId("schema.xsd");
context.generateSchema(new SchemaOutputResolver() {
@Override
public Result createOutput(String namespaceUri,
String suggestedFileName) {
return result;
}
});
@SuppressWarnings("deprecation")
final SchemaFactory schemaFactory = SchemaFactory
.newInstance(WellKnownNamespace.XML_SCHEMA);
final Schema schema = schemaFactory.newSchema(new DOMSource(result
.getNode()));
final Marshaller marshaller = context.createMarshaller();
marshaller.setSchema(schema);
// Works
marshaller.marshal(new A("works"), System.out);
// Fails
marshaller.marshal(new A(null), System.out);
}
}
Upvotes: 5