Java JAXB 中的解组器和模式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4478666/
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
Unmarshaller and schema in JAXB
提问by Stan Kurilin
I have application that can save file in various formats (all of them is xml). So I should solve problem with determination in what format file have been saved. So, I see 2 solutions
我有可以以各种格式保存文件的应用程序(所有格式都是 xml)。所以我应该解决确定保存的格式文件的问题。所以,我看到了 2 个解决方案
- different formats have different schemas, so I could determine it by them. I set schemas in way that I get from here
- 不同的格式有不同的模式,所以我可以通过它们来确定。我以我从这里获得的方式设置模式
marshaller.setProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION, "bla-bla.xsd");
marshaller.setProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION, "bla-bla.xsd");
so I suppose I can get it using unmarshaller.getProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION)
所以我想我可以使用它 unmarshaller.getProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION)
but it throwing
但它扔
javax.xml.bind.PropertyException: jaxb.noNamespaceSchemaLocation
javax.xml.bind.PropertyException: jaxb.noNamespaceSchemaLocation
and getSchema()
return null
So, how can I get schema location?
并getSchema()
返回 null 那么,如何获取架构位置?
- Specifying different adapters for different beans using
setAdapter(Class<A> type, A adapter)
method
- 使用
setAdapter(Class<A> type, A adapter)
方法为不同的bean指定不同的适配器
What way is preferable? If first, then how can I get schema location label?
哪种方式更可取?如果首先,那么我怎样才能获得架构位置标签?
upd code examplesuppose we have bean
更新代码示例假设我们有 bean
@XmlRootElement
public class Foo{
String bar;
public String getBar() {return bar; }
public void setBar(String bar) {this.bar = bar;}
}
and code that generates schema, saves Foo's instances and loads then.
和生成模式的代码,然后保存 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());
}
}
schema that 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 temp 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 is
正如我们所见,有
xsi:noNamespaceSchemaLocation="fooschema.xsd"
xsi:noNamespaceSchemaLocation="fooschema.xsd"
How I can get this text using JAXB?
如何使用 JAXB 获取此文本?
采纳答案by bdoughan
I would leverage a StAX parser to get this information (see example below). Create an XMLStreamReader on the input. Advance 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(XMLStreamReader)method on Unmarshaller.
我会利用 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);
}
}
回答by Stan Kurilin
You have to provide it with the location of your schema by using a file our fileoutputstream reference:
您必须使用我们的 fileoutputstream 引用的文件为其提供架构的位置:
http://download.oracle.com/javase/6/docs/api/javax/xml/bind/Marshaller.html
http://download.oracle.com/javase/6/docs/api/javax/xml/bind/Marshaller.html
EDIT:
编辑:
Sorry, after reading further, you actually want the location of the schema, not the XML file, and there are quite a few examples online. Most of them like this one:
抱歉,进一步阅读后,您实际上想要的是模式的位置,而不是 XML 文件,并且网上有很多示例。他们中的大多数人喜欢这个:
http://robaustin.wikidot.com/how-to-improve-perforamance-of-jaxb
http://robustin.wikidot.com/how-to-improve-perforamance-of-jaxb
Show how to pass in the schema location using a context class loader.
展示如何使用上下文类加载器传入架构位置。
EDIT:
编辑:
Per your comments:
根据您的评论:
http://download.oracle.com/javase/6/docs/api/javax/xml/bind/Marshaller.html#getSchema%28%29
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 set on the marshaller. That is why you can't get the property you want because it (the schema) doesn't exist.
如果在编组器上没有设置架构,getSchema() 将返回 null。这就是为什么您无法获得所需属性的原因,因为它(架构)不存在。