JAXB中的Unmarshaller和模式

我有应用程序,可以以各种格式保存文件(所有这些都是xml)。 所以我应该在确定格式文件已保存的情况下解决问题。 所以,我看到了两个解决方案

  • 不同的格式有不同的模式,所以我可以通过它们来确定。 我按照从这里开始的方式设置模式

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

所以我想我可以使用unmarshaller.getProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION)来获取它

但它扔了

javax.xml.bind.PropertyException:jaxb.noNamespaceSchemaLocation

getSchema()返回null那么, 我怎样才能获得模式位置?

什么方式更可取? 如果是第一个,那我怎样才能获得架构位置标签?

upd 代码示例假设我们有bean

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

和生成模式的代码,然后保存Foo的实例和加载。

 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()); } } 

生成的模式

         

我们的临时文件

   test bar 

正如我们所见,有

的xsi:noNamespaceSchemaLocation = “fooschema.xsd”

我如何使用JAXB获取此文本?

我将利用StAX解析器来获取此信息(请参阅下面的示例)。 在输入上创建XMLStreamReader。 使用nextTag()方法将XMLStreamReader推进到根元素。 然后获取根元素的noNamespaceSchemaLocation属性。 然后将XMLStreamReader传递给Unmarshaller上的unmarshal(XMLStreamReader)方法。

 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); } } 

您必须使用fileoutputstream参考文件为其提供架构的位置:

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

编辑:

对不起,在进一步阅读之后,您实际上想要架构的位置,而不是XML文件,并且在线有很多示例。 大多数人喜欢这个:

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

演示如何使用上下文类加载器传递模式位置。

编辑:

根据你的意见:

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

如果marshaller上没有设置架构,则getSchema()将返回null。 这就是为什么你不能得到你想要的属性,因为它(架构)不存在。