1. XStream简介
2.简单使用
3.正常xml的解析
4.有点不正常xml的解析
5.更加不正常xml的解析
6.非常不正常xml的解析
1. XStream简介
XStream是一个Java对象与XML互相转换的工具类库。
官网链接: http://x-stream.github.io/index.html
2.简单使用
下载页面:http://x-stream.github.io/download.html
使用Maven构建项目的加入以下依赖:
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.10</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>12345678910
3.正常xml的解析
注意:代码中xmlString都代表当前小结里面的xml字符串
<User>
<userName>lanweihong</userName>
<email>lwhhhp@gmail.com</email>
</User>1234
对象
public class User {
private String userName;
private String email;
public User(String userName, String email) {
this.userName = userName;
this.email = email;
}
}12345678910
运行
public static void main(String[] args) {
XStream xStream = new XStream();
xStream.alias("User", User.class);
String xml = xmlString;
//转对象
User user = (User)xStream.fromXML(xml);
System.out.println(user.toString());
}12345678
输出文本为:
User:{userName=lanweihong,email=lwhhhp@gmail.com}1
4.有点不正常xml的解析
一个看着比较“正常”的带有集合的xml
1. carInfos做为根元素,其子元素是由N个carInfo组成的集合,每个carInfo元素描述一个对象信息。
2. carInfo的子元素,每个tag做为属性名,tag所包含的txt做为属性值。
<carInfos dwName="sys.common.new_vehicle_DW">
<carInfo index="1">
<VehicleId>FTBAUD0088</VehicleId>
<VehicleName>福克斯CAF7163B5轿车</VehicleName>
<Remark>两厢 双离合 舒适型 国Ⅴ</Remark>
<VehiclePrice>101800</VehiclePrice>
</carInfo>
<carInfo index="2">
<VehicleId>FTBAUD0078</VehicleId>
<VehicleName>福克斯CAF7163B5轿车</VehicleName>
<Remark>两厢 双离合 风尚型 国Ⅴ</Remark>
<VehiclePrice>113800</VehiclePrice>
</carInfo>
<carInfo index="3">
<VehicleId>FTBAUD0097</VehicleId>
<VehicleName>福克斯CAF7163B5轿车</VehicleName>
<Remark>两厢 双离合 智行版 风尚型 国Ⅴ</Remark>
<VehiclePrice>115800</VehiclePrice>
</carInfo>
</carInfos>1234567891011121314151617181920
与xml元素对应的Java类
对应carInfos元素
@XStreamAlias("carInfos")//对应carInfos元素
public class CarInfos {
@XStreamAsAttribute
private String dwName;//对应carInfos元素的dwName属性
@XStreamImplicit(itemFieldName = "carInfo")
private List<CarInfo> carInfoList = new ArrayList<CarInfo>();//对应N个carInfo元素组成的集合
//省略getter/setter方法
}1234567891011
对应carInfo元素
@XStreamAlias("carInfo")//对应carInfo元素
public class CarInfo {
@XStreamAsAttribute
private String index;//对应carInfo的index属性
@XStreamAlias("VehicleId")
private String vehicleId;//对应carInfo的VehicleId子元素
@XStreamAlias("VehicleName")
private String VehicleName;//对应carInfo的VehicleName子元素
@XStreamAlias("Remark")
private String remark;//对应carInfo的Remark子元素
@XStreamAlias("VehiclePrice")
private String vehiclePrice;//对应carInfo的VehiclePrice子元素
//省略getter/setter方法
}1234567891011121314151617181920
解析xml
public static void main(String[] args) throws Exception {
File dataXml = readXml();//读取xml
XStream xstream = new XStream(new DomDriver());//创建Xstram对象
xstream.autodetectAnnotations(true);
xstream.processAnnotations(CarInfos.class);
CarInfos carInfos = (CarInfos) xstream.fromXML(dataXml);
//打印对象
System.out.printf("CarInfos dwName:%s\n", carInfos.getDwName());
for (CarInfo carInfo : carInfos.getCarInfoList()) {
System.out.printf("\tCarInfo index:%s\n", carInfo.getIndex());
System.out.printf("\tCarInfo VehicleId:%s\n", carInfo.getVehicleId());
System.out.printf("\tCarInfo VehicleName:%s\n", carInfo.getVehicleName());
System.out.printf("\tCarInfo VehiclePrice:%s\n", carInfo.getVehiclePrice());
System.out.printf("\tCarInfo Remark:%s\n", carInfo.getRemark());
}
//将对象转为xml,再次打印
String resultXml = xstream.toXML(carInfos);
System.out.printf("=======================\n" + resultXml);
}12345678910111213141516171819
5.更加不正常xml的解析
一个“有点别扭”的xml
特点是carInfo元素下是多个attribute元素的集合。但是很明显,每个attribute元素的属性name的值,都本应该是carInfo元素的子元素的tagName。
<carInfos dwName="sys.common.new_vehicle_DW">
<carInfo index="1">
<attribute name="VehicleId">FTBAUD0088</attribute>
<attribute name="VehicleName">福克斯CAF7163B5轿车</attribute>
<attribute name="Remark">两厢 双离合 舒适型 国Ⅴ</attribute>
<attribute name="VehiclePrice">101800</attribute>
</carInfo>
<carInfo index="2">
<attribute name="VehicleId">FTBAUD0078</attribute>
<attribute name="VehicleName">福克斯CAF7163B5轿车</attribute>
<attribute name="Remark">两厢 双离合 风尚型 国Ⅴ</attribute>
<attribute name="VehiclePrice">113800</attribute>
</carInfo>
<carInfo index="3">
<attribute name="VehicleId">FTBAUD0097</attribute>
<attribute name="VehicleName">福克斯CAF7163B5轿车</attribute>
<attribute name="Remark">两厢 双离合 智行版 风尚型 国Ⅴ</attribute>
<attribute name="VehiclePrice">115800</attribute>
</carInfo>
</carInfos>1234567891011121314151617181920
与xml元素对应的Java类
根据attribute元素,新建一个CarAttr类。
注意这里使用到@XStreamCoverter注解。 而且没有对成员变量添加注解。
@XStreamAlias("attribute")
@XStreamConverter(CarAttrConverter.class)
public class CarAttr {
//没有使用@XStreamAsAttribute注解
private String name;
//没有使用注解
private String value;
//省略getter/setter方法
}123456789101112
对CarInfo类进行修改,因为carInfo元素下是多个attribute元素,所以定义了一个List集合。如同CarInfos与CarInfo的关系。
@XStreamAlias("carInfo")
public class CarInfo {
@XStreamAsAttribute
private String index;
@XStreamImplicit(itemFieldName = "attribute")
private List<CarAttr> attrs = new ArrayList<CarAttr>();
//省略getter/setter方法
}1234567891011
定义CarAttr转换类(这个是可有可无的类)
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 CarAttrConverter implements Converter {
@Override
public boolean canConvert(Class type) {
return type.equals(CarAttr.class);//转换条件
}
/**
* 将java对象转为xml时使用
*/
@Override
public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
CarAttr attr = (CarAttr) source;
// writer.startNode("attribute");
writer.addAttribute("name", attr.getName());
writer.setValue(attr.getValue());
// writer.endNode();
}
/**
* 将xml转为java对象使用
*/
@Override
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
CarAttr a = new CarAttr();// 在解析attribute元素时,先创建一个CarAttr对象
a.setName(reader.getAttribute("name"));// 将attribute元素的name属性设置为CarAttr对象的name属性值
a.setValue(reader.getValue());// 将attribute元素的txt值设置为CarAttr对象的value值
return a;
}
}123456789101112131415161718192021222324252627282930313233343536
解析xml
public static void main(String[] args) throws Exception {
File dataXml = readXml();
XStream xstream = new XStream(new DomDriver());
xstream.autodetectAnnotations(true);
xstream.processAnnotations(CarInfos.class);
CarInfos carInfos = (CarInfos) xstream.fromXML(dataXml);
//打印对象
System.out.printf("CarInfos dwName:%s\n", carInfos.getDwName());
for (CarInfo carInfo : carInfos.getCarInfoList()) {
System.out.printf("\tCarInfo index:%s\n", carInfo.getIndex());
for (CarAttr ca : carInfo.getAttrs()) {
System.out.printf("\t\tCarAttr name:%s,value:%s\n", ca.getName(), ca.getValue());
}
}
String resultXml = xstream.toXML(carInfos);
System.out.printf("=======================\n" + resultXml);
}1234567891011121314151617
两个xml的解析方法没有区别,只是在打印解析出的对象时,稍有不同。主要区别在于根据attribute元素,新增加了CarAttr类的定义,及与CarAttr类对应CarAttrConverter转换类的使用。
6.非常不正常xml的解析
<dlineage>
<relation id="3" type="dataflow">
<target coordinate="[1,27],[1,31]" column="NAME" id="5" parent_id="1" parent_name="TABLEA"/>
<source coordinate="[1,27],[1,31]" column="NAME" id="1" parent_id="2" parent_name="B"/>
</relation>
<relation id="4" type="dataflow">
<target coordinate="[1,32],[1,35]" column="AGE" id="6" parent_id="1" parent_name="TABLEA"/>
<source coordinate="[1,32],[1,35]" column="AGE" id="2" parent_id="2" parent_name="B"/>
</relation>
<table name="TABLEA" id="1" type="table" coordinate="[1,13],[1,19]">
<column name="NAME" id="5" coordinate="[1,27],[1,31]"/>
<column name="AGE" id="6" coordinate="[1,32],[1,35]"/>
</table>
<table name="B" id="2" type="table" coordinate="[1,42],[1,43]">
<column name="NAME" id="1" coordinate="[1,27],[1,31]"/>
<column name="AGE" id="2" coordinate="[1,32],[1,35]"/>
</table>
</dlineage>123456789101112131415161718
这里有俩坑
1. 坑1:dlineage对象我的Dlinage(一个解析血缘的工具类收费的))已经存储,不能定义这个
2. 坑2:parent_id parent_name 不识别带有横岗的属性
针对这两个问题对xml进行预处理
xmlString = xmlString.replaceAll("dlineage","DlineageEntity");
xmlString = xmlString.replaceAll("parent_id","parentId");
xmlString = xmlString.replaceAll("parent_name","parentName");123
建立实体类
@Data
@XStreamAlias("DlineageEntity")//对应dlineage元素
public class DlineageEntity {
// 对应relation
@XStreamImplicit(itemFieldName = "relation")
private List<Relation> relation;
// 对应table
@XStreamImplicit(itemFieldName = "table")
private List<Table> table;
}
1234567891011121314
@Data
@XStreamAlias("relation") // 对应relation
public class Relation {
// 对应 id 属性
@XStreamAsAttribute
private String id;
// 对应 type 属性
@XStreamAsAttribute
private String type;
// 对应 target 子元素
@XStreamImplicit(itemFieldName = "target")
private List<Target> target ;
// 对应 source 子元素
@XStreamImplicit(itemFieldName = "source")
private List<Source> source ;
}
1234567891011121314151617181920
@Data
@XStreamAlias("target") // 对应 target
public class Target {
// 对应 coordinate 属性
@XStreamAsAttribute
private String coordinate;
// 对应 column 属性
@XStreamAsAttribute
private String column;
// 对应 id 属性
@XStreamAsAttribute
private String id;
// 对应 parentId 属性
@XStreamAsAttribute
private String parentId;
// 对应 parentName 属性
@XStreamAsAttribute
private String parentName;
}123456789101112131415161718192021
@Data
@XStreamAlias("source")
public class Source {
@XStreamAsAttribute
private String coordinate;
@XStreamAsAttribute
private String column;
@XStreamAsAttribute
private String id;
@XStreamAsAttribute
private String parentId;
@XStreamAsAttribute
private String parentName;
}12345678910111213141516
@Data
@XStreamAlias("table")
public class Table {
@XStreamAsAttribute
private String name;
@XStreamAsAttribute
private String id;
@XStreamAsAttribute
private String type;
@XStreamAsAttribute
private String coordinate;
@XStreamImplicit(itemFieldName = "column")
private List<Column> column;
}
1234567891011121314151617
@Data
@XStreamAlias("column")
public class Column {
@XStreamAsAttribute
private String name;
@XStreamAsAttribute
private String id;
@XStreamAsAttribute
private String coordinate;
}
1234567891011121314
解析对象
private static void makeBlood(String result ) {
result = result.replaceAll("dlineage","DlineageEntity");
result = result.replaceAll("parent_id","parentId");
result = result.replaceAll("parent_name","parentName");
System.out.println( "===>"+result );
XStream xStream = new XStream();
xStream.autodetectAnnotations(true);
xStream.processAnnotations(DlineageEntity.class);
DlineageEntity carInfos = (DlineageEntity) xStream.fromXML(result);
System.out.println(carInfos.toString());
}1234567891011121314
结果
DlineageEntity(
relation=[
Relation(
id=3, type=dataflow,
target=[ Target( coordinate=[1,27],[1,31], column=NAME, id=5, parentId=1, parentName=TABLEA)],
source=[Source(coordinate=[1,27],[1,31], column=NAME, id=1, parentId=2, parentName=B)]
),
Relation(id=4, type=dataflow,
target=[Target(coordinate=[1,32],[1,35], column=AGE, id=6, parentId=1, parentName=TABLEA)],
source=[Source(coordinate=[1,32],[1,35], column=AGE, id=2, parentId=2, parentName=B)]
)
],
table=[
Table(name=TABLEA, id=1, type=table, coordinate=[1,13],[1,19],
column=[
Column(name=NAME, id=5, coordinate=[1,27],[1,31]),
Column(name=AGE, id=6, coordinate=[1,32],[1,35])
]
),
Table(name=B, id=2, type=table, coordinate=[1,42],[1,43],
column=[
Column(name=NAME, id=1, coordinate=[1,27],[1,31]),
Column(name=AGE, id=2, coordinate=[1,32],[1,35])
]
)
)
123456789101112131415161718192021222324252627
---------------------
作者:九师兄-梁川川
来源:CSDN
原文:https://blog.csdn.net/qq_21383435/article/details/82116706
版权声明:本文为博主原创文章,转载请附上博文链接!