JAXB体验之旅第二篇:unmarshal
来源:互联网 发布:linux访问https地址 编辑:程序博客网 时间:2024/05/01 15:56
例子1:
xml schema:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="book">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="author" type="xsd:string"/>
<xsd:element name="ISBN" type="xsd:int"/>
<xsd:element name="publisher" type="xsd:string"/>
<xsd:element name="edition" type="xsd:int"/>
<xsd:element type="xsd:double" name="price"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
对应xml 文档:
<?xml version="1.0" encoding="UTF-8"?>
<book xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="src/simple.xsd">
<name>hello china</name>
<author>owen</author>
<ISBN>1860</ISBN>
<publisher>objectiva</publisher>
<edition>1</edition>
<price>10.0</price>
</book>
解析类:
/*************************the code can make sure the root element of XML document automatically
JAXBContext context = JAXBContext.newInstance("com.objectiva.JAXBTesting.book");
Unmarshaller unMarshaller = context.createUnmarshaller();
Object object = unMarshaller.unmarshal(new File("simple.xml"));
if(object instanceof Book)
{
System.out.println(((Book)object).getName());
System.out.println(((Book)object).getPublisher());
System.out.println(((Book)object).getAuthor());
System.out.println(((Book)object).getISBN());
System.out.println(((Book)object).getEdition());
}
******************************************************/
这个例子Unmarshalle.unmarshal方法返回的就是实际的xml文档根元素类型实例。
例子2:
xml schema:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="book" type="BookType"></xsd:element>
<xsd:complexType name="BookType">
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="author" type="xsd:string"/>
<xsd:element name="ISBN" type="xsd:int"/>
<xsd:element name="publisher" type="xsd:string"/>
<xsd:element name="edition" type="xsd:int"/>
<xsd:element type="xsd:double" name="price"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="comment" type="xsd:string"/>
</xsd:schema>
对应xml 文档:
<?xml version="1.0" encoding="UTF-8"?>
<book xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="simpleTest.xsd">
<name>effective java</name>
<author>ruly</author>
<ISBN>10086</ISBN>
<publisher>o'Reily</publisher>
<edition>1</edition>
<price>50.0</price>
</book>
解析类:
/*************************the code can't make sure the root element of XML document automatically**/
JAXBContext context = JAXBContext.newInstance("com.objectiva.JAXBTesting.book");
Unmarshaller unMarshaller = context.createUnmarshaller();
Object object = unMarshaller.unmarshal(new File("simpleTest.xml"));
System.out.println(((JAXBElement<BookType>)object).getValue().getName());
/*************************************************************/
这个例子解析后实际返回的是JAXBElement类型的一个实例。
分析后得出:在第一个例子中,JAXB框架可以根据xml schema确定出xml文档的根元素,因为在解析时可以直接返回根元素类型的实例。而在第二个例子中,JAXB框架无法确定xml文档的根元素,因此在解析时就只能返回JAXBElement类型的实例了。在第一个例子中,生成的java类中可以看到@XmlRootElement(name = "book") anonation,但是第二个例子就没有。这样正好印证了API所说:
Note that when the root element name is unknown and the root element has an @xsi:type, the XML data is unmarshalled using that JAXB mapped class as the value of a
JAXBElement
.至此xml 文档的unmarshal操作就算结束了,xml文档的内容已经装载到java对象里程序可以直接操作了。
自己研究中参考了(http://weblogs.java.net/blog/kohsuke/archive/2006/03/why_does_jaxb_p.html),对自己理解帮助颇大:
Why does JAXB put @XmlRootElement sometimes but not always?
isusanin asked in the JAXB forum:
When trying to marshall an object I get this error message:
unable to marshal type "org.blah.MessageType" as an element
because it is missing an @XmlRootElement annotationIf I add the @XmlRootElement annotation to the MessageType, it works,but my question is why doesn't the JAXB compiler put this annotation inautomatically. It's inconvenient because MessageType is automaticallygenerated and I don't want to edit it every time I regenerate the javaclasses.
Is there any better way to resolve this problem?
XJC does try to put @XmlRootElement annotation on a class that wegenerate from a complex type. The exact condition is somewhat ugly, butthe basic idea is that if we can statically guarantee that a complextype won't be used by multiple different tag names, we put@XmlRootElement. So for example, if the schema is as follows:
<br>&lt;schema&gt;<br> &lt;element name="foo"&gt;<br> &lt;complexType&gt;<br> ...<br> &lt;/complexType&gt;<br> &lt;/element&gt;<br>&lt;/schema&gt;<br>
Then you'd get:
@XmlRootElementBut if the schema is as follows, then XJC can't eliminate thepossibility that your type might be used in other schemas (that can becompiled separately and put together at runtime):
class Foo {
...
}
<br>&lt;schema&gt;<br> &lt;element name="foo" type="bar" /&gt;<br> &lt;complexType name="bar" /&gt;<br>&lt;/schema&gt;<br>
So you'd get:
class Bar {
}
class ObjectFactory {
JAXBElement<Bar> createFoo(Bar value) { ... }
}
Now, the crucial part in the above inference done by XJC is that "your schema might be used by other schemas that XJC isn't compiling right now".This is certainly true for some users (and we learned that the hardway), but it's also true that for many users this is too conservativean assumption. It's often the case that what you are compiling isindeed the whole thing, and you want XJC to know that so that it canoptimize the generated code more aggressively.
Such notion isn't defined in the spec, but as an experiment wehave such aggressive optimization mode in XJC, tentatively called"simple-minded binding mode". Consider the following schema that usesthis mode (see that <xjc:simple/> customization):
<br>&lt;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"<br> xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"<br> jaxb:version="1.0"<br> xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"<br> jaxb:extensionBindingPrefixes="xjc"&gt;<br> &lt;xs:annotation&gt;<br> &lt;xs:appinfo&gt;<br> &lt;jaxb:globalBindings&gt;<br> &lt;xjc:simple /&gt;<br> &lt;/jaxb:globalBindings&gt;<br> &lt;/xs:appinfo&gt;<br> &lt;/xs:annotation&gt;<br> <br> &lt;xs:element name="foo" type="bar" /&gt;<br> &lt;xs:complexType name="bar" /&gt;<br>&lt;/xs:schema&gt;<br>
From this you'll just get Foo class, since XJC now knows that only one element is using bar,and therefore there's no point in having two of them around (I justfixed a few issues wrt this, so if you want to try it, wait untiltomorrow and download nightly.) Also note that this is an experimental mode and it is subject to change.
Now, that said, there's another way to work around this issue. If all you want is just to marshal an object without @XmlRootElement, then you can just do:
marshaller.marshal( new JAXBElement(
new QName("uri","local"), MessageType.class, messageType ));
- JAXB体验之旅第二篇:unmarshal
- JAXB体验之旅第三篇:marshal
- JAXB unmarshal with Schema Validation
- A generic JAXB marshal/unmarshal XmlType
- JAXB使用经验总结 unmarshal与marshal
- JAXB初体验之错误解决
- JAXB体验之旅第一篇:基于xml schema产生java类
- jaxb 使用 之 marshal
- jaxb 使用之 unmarshall
- JAXB之helloworld
- JAXB学习之注解
- 实习生活第二篇,工作体验。
- Java与XML联合编程之JDOM/JAXB篇
- C#锐利体验之第二讲 C#语言基础介绍
- 第二周项目3体验复杂度之汉诺塔问题
- 数据结构第二周项目3(2)--体验复杂度之汉诺塔
- 数据结构第二周项目--体验复杂度之汉诺塔
- 数据结构第二周项目-体验复杂度之汉诺塔
- sqlite3嵌入式数据库的移植
- 居然问到了8queen的问题....
- Hibernate获取数据方式与缓存使用
- delphi7,播放音乐
- 深入理解C语言指针的奥秘(转)
- JAXB体验之旅第二篇:unmarshal
- 利用 ASP.NET 的内置功能抵御 Web 攻击
- List与ArrayList区别
- poj1607
- 在.NET应用程序中不注册使用ocx Com组件
- NetBeans 时事通讯(刊号 # 17 - Jul 22, 2008 )
- ASP.NET AJAX客户端编程
- DB2 V8.2库还原到V8.2.7需手工绑定db2schema包(SQL0443N)
- c++成员初始化(做个笔记)