什么是JAXB? 不多解释,可以参见维基百科,亦或是百度百科。本文不会对基础部分进行讲解,因为我也没去细看,我只看了了他最简洁的应用方式(基于Annotaion),技术是项目服务,会用,能用好即可。本文主要给出一个Demo,并就JAXB生成xml文件的namespace的prefix不能自定义的问题进行解决。
直接来看代码,首先定义一个 Book类
package com.jaxb.first;
import java.util.ArrayList;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(namespace="abc")
public class Bookstore {
// XmLElementWrapper generates a wrapper element around XML representation
@XmlElementWrapper(name = "bookList")
// XmlElement sets the name of the entities
@XmlElement(name = "book")
private ArrayList<Book> bookList;
private String name;
private String location;
public void setBookList(ArrayList<Book> bookList) {
this.bookList = bookList;
}
public ArrayList<Book> getBooksList() {
return bookList;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
}
然后我们定义了一个BookStore来存储Book. 在BookStore中,我们引入了命名空间(namespace)
package com.jaxb.first;
import java.util.ArrayList;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(namespace="abc")
public class Bookstore {
// XmLElementWrapper generates a wrapper element around XML representation
@XmlElementWrapper(name = "bookList")
// XmlElement sets the name of the entities
@XmlElement(name = "book")
private ArrayList<Book> bookList;
private String name;
private String location;
public void setBookList(ArrayList<Book> bookList) {
this.bookList = bookList;
}
public ArrayList<Book> getBooksList() {
return bookList;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
}
接着,我们要写一个测试类,来完成Xml 和 BookStore对象的相互转换。
package com.jaxb.first;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import com.sun.xml.bind.marshaller.NamespacePrefixMapper;
public class BookMain {
private static final String BOOKSTORE_XML = "./bookstore-jaxb.xml";
public static void main(String[] args) throws JAXBException, IOException {
ArrayList<Book> bookList = new ArrayList<Book>();
// create books
Book book1 = new Book();
book1.setIsbn("978-0060554736");
book1.setName("The Game");
book1.setAuthor("Neil Strauss");
book1.setPublisher("Harpercollins");
bookList.add(book1);
Book book2 = new Book();
book2.setIsbn("978-3832180577");
book2.setName("Feuchtgebiete");
book2.setAuthor("Charlotte Roche");
book2.setPublisher("Dumont Buchverlag");
bookList.add(book2);
// create bookstore, assigning book
Bookstore bookstore = new Bookstore();
bookstore.setName("Fraport Bookstore");
bookstore.setLocation("Frankfurt Airport");
bookstore.setBookList(bookList);
// create JAXB context and instantiate marshaller
JAXBContext context = JAXBContext.newInstance(Bookstore.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.marshal(bookstore, System.out);
Writer w = null;
try {
w = new FileWriter(BOOKSTORE_XML);
m.marshal(bookstore, w);
} finally {
try {
w.close();
} catch (Exception e) {
}
}
// get variables from our xml file, created before
System.out.println();
System.out.println("Output from our XML File: ");
Unmarshaller um = context.createUnmarshaller();
Bookstore bookstore2 = (Bookstore) um.unmarshal(new FileReader(
BOOKSTORE_XML));
for (int i = 0; i < bookstore2.getBooksList().toArray().length; i++) {
System.out.println("Book " + (i + 1) + ": "
+ bookstore2.getBooksList().get(i).getName() + " from "
+ bookstore2.getBooksList().get(i).getAuthor());
}
}
}
OK, 整个代码都很简单,很容易理解。相关API我也不解释,可以自己Goole,或是Baidu.
看下运行结果
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:bookstore xmlns:ns2="abc">
<bookList>
<book>
<author>Neil Strauss</author>
<name>The Game</name>
<publisher>Harpercollins</publisher>
<isbn>978-0060554736</isbn>
</book>
<book>
<author>Charlotte Roche</author>
<name>Feuchtgebiete</name>
<publisher>Dumont Buchverlag</publisher>
<isbn>978-3832180577</isbn>
</book>
</bookList>
<location>Frankfurt Airport</location>
<name>Fraport Bookstore</name>
</ns2:bookstore>
Output from our XML File:
Book 1: The Game from Neil Strauss
Book 2: Feuchtgebiete from Charlotte Roche
我发现,在Bookstore在命名空间加了前缀,也就是ns2。 那么这个东西可以换成我自己想要的么? 笔者在网上搜索了这个问题很久,碰到这种问题的人相当的多,大多数都是说通过建package-info.java类来解决,笔者也按他们说的做了,但是丝毫没有反应。最后我在这找到了答案:http://stackoverflow.com/questions/2252028/jaxb-how-to-avoid-repeated-namespace-definition-for-xmlnsxsi
然后我查了相关资料,大致上好像是这样的:虽然JDK1.6虽然已经将JAXB做为一个标准和规范了,不过他提供的JAXB是1.0的。而在1.0中namespace的prefix问题是没办法解决的,因为我们要另外引入JAXB2.0.jar 并定义NamespacePrefixMapper,重写getPreferredPrefix()方法。 那么,我改动了一下代码,如入:
package com.jaxb.first;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import com.sun.xml.bind.marshaller.NamespacePrefixMapper;
public class BookMain {
private static final String BOOKSTORE_XML = "./bookstore-jaxb.xml";
public static void main(String[] args) throws JAXBException, IOException {
ArrayList<Book> bookList = new ArrayList<Book>();
// create books
Book book1 = new Book();
book1.setIsbn("978-0060554736");
book1.setName("The Game");
book1.setAuthor("Neil Strauss");
book1.setPublisher("Harpercollins");
bookList.add(book1);
Book book2 = new Book();
book2.setIsbn("978-3832180577");
book2.setName("Feuchtgebiete");
book2.setAuthor("Charlotte Roche");
book2.setPublisher("Dumont Buchverlag");
bookList.add(book2);
// create bookstore, assigning book
Bookstore bookstore = new Bookstore();
bookstore.setName("Fraport Bookstore");
bookstore.setLocation("Frankfurt Airport");
bookstore.setBookList(bookList);
// create JAXB context and instantiate marshaller
JAXBContext context = JAXBContext.newInstance(Bookstore.class);
Marshaller m = context.createMarshaller();
NamespacePrefixMapper mapper = new PreferredMapper();
m.setProperty("com.sun.xml.bind.namespacePrefixMapper", mapper);
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.marshal(bookstore, System.out);
Writer w = null;
try {
w = new FileWriter(BOOKSTORE_XML);
m.marshal(bookstore, w);
} finally {
try {
w.close();
} catch (Exception e) {
}
}
// get variables from our xml file, created before
System.out.println();
System.out.println("Output from our XML File: ");
Unmarshaller um = context.createUnmarshaller();
Bookstore bookstore2 = (Bookstore) um.unmarshal(new FileReader(
BOOKSTORE_XML));
for (int i = 0; i < bookstore2.getBooksList().toArray().length; i++) {
System.out.println("Book " + (i + 1) + ": "
+ bookstore2.getBooksList().get(i).getName() + " from "
+ bookstore2.getBooksList().get(i).getAuthor());
}
}
public static class PreferredMapper extends NamespacePrefixMapper {
@Override
public String getPreferredPrefix(String namespaceUri,
String suggestion, boolean requirePrefix) {
return "pre";
}
}
}
再看一下,输出结果:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<pre:bookstore xmlns:pre="abc">
<bookList>
<book>
<author>Neil Strauss</author>
<name>The Game</name>
<publisher>Harpercollins</publisher>
<isbn>978-0060554736</isbn>
</book>
<book>
<author>Charlotte Roche</author>
<name>Feuchtgebiete</name>
<publisher>Dumont Buchverlag</publisher>
<isbn>978-3832180577</isbn>
</book>
</bookList>
<location>Frankfurt Airport</location>
<name>Fraport Bookstore</name>
</pre:bookstore>
Output from our XML File:
Book 1: The Game from Neil Strauss
Book 2: Feuchtgebiete from Charlotte Roche
It works! 所以,我们的问题也就随之解决了。。我将整个Project放到我的CSDN资源中,地址如下:
http://download.csdn.net/detail/zl3450341/4739970