使用JAXB来处理XML文件(JavaBean和xml互转)

最近在研究公司的工作流(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使用上的粗浅理解,未深究,欢迎留言交流。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冷风在北京

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值