简介
java自带的jar包中并不支持Javabean和xml的转换
所以是首先要使用的两个jar包:
Javabean和xml的转换是XStream中的类和方法,而使用XStream就必须依赖xpp3jar包;
XStream网上都能下载,下面是下载xpp3的网址,但是原网址被废弃了,存档一般是进不去的
http://www.extreme.indiana.edu/xgws/xsoap/xpp/
百度上搜了下,很多下载xpp3都要收费的,这里作为学习交流提供XStream和xpp3的jar包:
1 2 | 链接:https: //pan.baidu.com/s/1PYfE3yiYdXEHVFUeaa6SSw?pwd=8080 提取码: 8080 |
然后就是创建java工程和导入jar包了,导包可以参照:
https://www.cnblogs.com/0099-ymsml/p/16062244.html
应用:
javabean和xml的转换需要使用toXml()方法:
public String toXML(Object obj) {
Writer writer = new StringWriter();
toXML(obj, writer);
return writer.toString();
}
public void toXML(Object obj, Writer out) {
HierarchicalStreamWriter writer = hierarchicalStreamDriver.createWriter(out);
try {
marshal(obj, writer);
} finally {
writer.flush();
}
}
public void marshal(Object obj, HierarchicalStreamWriter writer) {
marshal(obj, writer, null);
}
public void marshal(Object obj, HierarchicalStreamWriter writer, DataHolder dataHolder) { marshallingStrategy.marshal(writer, obj, converterLookup, mapper, dataHolder); }
上面就是XStream中的toXml()方法,
太多了懒得分析,返回的是一个xml形式的字符串。
使用toXml():
首先需要创建标准Java类:
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* @author CDU_LM
* 省份类
*/
public class Province {
private String name; // 名称
private List<City> cities = new ArrayList<City>();
public Province(String name, List<City> cities) {
this.name = name;
this.cities = cities;
}
public Province() {
// TODO Auto-generated constructor stub
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<City> getCities() {
return cities;
}
public void setCities(List<City> cities) {
this.cities = cities;
}
@Override
public int hashCode() {
return Objects.hash(cities, name);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Province other = (Province) obj;
return Objects.equals(cities, other.cities) && Objects.equals(name, other.name);
}
@Override
public String toString() {
return "Province [name=" + name + ", cities=" + cities + "]";
}
public void addCity(City city) {
this.cities.add(city);
}
}
import java.util.Objects;
// 城市类
public class City {
private String name; // 名称
private String descript; // 描述
public City(String name, String descript) {
this.name = name;
this.descript = descript;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescript() {
return descript;
}
public void setDescript(String descript) {
this.descript = descript;
}
@Override
public int hashCode() {
return Objects.hash(descript, name);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
City other = (City) obj;
return Objects.equals(descript, other.descript) && Objects.equals(name, other.name);
}
@Override
public String toString() {
return "Province [name=" + name + ", descript=" + descript + "]";
}
}
然后是创建一个@Test测试类:
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import com.thoughtworks.xstream.XStream;
// 测试类
public class JavaToXml {
// 返回javabean集合
public List<Province> getProvinceList(){
Province p1 = new Province(); // 创建省1
p1.setName("北京"); // 省份名称
p1.addCity(new City("东城区","dcq")); // 添加城市
p1.addCity(new City("西城区","xcq")); // 添加城市
p1.addCity(new City("北城区","bcq")); // 添加城市
Province p2 = new Province(); // 创建省2
p2.setName("四川"); // 省份名称
p2.addCity(new City("简阳","jy")); // 添加城市
p2.addCity(new City("成都","cd")); // 添加城市
p2.addCity(new City("绵阳","my")); // 添加城市
List<Province> provinceList = new ArrayList<>(); // 创建集合
provinceList.add(p1); // 添加元素p1
provinceList.add(p2); // 添加元素p2
return provinceList;
}
@SuppressWarnings("resource")
@Test
public void fun1() {
List<Province> proList = getProvinceList();
/**
* 创建XStream对象
* 调用toXML()方法把集合转换为字符串
*/
XStream xs = new XStream();
String s = "<?xml version='1.0' encoding='utf-8'?>\n";
s +=xs.toXML(proList);
System.out.print(s);
try {
PrintStream print = new PrintStream("D:" + File.separator + "toXml.xml");
print.print(s);
print.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
运行这个测试类:
<?xml version='1.0' encoding='utf-8'?>
<list>
<toXml.Province>
<name>北京</name>
<cities>
<toXml.City>
<name>东城区</name>
<descript>dcq</descript>
</toXml.City>
<toXml.City>
<name>西城区</name>
<descript>xcq</descript>
</toXml.City>
<toXml.City>
<name>北城区</name>
<descript>bcq</descript>
</toXml.City>
</cities>
</toXml.Province>
<toXml.Province>
<name>四川</name>
<cities>
<toXml.City>
<name>简阳</name>
<descript>jy</descript>
</toXml.City>
<toXml.City>
<name>成都</name>
<descript>cd</descript>
</toXml.City>
<toXml.City>
<name>绵阳</name>
<descript>my</descript>
</toXml.City>
</cities>
</toXml.Province>
</list>
可以发现这个运行结果去掉第一行人为添加的后:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 根元素<list>:使用的List接口集合类型,如果是使用其它的集合类型就是对应的类型名称 下面的<toXml.Province>:包.省份类名 <toXml.Province>下面的<name>:Province 的第一个成员属性 <toXml.Province>下面的<cities>:Province 的第二个成员属性 <toXml.City> :包.城市类名 <toXml.City> 下面的<name>:City的第一个成员属性 <toXml.City> 下面的<descript>:City的第二个成员属性 |
那么结构就是这样了,成功地将Java类转换为了xml的形式。
然后在文件路径中有:
打开后:
如果打开报错,可能是编码的问题,可以在:
选择utf-8,建议写代码之前就换一下,因为默认的是gbk格式,在转换为utf-8后会导致中文乱码;
在程序开发中建议的也是utf-8格式。
给默认的标签起别名:
上面我们发现 得出结果的xml数据的标签是根据包和类来定义的,看着很不规律或整齐,所以可以使用XStream中的alias()方法
首先看看alias()方法的代码:
classAliasingMapper 是 类别名映射器
public void alias(String name, Class type) {
if (classAliasingMapper == null) {
throw new com.thoughtworks.xstream.InitializationException("No "
+ ClassAliasingMapper.class.getName()
+ " available");
}
classAliasingMapper.addClassAlias(name, type);
}
如果classAliasingMapper 不为空,那么就执行addClassAlias()方法
public void addClassAlias(String name, Class type) {
nameToType.put(name, type.getName());
classToName.put(type.getName(), name);
}
在addClassAlias()方法中可以发现,和Map集合有了联系。
private final Map classToName = new HashMap();
private transient Map nameToType = new HashMap()
put()方法就相当于在给classToName和nameToType赋值
想要深究的可以去看源码
@Test
public void fun2() {
List<Province> proList = getProvinceList();
XStream xs = new XStream();
xs.alias("china", List.class); // List类型别名为china
xs.alias("province", Province.class); // Province类型别名为province
xs.alias("city", City.class); // City类型别名为city
String s = "<?xml version='1.0' encoding='utf-8'?>\n";
s +=xs.toXML(proList);
System.out.print(s);
}
运行结果:
<?xml version='1.0' encoding='utf-8'?>
<china>
<province>
<name>北京</name>
<cities>
<city>
<name>东城区</name>
<descript>dcq</descript>
</city>
<city>
<name>西城区</name>
<descript>xcq</descript>
</city>
<city>
<name>北城区</name>
<descript>bcq</descript>
</city>
</cities>
</province>
<province>
<name>四川</name>
<cities>
<city>
<name>简阳</name>
<descript>jy</descript>
</city>
<city>
<name>成都</name>
<descript>cd</descript>
</city>
<city>
<name>绵阳</name>
<descript>my</descript>
</city>
</cities>
</province>
</china>
这样就可以使对应的标签变成自定义标签名称;
将某个类的成员属性变为xml中标签的属性:
/**
* 默认子元素是java类的成员属性
* 现在需要将某些java类的成员属性变为标签的属性
*/
@Test
public void fun3() {
List<Province> proList = getProvinceList();
XStream xs = new XStream();
xs.alias("china", List.class); // List类型别名为china
xs.alias("province", Province.class); // Province类型别名为province
xs.alias("city", City.class); // City类型别名为city
/**
* 把Pprovince类型的name属性变为<province>标签的属性
*/
xs.useAttributeFor(Province.class,"name"); // 将Province类的name成员属性变为xml中的标签属性
String s = "<?xml version='1.0' encoding='utf-8'?>\n";
s +=xs.toXML(proList);
System.out.print(s);
}
运行结果:
</china><?xml version='1.0' encoding='utf-8'?>
<china>
<province name="北京">
<cities>
<city>
<name>东城区</name>
<descript>dcq</descript>
</city>
<city>
<name>西城区</name>
<descript>xcq</descript>
</city>
<city>
<name>北城区</name>
<descript>bcq</descript>
</city>
</cities>
</province>
<province name="四川">
<cities>
<city>
<name>简阳</name>
<descript>jy</descript>
</city>
<city>
<name>成都</name>
<descript>cd</descript>
</city>
<city>
<name>绵阳</name>
<descript>my</descript>
</city>
</cities>
</province>
可以发现Province类下的name成员属性变为了标签<province>中的属性
使某个类中的某个成员属性不显示在xml的标签中:
换一种说法就是只是将集合中(不包括集合名本身)的元素生成xml标签
@Test
public void fun4() {
List<Province> proList = getProvinceList();
XStream xs = new XStream();
xs.alias("china", List.class); // List类型别名为china
xs.alias("province", Province.class); // Province类型别名为province
xs.alias("city", City.class); // City类型别名为city
xs.useAttributeFor(Province.class,"name"); // 将Province类的name成员属性变为xml中的标签属性
/**
* 去掉<cities>这样的集合类型属性
*/
xs.addImplicitCollection(Province.class, "cities"); // 使Province类中的cities不显示在xml标签中
String s = "<?xml version='1.0' encoding='utf-8'?>\n";
s +=xs.toXML(proList);
System.out.print(s);
}
运行结果:
<?xml version='1.0' encoding='utf-8'?>
<china>
<province name="北京">
<city>
<name>东城区</name>
<descript>dcq</descript>
</city>
<city>
<name>西城区</name>
<descript>xcq</descript>
</city>
<city>
<name>北城区</name>
<descript>bcq</descript>
</city>
</province>
<province name="四川">
<city>
<name>简阳</name>
<descript>jy</descript>
</city>
<city>
<name>成都</name>
<descript>cd</descript>
</city>
<city>
<name>绵阳</name>
<descript>my</descript>
</city>
</province>
</china>
上面的xml就去掉了<cities>这个标签。
使用某些javabean属性不生成为xml标签:
@Test
public void fun5() {
List<Province> proList = getProvinceList();
XStream xs = new XStream();
xs.alias("china", List.class); // List类型别名为china
xs.alias("province", Province.class); // Province类型别名为province
xs.alias("city", City.class); // City类型别名为city
xs.useAttributeFor(Province.class,"name"); // 将Province类的name成员属性变为xml中的标签属性
xs.addImplicitCollection(Province.class, "cities"); // 使Province类中的cities不显示在xml标签中
/**
* 使某些类的某个属性不生成对应的xml标签
*/
xs.omitField(City.class,"descript");
String s = "\n<?xml version='1.0' encoding='utf-8'?>\n";
s +=xs.toXML(proList);
System.out.print(s);
}
运行结果:
<?xml version='1.0' encoding='utf-8'?>
<china>
<province name="北京">
<city>
<name>东城区</name>
</city>
<city>
<name>西城区</name>
</city>
<city>
<name>北城区</name>
</city>
</province>
<province name="四川">
<city>
<name>简阳</name>
</city>
<city>
<name>成都</name>
</city>
<city>
<name>绵阳</name>
</city>
</province>
</china>
这样xml中的<descript>标签就不会生成了
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)