Unmarshaller and schema in JAXB

I have an application that can save a file in various formats (all of them are xml). Therefore, I have to solve the problem with the definition in the format file. So I see 2 solutions

  • different formats have different schemes, so I can define them with them. I set the circuits in such a way that I get from here

marshaller.setProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION, "bla-bla.xsd");

so I can get it with unmarshaller.getProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION)

but he throws

javax.xml.bind.PropertyException: jaxb.noNamespaceSchemaLocation

and getSchema() return null So, how can I get the location of the schema?

  • Specifying different adapters for different beans using the setAdapter(Class<A> type, A adapter) method

Which method is preferable? If at first, how can I get the location label of the circuit?

sample code suppose bean

 @XmlRootElement public class Foo{ String bar; public String getBar() {return bar; } public void setBar(String bar) {this.bar = bar;} } 

and the code that generates the circuit then stores the instances of Foo and loads.

 public class Test { final static String schemaLoc = "fooschema.xsd"; public static void write(File file, Foo foo, Schema schema) throws Throwable { XMLEventWriter xsw = null; try{ JAXBContext context = JAXBContext.newInstance(Foo.class); XMLOutputFactory xof = XMLOutputFactory.newInstance(); OutputStream out = new FileOutputStream(file); xsw = xof.createXMLEventWriter(out); Marshaller m = context.createMarshaller(); m.setSchema(schema); //schema setted System.out.println(">>>marchal : " + m.getSchema()); //check it m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); m.setProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION, schemaLoc); m.marshal(foo, xsw); } finally{ xsw.close(); } } public static Foo load(File file) throws Throwable { JAXBContext context = JAXBContext.newInstance(Foo.class); Unmarshaller unmarshaller = context.createUnmarshaller(); System.out.println("unmarshaller schema:" + unmarshaller.getSchema()); //I need get it here // System.out.println("schema_prop:" + unmarshaller.getProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION)); InputStreamReader in = new InputStreamReader(new FileInputStream(file)); XMLEventReader xer = XMLInputFactory.newInstance() .createXMLEventReader(in); return Foo.class.cast(unmarshaller.unmarshal(xer)); } private static File createSchema(String schemaLocation) throws Throwable{ final File target = new File(schemaLocation); if(!target.exists()){ JAXBContext jaxbContext = JAXBContext.newInstance(Foo.class); SchemaOutputResolver sor = new SchemaOutputResolver() { public Result createOutput(String namespaceURI, String suggestedFileName) throws IOException { StreamResult result = new StreamResult(target); result.setSystemId(target.toURI().toURL().toString()); return result; } }; jaxbContext.generateSchema(sor); } return target; } public static void main(String[] args) throws Throwable { createSchema(schemaLoc); File file = new File("temp.xml"); Foo foo = new Foo(); foo.setBar("test bar"); SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); Schema schema = factory.newSchema(createSchema(schemaLoc)); write(file, foo, schema); System.out.println("result " + load(file).getBar()); } } 

which generates

  <xs:element name="foo" type="foo"/> <xs:complexType name="foo"> <xs:sequence> <xs:element name="bar" type="xs:string" minOccurs="0"/> </xs:sequence> </xs:complexType> </xs:schema> 

our temporary file

 <?xml version="1.0"?> <foo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="fooschema.xsd"> <bar>test bar</bar></foo> 

as we see there

XSI: noNamespaceSchemaLocation = "fooschema.xsd"

How can I get this text using JAXB?

+4
source share
2 answers

I would use the StAX analyzer to get this information (see example below). Create an XMLStreamReader in the input. Move the XMLStreamReader to the root element using the nextTag () method. Then grab the noNamespaceSchemaLocation attribute of the root element. Then pass the XMLStreamReader to the unmarshal method (XMLStreamReader) on the Unmarshaller.

 import java.io.FileInputStream; import javax.xml.XMLConstants; import javax.xml.bind.JAXBContext; import javax.xml.bind.Unmarshaller; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamReader; public class Demo { public static void main(String[] args) throws Exception { JAXBContext context = JAXBContext.newInstance(Categories.class); XMLInputFactory xif = XMLInputFactory.newInstance(); FileInputStream fis = new FileInputStream("input.xml"); XMLStreamReader xsr = xif.createXMLStreamReader(fis); xsr.nextTag(); String noNamespaceSchemaLocation = xsr.getAttributeValue(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "noNamespaceSchemaLocation"); System.out.println(noNamespaceSchemaLocation); Unmarshaller um = context.createUnmarshaller(); Categories response = (Categories) um.unmarshal(xsr); } } 
+4
source

You must specify its location for your schema using the file with our fileoutputstream link:

http://download.oracle.com/javase/6/docs/api/javax/xml/bind/Marshaller.html

EDIT:

Sorry, after reading you really need the layout of the schema, not the XML file, and there are some examples online. Most of them, like this one:

http://robaustin.wikidot.com/how-to-improve-perforamance-of-jaxb

Show how to pass a schema location using the context class loader.

EDIT:

For your comments:

http://download.oracle.com/javase/6/docs/api/javax/xml/bind/Marshaller.html#getSchema%28%29

getSchema () will return null if there is no schema on the marshaller. That is why you cannot get the required property because it (the circuit) does not exist.

+2
source

Source: https://habr.com/ru/post/1332536/


All Articles