java xsd转换xml文件_JAXB—Java类与XML文件之间转换

JAXB—Java类与XML文件之间转换

简介

JAXB(Java Architecture for XML Binding) 是一个业界的标准,是一项可以根据XML Schema产生Java类的技术。该过程中,JAXB也提供了将XML实例文档反向生成Java对象树的方法,并能将Java对象树的内容重新写到XML实例文档。从另一方面来讲,JAXB提供了快速而简便的方法将XML模式绑定到Java表示,从而使得Java开发者在Java应用程序中能方便地结合XML数据和处理函数。

一、JAXB使用

一个简单的例子:

Person.class:

@XmlRootElement

public class Person {

private int id;

private String name;

private String gender;

private String addr;

private String area;

public Person() {

}

public Person(String name, String gender, String addr, String area) {

this.name = name;

this.gender = gender;

this.addr = addr;

this.area = area;

}

public int getId() {

return id;

}

@XmlElement

public void setId(int id) {

this.id = id;

}

public String getName() {

return name;

}

@XmlElement

public void setName(String name) {

this.name = name;

}

public String getGender() {

return gender;

}

@XmlElement

public void setGender(String gender) {

this.gender = gender;

}

public String getAddr() {

return addr;

}

@XmlElement

public void setAddr(String addr) {

this.addr = addr;

}

public String getArea() {

return area;

}

@XmlElement

public void setArea(String area) {

this.area = area;

}

@Override

public String toString() {

return "Person{" +

"id=" + id +

", name='" + name + '\'' +

", gender='" + gender + '\'' +

", addr='" + addr + '\'' +

", area='" + area + '\'' +

'}';

}

}

Test:

public class JAXBTest {

@Test

public void generateXML() {

Person person = new Person("abc", "男", "北京", "朝阳区");

File file = new File("E:\\person.xml");

JAXBContext jc = null;

try {

//根据Person类生成上下文对象

jc = JAXBContext.newInstance(Person.class);

//从上下文中获取Marshaller对象,用作将bean编组(转换)为xml

Marshaller ma = jc.createMarshaller();

//以下是为生成xml做的一些配置

//格式化输出,即按标签自动换行,否则就是一行输出

ma.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

//设置编码(默认编码就是utf-8)

ma.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");

//是否省略xml头信息,默认不省略(false)

ma.setProperty(Marshaller.JAXB_FRAGMENT, false);

//编组

ma.marshal(person, file);

} catch (JAXBException e) {

e.printStackTrace();

}

}

@Test

public void generateBean() {

File file = new File("E:\\person.xml");

JAXBContext jc = null;

try {

jc = JAXBContext.newInstance(Person.class);

Unmarshaller uma = jc.createUnmarshaller();

Person person = (Person) uma.unmarshal(file);

System.out.println(person);

} catch (JAXBException e) {

e.printStackTrace();

}

}

}

测试结果:

generateXML():

d858a993ee63addf3b2622ecf43e8a03.png

此xml相当于该xsd文件:

generateBean():

9eab6d2ab1acc9e49908ed38d152436d.png

注:从jdk1.7开始,JAXB就对解组和编组的方法进行了更简单的封装,所以实际项目中除非自己要进行个性化设置,否则大可不用自己再创建JAXBContext实例,直接通过JAXB静态调用相应的工具方法就行了,于是上面的测试方法可以写的更简练些:

public class JAXBTest {

@Test

public void generateXML() {

Person person = new Person("abc", "男", "北京", "朝阳区");

File file = new File("E:\\person.xml");

JAXB.marshal(person, file);

}

@Test

public void generateBean() {

File file = new File("E:\\person.xml");

Person person = JAXB.unmarshal(file, Person.class);

System.out.println(person);

}

}

二、JAXB常用注解

1、@XmlRootElement:

(1)作用和用法:

类级别的注解,将类映射为xml全局元素,也就是根元素。就像spring配置文件中的beans。

上面的例子中我将该注解用在了person类上,生成了根元素。常与@XmlType,@XmlAccessorType,@XmlAccessorOrder连用。

(2)属性:

该注解含有name和namespace两个属性。namespace属性用于指定生成的元素所属的命名空间。name属性用于指定生成元素的名字,若不指定则默认使用类名小写作为元素名。

修改上面的例子,在该注解上使用name属性:

@XmlRootElement(name = "human")

public class Person {

private int id;

private String name;

...

...

} //省略下面代码

生成的xml:

4294426f32536ecaff64ef2480bcbd4e.png

2、@XmlElement

(1)作用和用法:

字段,方法,参数级别的注解。该注解可以将被注解的字段(非静态),或者被注解的get/set方法对应的字段映射为本地元素,也就是子元素。默认使用字段名或get/set方法去掉前缀剩下部分小写作为元素名(在字段名和get/set方法符合命名规范的情况下)。上面例子中,id、addr、name、gender、area都被映射成了元素的子元素。下文会配合@XmlAccessorType注解详细讲解该注解的用法。常与@XmlValue,@XmlJavaTypeAdapter,@XmlElementWrapper连用。

(2)属性:

该注解的属性常用的属性有有:name、nillable、required、namespace、defaultValue

name属性可以指定生成元素的名字,同@XmlRootElement注解的name属性一样,不再举例。

nillable属性可以指定元素的文本值是否可以为空,默认为false。修改上面例子:

@XmlElement(nillable = true)

public void setName(String name) {

this.name = name;

}

则生成的xsd(为了节省篇幅,只截取必要的片段)为:

required属性可以指定该元素是否必须出现,默认为false,所以在xsd中会有对应的属性minOccurs="0"。修改该属性为true

@XmlElement(nillable = true, required = true)

public void setName(String name) {

this.name = name;

}

生成的xsd文件为:

namespace属性可以指定该元素所属的命名空间

defaultValue属性可以指定该元素默认的文本值

3、@XmlAttribute

(1)作用和用法:

字段和方法级别的注解。该注解会将字段或get/set方法对应的字段映射成本类对应元素的属性,属性名默认使用字段名或get/set方法去掉前缀剩下部分首字母小写(在字段名和get/set方法符合命名规范的情况下)。

修改上面例子:

@XmlAttribute

public void setGender(String gender) {

this.gender = gender;

}

生成的xml:

904d19785cf109558334694197ac8431.png

对应的xsd:

(2)属性:

该注解有name,required,namespace三个属性。用法和@XmlElement注解相同,不再举例,可以自己尝试下。

4、@XmlTransient

(1)作用和用法:

类,字段,方法级别的注解。可使JAXB在映射xml元素时忽略被注解的类,字段,get/set对应字段。需要注意的是该注解与所有其他JAXB注释相互排斥,也就是说与其他注释连用就会报错。

修改上面例子:

@XmlTransient

public void setId(int id) {

this.id = id;

}

生成的xml:

90779e65c93f072902c94890af19298e.png

(2)属性:

该注解没有属性。

5、@XmlAccessorType

(1)作用和用法:

包和类级别的注解。javaEE的API对该注解的解释是:控制字段是否被默认序列化。通俗来讲,就是决定哪些字段或哪些get/set方法对应的字段会被映射为xml元素,需要注意的是字段或get/set方法的访问权限(public/private)会影响字段是否被映射为xml元素,下面会详细讲解。

(2)属性:

该注解只有一个value属性,可取的值是一个名为XmlAccessType的枚举类型里的值,下面详细看一下这几个值分别有什么用:

XmlAccessType.PROPERTY

XmlAccessType.FIELD

XmlAccessType.PUBLIC_MEMBER (该值为默认值)

XmlAccessType.NONE

6、@XmlAccessorOrder

(1)作用和用法:

包和类级别的注解。控制生成元素的顺序。

(2)属性:

只有一个value属性,可取的值是一个名为XmlAccessOrder的枚举类型的两个值,XmlAccessOrder.ALPHABETICAL 和 XmlAccessOrder.UNDEFINED。默认为XmlAccessOrder.UNDEFINED,代表按照类中字段的顺序生成元素的顺序。

另一个值则代表按照字母表的顺序对生成的元素排序。但奇怪的是,只有jaxb按照field生成元素时,默认值才会生效,否则总是按照字母表的顺序排序。

7、@XmlElementWrapper

(1)作用和用法:

字段和方法级别的注解。围绕被映射的xml元素生成包装元素。主要用在集合对象映射后生成包装映射结果的xml元素。

修改上面的例子,添加一个Key类,在Person类中添加一个Key类的Set集合,修改如下:

Key类:

@XmlRootElement

public class Key {

private String roomNum;

public Key() {

}

public Key(String roomNum) {

this.roomNum = roomNum;

}

public String getRoomNum() {

return roomNum;

}

@XmlElement

public void setRoomNum(String roomNum) {

this.roomNum = roomNum;

}

@Override

public String toString() {

return "Key{" +

"roomNum='" + roomNum + '\'' +

'}';

}

}

Person类:

@XmlRootElement(name = "human")

@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)

@XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL)

public class Person {

...

private Set key = new HashSet<>();

public Person() {

}

public Person(String name, String gender, String addr, String area) {

this.name = name;

this.gender = gender;

this.addr = addr;

this.area = area;

key.add(new Key("001")); //向集合中添加两个Key对象

key.add(new Key("002"));

}

...

public Set getKey() {

return key;

}

@XmlElement

public void setKey(Set key) {

this.key = key;

}

}

生成的xml:

97cc40050a37eb749b8ca3d3278b2bfa.png

但同一元素应该需要被“包装”一下才显得有层次感,所以可以使用@XmlElementWrapper来实现:

@XmlElementWrapper(name = "keys")

@XmlElement

public void setKey(Set key) {

this.key = key;

}

生成的xml:

83f91ab061f35252cac301d2c92e48ad.png

(2)属性:

该注解有name、nillable、namespace、required四个属性,用法同上,不再赘述。

8、@XmlJavaTypeAdapter

(1)作用和用法:

包、类、字段,方法、参数级别的注解。解决java日期(Date),数字(Number)格式化问题。直接看例子,修改Person类,添加一个Date类型字段:

Person类:

@XmlRootElement(name = "human")

/*@XmlType(propOrder = {

"name",

"gender",

"addr",

"area"

})*/

@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)

@XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL)

public class Person {

...

private Date date = new Date();

...

public Date getDate() {

return date;

}

@XmlElement

public void setDate(Date date) {

this.date = date;

}

}

生成的xml:

ed52eeea147c1a0165cf2101505cd6a0.png

这样的date格式显然令人不满意,我们需要例如“2018-05-20”这样的格式。这就需要@XmlJavaTypeAdapter注解,自定义一个适配器来解决这个问题。该注解的用法就是自定义适配器并继承XmlAdapter类,实现里面的marshal和unmarshal方法,并在该注解上引用。修改例子:

自定义的DateAdapter:

public class DateAdapter extends XmlAdapter {

private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd");

@Override

public Date unmarshal(String date) throws Exception {

return SDF.parse(date);

}

@Override

public String marshal(Date date) throws Exception {

return SDF.format(date);

}

}

Person类:

@XmlJavaTypeAdapter(DateAdapter.class)

@XmlElement

public void setDate(Date date) {

this.date = date;

}

生成的xml:

5027c387cb19c0156c70a95351c299af.png

完美解决。

(2)属性:

常用的就是value属性,其他属性请自行研究。

9、@XmlValue:

(1)作用和用法:

字段和方法级别的注解。该注解的作用,简单理解就是定义xml元素文本值的类型,例如在一个类的String类型字段上使用该注解,则生成的元素文本值类型就是xsd:string,也就是定义一个xsd中的simpleType.若类中还有一个字段并使用了@XmlAttribute注解,则是定义一个xsd中的complexType。

(2)属性:

10、@XmlType:

(1)作用和用法:

类级别的注解。该注解有些复杂,主要使用的是它的propOrder属性,简单来说是用来定义xsd中的simpleType或complexType,从生成的xml中来看,它的作用就是指定生成元素的顺序,具体看下图:

25084c14c4b7a934dd34a7905b47c5e8.png

简单解释下每行什么意思:

若指定该注解的propOrder为{},会生成ComplexType并且使用xs:all指示器,表示所有被映射的元素都必须出现在xml中

若propOrder的值为{"name", "addr", "area"}(大括号中都是Person类的字段名称),会生成ComplexType并使用xs:sequence指示器,表示生成的xml元素必须按照propOrder指定的顺序出现,也就间接实现了排序。

若不指定propOrder属性(这与指定propOrder但值为{}不同),没有字段,会生成ComplexType并包含一个空的xs:sequence指示器。

若不指定propOrder属性,但含有被@XmlValue注解的字段和被@XmlAttribute注解的字段,会生成一个含有simpleContent的ComplexType。

若不指定propOrder属性,但含有被@XmlValue注解的字段而没有被@XmlAttribute注解的字段,会生成一个含有simpleType的ComplexType。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用Java中的JAXBJava Architecture for XML Binding)库来根据XSD文件生成XMLJAXBJava EE的一部分,可以将Java对象映射到XML文档,并提供了在Java对象和XML文档之间进行转换的方法。 以下是使用JAXB生成XML的基本步骤: 1. 创建一个Java,该的属性对应于XSD文件中的元素和型。 2. 使用JAXB的XJC工具从XSD文件生成Java。这可以通过在命令行中使用xjc命令或在Eclipse中使用插件来完成。 3. 在Java代码中创建JAXBContext对象,该对象负责将Java对象转换XML文档。 4. 创建Java对象,并设置其属性。 5. 使用JAXB Marshaller将Java对象转换XML文档。 以下是一个简单的示例代码: ```java import javax.xml.bind.*; import java.io.*; public class GenerateXML { public static void main(String[] args) throws JAXBException, IOException { // 创建JAXBContext对象 JAXBContext jaxbContext = JAXBContext.newInstance(Person.class); // 创建Marshaller对象 Marshaller marshaller = jaxbContext.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // 创建Java对象 Person person = new Person(); person.setName("John Doe"); person.setAge(30); // 将Java对象转换XML文档 StringWriter writer = new StringWriter(); marshaller.marshal(person, writer); String xml = writer.toString(); System.out.println(xml); } } @XmlRootElement class Person { private String name; private int age; // getters and setters } ``` 在上面的示例中,我们创建了一个名为Person的Java,并使用@XmlRootElement注解将其标记为根元素。然后,我们使用JAXBContext和Marshaller对象将Java对象转换XML文档。最后,我们使用StringWriter将XML文档输出到控制台。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值