xStream转换XML

原文:http://www.cnblogs.com/hoojo/archive/2011/04/22/2025197.html

 

xStream框架

xStream可以轻易的将Java对象和xml文档相互转换,而且可以修改某个特定的属性和节点名称,而且也支持json的转换; 

前面有介绍过json-lib这个框架,在线博文:http://www.cnblogs.com/hoojo/archive/2011/04/21/2023805.html

以及Jackson这个框架,在线博文:http://www.cnblogs.com/hoojo/archive/2011/04/22/2024628.html 

它们都完美支持JSON,但是对xml的支持还不是很好。一定程度上限制了对Java对象的描述,不能让xml完全体现到对Java对象的描述。这里将会介绍xStream对JSON、XML的完美支持。xStream不仅对XML的转换非常友好,而且提供annotation注解,可以在JavaBean中完成对xml节点、属性的描述。以及对JSON也支持,只需要提供相关的JSONDriver就可以完成转换。

建议:xml的转换使用xStream框架;JSON的转换使用Jackson框架。

1. 准备工作 

1.1. 下载jar包、及官方资源 

xStream的jar下载地址: 

https://nexus.codehaus.org/content/repositories/releases/com/thoughtworks/xstream/xstream-distribution/1.3.1/xstream-distribution-1.3.1-bin.zip

官方的示例很全,官方参考示例:http://xstream.codehaus.org/tutorial.html 

添加xstream-1.3.1.jar文件到工程中,就可以开始下面的工作;

1.2. 需要的JavaBean

Birthday :

public class Birthday {
	private String birthday;

	public Birthday() {
	}

	public Birthday(String birthday) {
		this.birthday = birthday;
	}

	public String getBirthday() {
		return birthday;
	}

	public void setBirthday(String birthday) {
		this.birthday = birthday;
	}
}

Student :

public class Student {

	private int id;

	private String name;

	private String email;

	private String address;

	private Birthday birthday;

	// getter、setter

	public String toString() {
		return this.name + "#" + this.id + "#" + this.address + "#" + this.birthday + "#" + this.email;
	}

}

ListBean:

import java.util.List;

public class ListBean {

	private String name;
	private List<Object> list;

	// getter、setter
}

2. Java转换成XML

2.1. JavaBean转换XML

import com.thoughtworks.xstream.XStream;

/**
 * Java对象和XML字符串的相互转换
 */
public class WriteBean2XML {
	private static XStream xstream = new XStream();

	public static void main(String[] args) {
		Student bean = new Student();
		bean.setAddress("china");
		bean.setEmail("[email protected]");
		bean.setId(1);
		bean.setName("jack");
		Birthday day = new Birthday();
		day.setBirthday("2010-11-22");
		bean.setBirthday(day);
		System.out.println(xstream.toXML(bean));
		System.out.println();
		
		// 类重命名
		// xstream.alias("account", Student.class);
		// xstream.alias("生日", Birthday.class);
		// xstream.aliasField("生日", Student.class, "birthday");
		// xstream.aliasField("生日", Birthday.class, "birthday");
		// fail(xstream.toXML(bean));
		// 属性重命名
		xstream.aliasField("邮件", Student.class, "email");
		// 包重命名
		xstream.aliasPackage("", "test2");
		System.out.println(xstream.toXML(bean));
	}
}

通过XStream对象的toXML方法就可以完成Java对象到XML的转换,toXML方法还有2个相同签名的方法,需要传递一个流。然后通过流来完成xml信息的输出。

看结果中的第一份xml内容,是没有经过然后修改或重命名的文档,按照原样输出。文档中的第二份文档的package经过重命名,email属性也经过重命名以及类名也可以进行重命名的。 

运行后结果如下: 

<test2.Student>
  <id>1</id>
  <name>jack</name>
  <email>[email protected]</email>
  <address>china</address>
  <birthday>
    <birthday>2010-11-22</birthday>
  </birthday>
</test2.Student>

<Student>
  <id>1</id>
  <name>jack</name>
  <邮件>[email protected]</邮件>
  <address>china</address>
  <birthday>
    <birthday>2010-11-22</birthday>
  </birthday>
</Student>

2.2. 将List集合转换成xml文档

import java.util.ArrayList;
import java.util.List;

import com.thoughtworks.xstream.XStream;

/**
 * 将List集合转换成xml文档
 */
public class WriteList2XML {
	private static XStream xstream = new XStream();

	public static void main(String[] args) {
		try {
			ListBean listBean = new ListBean();
			listBean.setName("this is a List Collection");
			List<Object> list = new ArrayList<Object>();
			Student bean1 = new Student();
			bean1.setAddress("USA");
			bean1.setEmail("[email protected]");
			bean1.setId(2);
			bean1.setName("tom");
			Birthday day1 = new Birthday("2010-11-22");
			bean1.setBirthday(day1);
			list.add(bean1);
			Student bean2 = new Student();
			bean2.setAddress("china");
			bean2.setEmail("[email protected]");
			bean2.setId(2);
			bean2.setName("zhansan");
			Birthday day2 = new Birthday("2001-05-06");
			bean2.setBirthday(day2);
			list.add(bean2);
			list.add(bean2);
			listBean.setList(list);
			// 修改元素名称
			xstream.alias("beans", ListBean.class);
			xstream.alias("student", Student.class);
			// 将ListBean中的集合设置空元素,即不显示集合元素标签
			// xstream.addImplicitCollection(ListBean.class, "list");
			// 设置reference模型
			//xstream.setMode(XStream.NO_REFERENCES);//不引用
			xstream.setMode(XStream.ID_REFERENCES);// id引用
			// xstream.setMode(XStream.XPATH_ABSOLUTE_REFERENCES);//绝对路径引用
			// 将name设置为父类(Student)的元素的属性
			xstream.useAttributeFor(Student.class, "name");
			xstream.useAttributeFor(Birthday.class, "birthday");
			// 修改属性的name
			xstream.aliasAttribute("姓名", "name");
			xstream.aliasField("生日", Birthday.class, "birthday");
			System.out.println(xstream.toXML(listBean));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

运行后结果如下: 

<beans id="1">
  <name>this is a List Collection</name>
  <list id="2">
    <student id="3" 姓名="tom">
      <id>2</id>
      <email>[email protected]</email>
      <address>USA</address>
      <birthday id="4" 生日="2010-11-22"/>
    </student>
    <student id="5" 姓名="zhansan">
      <id>2</id>
      <email>[email protected]</email>
      <address>china</address>
      <birthday id="6" 生日="2001-05-06"/>
    </student>
    <student reference="5"/>
  </list>
</beans>

如果不加xstream.addImplicitCollection(ListBean.class, "list"); 

这个设置的话,会出现一个List节点包裹着Student节点元素。添加addImplicitCollection可以忽略这个list节点元素。那么上面的list节点就不存在,只会在beans元素中出现name、student这2个xml元素标签; 

setMode是设置相同的对象的引用方式,如果设置XStream.NO_REFERENCES就是不引用,会输出2分相同的 Student元素。如果是XStream.ID_REFERENCES会引用相同的那个对象的id属性,如果是 XStream.XPATH_ABSOLUTE_REFERENCES引用,那么它将显示xpath路径。上面采用的id引用,<student reference="3"/>这个引用了id=3的那个student标签元素; 

useAttributeFor是设置某个节点显示到父节点的属性中,也就是将指定class中的指定属性,在这个class元素节点的属性中显示。 

如:<student><name>hoojo</name></student> 

设置好后就是这样的结果:<student name=”hoojo”></student> 

aliasAttribute是修改属性名称。

2.3. 在JavaBean中添加Annotation注解进行重命名设置 

JavaBean的代码

import java.util.Arrays;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;

import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import com.thoughtworks.xstream.annotations.XStreamImplicit;
import com.thoughtworks.xstream.annotations.XStreamOmitField;

@XStreamAlias("class")
public class Classes {

	// 设置属性显示
	@XStreamAsAttribute
	@XStreamAlias("名称")
	private String name;

	// 忽略
	@XStreamOmitField
	private int number;

	@XStreamImplicit(itemFieldName = "Students")
	private List<Student> students;

	@XStreamConverter(SingleValueCalendarConverter.class)
	private Calendar created = new GregorianCalendar();

	public Classes() {
	}

	public Classes(String name, Student... stu) {
		this.name = name;
		this.students = Arrays.asList(stu);
	}

	// getter、setter
}

SingleValueCalendarConverter.java这个是一个类型转换器

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;

public class SingleValueCalendarConverter implements Converter {

	public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
		Calendar calendar = (Calendar) source;
		writer.setValue(String.valueOf(calendar.getTime().getTime()));
	}

	public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
		GregorianCalendar calendar = new GregorianCalendar();
		calendar.setTime(new Date(Long.parseLong(reader.getValue())));
		return calendar;
	}

	@SuppressWarnings("rawtypes")
	public boolean canConvert(Class type) {
		return type.equals(GregorianCalendar.class);
	}
}

测试代码

import com.thoughtworks.xstream.XStream;

public class WriteList2XML4Annotation {
	private static XStream xstream = new XStream();

	public static void main(String[] args) {
		try {
			Student bean1 = new Student();
			bean1.setAddress("USA");
			bean1.setEmail("[email protected]");
			bean1.setId(2);
			bean1.setName("tom");
			Birthday day1 = new Birthday("2010-11-22");
			bean1.setBirthday(day1);
			Student bean2 = new Student();
			bean2.setAddress("china");
			bean2.setEmail("[email protected]");
			bean2.setId(2);
			bean2.setName("zhansan");
			Birthday day2 = new Birthday("2001-05-06");
			bean2.setBirthday(day2);
			Classes c = new Classes("一班", bean1, bean2);
			c.setNumber(2);
			// 对指定的类使用Annotation
			// xstream.processAnnotations(Classes.class);
			// 启用Annotation
			// xstream.autodetectAnnotations(true);
			xstream.alias("student", Student.class);
			System.out.println(xstream.toXML(c));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

当启用annotation或是对某个特定的类启用annotation时,上面的classes这个类才有效果。如果不启用annotation,运行后结果如下:

<test2.Classes>
  <name>一班</name>
  <number>2</number>
  <students class="java.util.Arrays$ArrayList">
    <a class="student-array">
      <student>
        <id>2</id>
        <name>tom</name>
        <email>[email protected]</email>
        <address>USA</address>
        <birthday>
          <birthday>2010-11-22</birthday>
        </birthday>
      </student>
      <student>
        <id>2</id>
        <name>zhansan</name>
        <email>[email protected]</email>
        <address>china</address>
        <birthday>
          <birthday>2001-05-06</birthday>
        </birthday>
      </student>
    </a>
  </students>
  <created>
    <time>1413786635143</time>
    <timezone>Asia/Shanghai</timezone>
  </created>
</test2.Classes>

当启用annotation后xstream.processAnnotations(Classes.class),结果如下:

<class 名称="一班">
  <Students>
    <id>2</id>
    <name>tom</name>
    <email>[email protected]</email>
    <address>USA</address>
    <birthday>
      <birthday>2010-11-22</birthday>
    </birthday>
  </Students>
  <Students>
    <id>2</id>
    <name>zhansan</name>
    <email>[email protected]</email>
    <address>china</address>
    <birthday>
      <birthday>2001-05-06</birthday>
    </birthday>
  </Students>
  <created>1413786890887</created>
</class>

2.4. Map集合转换xml文档

import java.util.HashMap;
import java.util.Map;

import com.thoughtworks.xstream.XStream;

/**
 * Map集合转换xml文档
 */
public class writeMap2XML {
	private static XStream xstream = new XStream();

	public static void main(String[] args) {
		try {
			Student bean1 = new Student();
			bean1.setAddress("china");
			bean1.setEmail("[email protected]");
			bean1.setId(1);
			bean1.setName("tom");
			Birthday day = new Birthday("2010-11-22");
			bean1.setBirthday(day);

			Student bean2 = new Student();
			bean2.setAddress("china");
			bean2.setEmail("[email protected]");
			bean2.setId(2);
			bean2.setName("zhansan");
			Birthday day2 = new Birthday("2001-05-06");
			bean2.setBirthday(day2);

			Map<String, Student> map = new HashMap<String, Student>();
			map.put("No.1", bean1);// put
			map.put("No.2", bean2);// put
			xstream.alias("student", Student.class);
			xstream.alias("key", String.class);
			xstream.useAttributeFor(Student.class, "id");
			xstream.useAttributeFor("birthday", String.class);
			System.out.println(xstream.toXML(map));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

运行后结果如下:

<map>
  <entry>
    <key>No.1</key>
    <student id="1">
      <name>tom</name>
      <email>[email protected]</email>
      <address>china</address>
      <birthday birthday="2010-11-22"/>
    </student>
  </entry>
  <entry>
    <key>No.2</key>
    <student id="2">
      <name>zhansan</name>
      <email>[email protected]</email>
      <address>china</address>
      <birthday birthday="2001-05-06"/>
    </student>
  </entry>
</map>

2.5. 用OutStream输出流写XML

import java.io.ObjectOutputStream;

import com.thoughtworks.xstream.XStream;

/**
 * 用OutStream输出流写XML
 */
public class WriteXML4OutStream {
	private static XStream xstream = new XStream();
	private static ObjectOutputStream out = null;

	public static void main(String[] args) {
		try {
			Student bean = new Student();
			bean.setAddress("china");
			bean.setEmail("[email protected]");
			bean.setId(1);
			bean.setName("tom");
			Birthday day = new Birthday("2010-11-22");
			bean.setBirthday(day);
			
			out = xstream.createObjectOutputStream(System.out);
			Student stu = new Student();
			stu.setName("jack");
			Classes c = new Classes("一班", bean, stu);
			c.setNumber(2);
			out.writeObject(stu);
			out.writeObject(new Birthday("2010-05-33"));
			out.write(22);// byte
			out.writeBoolean(true);
			out.writeFloat(22.f);
			out.writeUTF("hello");
			
			out.flush();
			out.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

使用输出流后,可以通过流对象完成xml的构建,即使没有JavaBean对象,你可以用流来构建一个复杂的xml文档,运行后结果如下:

<object-stream>
  <test2.Student>
    <id>0</id>
    <name>jack</name>
  </test2.Student>
  <test2.Birthday>
    <birthday>2010-05-33</birthday>
  </test2.Birthday>
  <byte>22</byte>
  <boolean>true</boolean>
  <float>22.0</float>
  <string>hello</string>
</object-stream>

3. XML内容转换Java对象

3.1. 用InputStream将XML文档转换成java对象

import java.io.ObjectInputStream;
import java.io.StringReader;

import com.thoughtworks.xstream.XStream;

/**
 * 用InputStream将XML文档转换成java对象
 */
public class ReadXML4InputStream {
	private static XStream xstream = new XStream();

	public static void main(String[] args) {
		try {
			String s = "<object-stream><test2.Student><id>0</id><name>jack</name>"
					+ "</test2.Student><test2.Birthday><birthday>2010-05-33</birthday>"
					+ "</test2.Birthday><byte>22</byte><boolean>true</boolean><float>22.0</float>"
					+ "<string>hello</string></object-stream>";
			StringReader reader = new StringReader(s);
			ObjectInputStream in = xstream.createObjectInputStream(reader);
			Student stu = (Student) in.readObject();
			Birthday b = (Birthday) in.readObject();
			byte i = in.readByte();
			boolean bo = in.readBoolean();
			float f = in.readFloat();
			String str = in.readUTF();
			System.out.println(stu);
			System.out.println(b);
			System.out.println(i);
			System.out.println(bo);
			System.out.println(f);
			System.out.println(str);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

读取后,转换的Java对象,结果如下:

jack#0#null#null#null
test2.Birthday@17590db
22
true
22.0
hello

XStream对JSON的也支持,但不建议使用该Jar执行转换。这里就不做介绍了。


发布了45 篇原创文章 · 获赞 21 · 访问量 66万+

猜你喜欢

转载自blog.csdn.net/yin_jw/article/details/40348315