最近在研究公司的工作流(xml格式),利用java类去处理xml,包括对xml的节点值进行修改、新建xml节点的等。这就需要先生成xml对应的java类,此时JAXB就派上用场了。
生成java类之前,先准备xml文件。
假设是这样:workflow.xml
<?xml version="1.0" encoding="UTF-8"?>
<flowstep stepname="第一次审核" steptype="1">
<userid>tom</userid>
<username>汤姆</username>
<sonflow>
<userid>someone</userid>
</sonflow>
</flowstep>
将这个xml转换成对应的java类之前,
先需要它的XSD( XML Schemas Definition),这里我们先下载一个trang.jar文件。
一 下载 trang.jar
1.百度搜索关键词 trang.jar maven;
2.打开搜索结果中maven那一条;
点击红色区域,即可下载。
3.将trang.jar放在某个路径下,假设D盘根目录。
4.将workflow.xml放在c盘的user\用户名 目录下。
5.执行cmd命令:java -jar D:\trang.jar workflow.xml workflow.xsd
这样,在xml同级目录下,就生成了需要的xsd文件。
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="flowstep">
<xs:complexType>
<xs:complexContent>
<xs:extension base="userid">
<xs:sequence>
<xs:element ref="username"/>
<xs:element ref="sonflow"/>
</xs:sequence>
<xs:attribute name="stepname" use="required" type="xs:NCName"/>
<xs:attribute name="steptype" use="required" type="xs:integer"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:element name="username" type="xs:NCName"/>
<xs:element name="sonflow" type="userid"/>
<xs:complexType name="userid">
<xs:sequence>
<xs:element ref="userid"/>
</xs:sequence>
</xs:complexType>
<xs:element name="userid" type="xs:NCName"/>
</xs:schema>
二、转成java类文件
1.下载 jaxb-ri 包文件,并解压到本地。
2. 将上一步生成的 workflow.xsd 文件拷贝到该目录下。
3. 在此目录下新建需要生成的java类的文件夹,例如 java。
4. 用cmd命令进入到 jaxb-ri\lib 目录。
5. 运行 xjc -d java workflow.xsd 命令。
三、java类的使用
将生成的javaBean放到某个目录下。另外,需要一个类JaxbMapper把xml文件和javaBean联系起来。
最后需要一个测试类 testMain.java.
工程里的JaxbMapper.java文件
package test.jaxb;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.namespace.QName;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.springside.modules.utils.Exceptions;
import org.springside.modules.utils.Reflections;
import com.sun.xml.bind.marshaller.CharacterEscapeHandler;
/**
* 使用Jaxb2.0实现XML<->Java Object的Mapper.
*
* 在创建时�?要设定所有需要序列化的Root对象的Class. 特别支持Root对象是Collection的情�?.
*
* @author calvin
*/
public class JaxbMapper {
private static ConcurrentMap<Class, JAXBContext> jaxbContexts = new ConcurrentHashMap<Class, JAXBContext>();
/**
* Java Object->Xml without encoding.
*/
public static String toXml(Object root) {
Class clazz = Reflections.getUserClass(root);
return toXml(root, clazz, null);
}
/**
* Java Object->Xml with encoding.
*/
public static String toXml(Object root, String encoding) {
Class clazz = Reflections.getUserClass(root);
return toXml(root, clazz, encoding);
}
/**
* Java Object->Xml with encoding.
*/
public static String toXml(Object root, Class clazz, String encoding) {
try {
StringWriter writer = new StringWriter();
createMarshaller(clazz, encoding).marshal(root, writer);
return writer.toString();
} catch (JAXBException e) {
throw Exceptions.unchecked(e);
}
}
/**
* Java Collection->Xml without encoding, 特别支持Root Element是Collection的情�?.
*/
public static String toXml(Collection<?> root, String rootName, Class clazz) {
return toXml(root, rootName, clazz, null);
}
/**
* Java Collection->Xml with encoding, 特别支持Root Element是Collection的情�?.
*/
public static String toXml(Collection<?> root, String rootName, Class clazz, String encoding) {
try {
CollectionWrapper wrapper = new CollectionWrapper();
wrapper.collection = root;
JAXBElement<CollectionWrapper> wrapperElement = new JAXBElement<CollectionWrapper>(new QName(rootName), CollectionWrapper.class, wrapper);
StringWriter writer = new StringWriter();
createMarshaller(clazz, encoding).marshal(wrapperElement, writer);
return writer.toString();
} catch (JAXBException e) {
throw Exceptions.unchecked(e);
}
}
/**
* Xml->Java Object.
*/
public static <T> T fromXml(String xml, Class<T> clazz) {
try {
StringReader reader = new StringReader(xml);
return (T) createUnmarshaller(clazz).unmarshal(reader);
} catch (JAXBException e) {
throw Exceptions.unchecked(e);
}
}
/**
* 创建Marshaller并设定encoding(可为null). 线程不安全,�?要每次创建或pooling�?
*/
public static Marshaller createMarshaller(Class clazz, String encoding) {
try {
JAXBContext jaxbContext = getJaxbContext(clazz);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
if (StringUtils.isNotBlank(encoding)) {
marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding);
}
marshaller.setProperty(CharacterEscapeHandler.class.getName(), new CharacterEscapeHandler() {
@Override
public void escape(char[] ac, int i, int j, boolean flag, Writer writer) throws IOException {
writer.write(ac, i, j);
}
});
return marshaller;
} catch (JAXBException e) {
throw Exceptions.unchecked(e);
}
}
/**
* 创建UnMarshaller. 线程不安全,�?要每次创建或pooling�?
*/
public static Unmarshaller createUnmarshaller(Class clazz) {
try {
JAXBContext jaxbContext = getJaxbContext(clazz);
return jaxbContext.createUnmarshaller();
} catch (JAXBException e) {
throw Exceptions.unchecked(e);
}
}
protected static JAXBContext getJaxbContext(Class clazz) {
Validate.notNull(clazz, "'clazz' must not be null");
JAXBContext jaxbContext = jaxbContexts.get(clazz);
if (jaxbContext == null) {
try {
jaxbContext = JAXBContext.newInstance(clazz, CollectionWrapper.class);
jaxbContexts.putIfAbsent(clazz, jaxbContext);
} catch (JAXBException ex) {
throw new RuntimeException("Could not instantiate JAXBContext for class [" + clazz + "]: " + ex.getMessage(), ex);
}
}
return jaxbContext;
}
/**
* 封装Root Element �? Collection的情�?.
*/
public static class CollectionWrapper {
@XmlAnyElement
protected Collection<?> collection;
}
}
注:需要引入一个Spring的jar包。
<dependency>
<groupId>org.springside</groupId>
<artifactId>springside-core</artifactId>
<version>4.2.3-GA</version>
</dependency>
testMain.java
package test.jaxb;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class testMain {
public static void main(String[] args) throws IOException {
File xmlFile = new File("C:/Users/huangs/Desktop/workflow.xml");
FileInputStream is = new FileInputStream(xmlFile);
InputStreamReader in = new InputStreamReader(is,"UTF-8");
BufferedReader bf = new BufferedReader(in);
String valueString = null;
StringBuffer sb = new StringBuffer();
while ((valueString=bf.readLine())!=null){
sb.append(valueString+"\n");
}
System.out.println("原文:"+sb.toString());
Flowstep sp = JaxbMapper.fromXml(sb.toString(), Flowstep.class);
//修改xml对象
sp.setUserid("tomcat");
sp.setUsername("汤姆猫");
Userid ui = sp.getSonflow();
ui.setUserid("汤姆猫的小弟");
String ModifiedXml = JaxbMapper.toXml(sp);
System.out.println("修改后的xml:"+ModifiedXml);
}
}
运行后输出:
原文:<?xml version="1.0" encoding="UTF-8"?>
<flowstep stepname="第一次审核" steptype="1">
<userid>tom</userid>
<username>汤姆</username>
<sonflow>
<userid>someone</userid>
</sonflow>
</flowstep>
修改后的xml:<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<flowstep stepname="第一次审核" steptype="1">
<userid>tomcat</userid>
<username>汤姆猫</username>
<sonflow>
<userid>汤姆猫的小弟</userid>
</sonflow>
</flowstep>
上面是修改XML的代码,如果需要创建xml节点,可以new一个对象出来,再set值。
以上是对Jaxb使用上的粗浅理解,未深究,欢迎留言交流。