本文探讨的问题是:如果你已经有了Java类,比如一些POJO类,如何把它们转换为XML?
这里需要用到JAXB的技术,关于JAXB的介绍,请参考《JAXB介绍》,本文不再赘述。
从Java到XML的过程,用专业的术语表示就是Marshal。
1. 创建POJO类
(1)Company.java
package java2xml;
import java.io.ByteArrayOutputStream;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@XmlType(namespace = "http://myNameSpace")
@XmlRootElement(name = "Corporation")
public class Company {
private String name;
@XmlElement
private List employees;
public Company() {
}
@XmlElement
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List getEmployees() {
return EmpManager.getEmpManager().getEmps();
}
public void setEmployees() {
EmpManager.getEmpManager().resetData();
}
}
注意,原来加在属性name上的批注@XmlElement,改到加在方法getName()上。
如果不改的话,执行schemagen.exe时会抛出如下异常:
com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
Class has two properties of the same name "name"
this problem is related to the following location:
at public java.lang.String java2xml.Company.getName()
at java2xml.Company
this problem is related to the following location:
at private java.lang.String java2xml.Company.name
at java2xml.Company
(2)Emp.java
比较简单,从略。
2. 运行schemagen.exe 生成 XML Schema
在JDK的bin目录下有一个命令:schemagen.exe,运行如下脚本生成XML Schema:
schemagen.exe -d D:\JDevRuntime\JDev11117\mywork\Java2Xml\Java2Xml\src -cp D:\JDevRuntime\JDev11117\mywork\Java2Xml\Java2XML\classes java2xml.Company java2xml.Emp
schemagen.exe -d D:\JDevRuntime\JDev11117\mywork\Java2Xml\Java2Xml\src -cp D:\JDevRuntime\JDev11117\mywork\Java2Xml\Java2XML\classes java2xml.Company java2xml.Emp
会生成两个xsd文件:
(1)schema1.xsd
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" targetNamespace="http://myNameSpace" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:import schemaLocation="schema2.xsd"/>
<xs:complexType name="company">
<xs:sequence>
<xs:element name="employees" type="emp" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="name" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
(2)schema2.xsd
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" xmlns:ns1="http://myNameSpace" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:import namespace="http://myNameSpace" schemaLocation="schema1.xsd"/>
<xs:element name="Corporation" type="ns1:company"/>
<xs:complexType name="emp">
<xs:sequence>
<xs:element name="comm" type="xs:double" minOccurs="0"/>
<xs:element name="deptno" type="xs:long" minOccurs="0"/>
<xs:element name="empno" type="xs:long" minOccurs="0"/>
<xs:element name="ename" type="xs:string" minOccurs="0"/>
<xs:element name="job" type="xs:string" minOccurs="0"/>
<xs:element name="mgr" type="xs:long" minOccurs="0"/>
<xs:element name="sal" type="xs:double" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
3. 生成JAXB对象
(1)右键schema1.xsd,选择“Generate JAXB 2.0 Content Model”:
(2)为了不与原来的POJO类冲突,这里放到另一个目录
4. 修改自动生成的POJO类
(1)在Company.java中增加如下方法:
public Company() {
resetData();
}
public void resetData() {
createEmp((long)7369, "SMITH", "CLERK", (long)7902, (double)800, null,
(long)20);
createEmp((long)7499, "ALLEN", "SALESMAN", (long)7698, (double)1600,
(double)300, (long)30);
createEmp((long)7521, "WARD", "SALESMAN", (long)7698, (double)1250,
(double)500, (long)30);
createEmp((long)7566, "JONES", "MANAGER", (long)7839, (double)2975,
null, (long)20);
createEmp((long)7654, "MARTIN", "SALESMAN", (long)7698, (double)1250,
(double)1400, (long)30);
createEmp((long)7698, "BLAKE", "MANAGER", (long)7839, (double)2850,
null, (long)30);
createEmp((long)7782, "CLARK", "MANAGER", (long)7839, (double)2450,
null, (long)10);
createEmp((long)7788, "SCOTT", "ANALYST", (long)7566, (double)3000,
null, (long)20);
createEmp((long)7839, "KING", "PRESIDENT", null, (double)5000, null,
(long)10);
createEmp((long)7844, "TURNER", "SALESMAN", (long)7698, (double)1500,
(double)0, (long)30);
createEmp((long)7876, "ADAMS", "CLERK", (long)7788, (double)1100, null,
(long)20);
createEmp((long)7900, "JAMES", "CLERK", (long)7698, (double)950, null,
(long)30);
createEmp((long)7902, "FORD", "ANALYST", (long)7566, (double)3000,
null, (long)20);
createEmp((long)7934, "MILLER", "CLERK", (long)7782, (double)1300,
null, (long)10);
}
public void createEmp(Long empno, String ename, String job, Long mgr,
Double sal, Double comm, Long deptno) {
Emp newEmp = new ObjectFactory().createEmp();
newEmp.update(empno, ename, job, mgr, sal, comm, deptno);
getEmployees().add(newEmp);
}
public static void main(String[] args) throws JAXBException {
JAXBContext jaxbContext = JAXBContext.newInstance("java2xml.generated");
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty("jaxb.formatted.output", Boolean.TRUE);
ObjectFactory objf = new ObjectFactory();
Company company = objf.createCompany();
company.setName("Ma Ping and Friends");
marshaller.marshal(company, System.out);
}
main函数中使用了Marshaller对象,使用ObjectFactory创建了Company对象,然后marshal该对象并输出。
(2)在Emp.java中增加如下方法:
public void update(Long empno, String ename, String job, Long mgr,
Double sal, Double comm, Long deptno) {
this.empno = empno;
this.ename = ename;
this.job = job;
this.mgr = mgr;
this.sal = sal;
this.comm = comm;
this.deptno = deptno;
}
5. 运行修改后的Company.java
输出的XML内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<Corporation xmlns:ns0="http://myNameSpace">
<employees>
<deptno>20</deptno>
<empno>7369</empno>
<ename>SMITH</ename>
<job>CLERK</job>
<mgr>7902</mgr>
<sal>800.0</sal>
</employees>
<employees>
<comm>300.0</comm>
<deptno>30</deptno>
<empno>7499</empno>
<ename>ALLEN</ename>
<job>SALESMAN</job>
<mgr>7698</mgr>
<sal>1600.0</sal>
</employees>
<employees>
<comm>500.0</comm>
<deptno>30</deptno>
<empno>7521</empno>
<ename>WARD</ename>
<job>SALESMAN</job>
<mgr>7698</mgr>
<sal>1250.0</sal>
</employees>
<employees>
<deptno>20</deptno>
<empno>7566</empno>
<ename>JONES</ename>
<job>MANAGER</job>
<mgr>7839</mgr>
<sal>2975.0</sal>
</employees>
<employees>
<comm>1400.0</comm>
<deptno>30</deptno>
<empno>7654</empno>
<ename>MARTIN</ename>
<job>SALESMAN</job>
<mgr>7698</mgr>
<sal>1250.0</sal>
</employees>
<employees>
<deptno>30</deptno>
<empno>7698</empno>
<ename>BLAKE</ename>
<job>MANAGER</job>
<mgr>7839</mgr>
<sal>2850.0</sal>
</employees>
<employees>
<deptno>10</deptno>
<empno>7782</empno>
<ename>CLARK</ename>
<job>MANAGER</job>
<mgr>7839</mgr>
<sal>2450.0</sal>
</employees>
<employees>
<deptno>20</deptno>
<empno>7788</empno>
<ename>SCOTT</ename>
<job>ANALYST</job>
<mgr>7566</mgr>
<sal>3000.0</sal>
</employees>
<employees>
<deptno>10</deptno>
<empno>7839</empno>
<ename>KING</ename>
<job>PRESIDENT</job>
<sal>5000.0</sal>
</employees>
<employees>
<comm>0.0</comm>
<deptno>30</deptno>
<empno>7844</empno>
<ename>TURNER</ename>
<job>SALESMAN</job>
<mgr>7698</mgr>
<sal>1500.0</sal>
</employees>
<employees>
<deptno>20</deptno>
<empno>7876</empno>
<ename>ADAMS</ename>
<job>CLERK</job>
<mgr>7788</mgr>
<sal>1100.0</sal>
</employees>
<employees>
<deptno>30</deptno>
<empno>7900</empno>
<ename>JAMES</ename>
<job>CLERK</job>
<mgr>7698</mgr>
<sal>950.0</sal>
</employees>
<employees>
<deptno>20</deptno>
<empno>7902</empno>
<ename>FORD</ename>
<job>ANALYST</job>
<mgr>7566</mgr>
<sal>3000.0</sal>
</employees>
<employees>
<deptno>10</deptno>
<empno>7934</empno>
<ename>MILLER</ename>
<job>CLERK</job>
<mgr>7782</mgr>
<sal>1300.0</sal>
</employees>
<name>Ma Ping and Friends</name>
</Corporation>
小结:实际应用中,为了能够让原始的POJO类和自动生成的同名POJO类不冲突,需要写包装类CompanyWrapper,EmpWrapper,这样所有的操作都统一针对Wrapper类的操作。
Project 下载:Java2Xml.7z
参考文献:
1. http://technology.amis.nl/2011/06/24/creating-an-xml-document-based-on-my-pojo-domain-model-how-will-jaxb-help-me/
2. http://technology.amis.nl/2011/06/25/turning-any-xml-document-into-java-object-graph-using-jaxb-2-0/
3. http://technology.amis.nl/2008/06/15/how-to-quickly-generate-an-xsd-xml-schema-definition-based-on-a-java-class-model-using-jdeveloper-11g/
4. http://www.developer.com/services/article.php/3722211/Using-JAXB-in-JDeveloper-1013.htm
5. http://biemond.blogspot.com/2008/02/jaxb-20-in-jdeveloper-10g-and-11g.html
没有评论:
发表评论