XStream与Jsoup解析xml的工具.这里总结一下.
1:相关依赖:
<!--xstream相关依赖-->
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.9</version>
</dependency>
<!--Jsoup相关依赖-->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.10.3</version>
</dependency>
2:针对XStream与Jsoup进行封装
package com.itmck.util;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.parser.Parser;
import org.jsoup.parser.XmlTreeBuilder;
import com.itmck.pojo.MS;
import com.itmck.pojo.QueryMsg;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
/**
*
* @ClassName: XMLUtil
* @Description: TODO(XML字符串与实体类之间互转) 需要依赖xsream Jsoup 注意依赖版本问题
* @author 34745
* @date 2019年1月31日
*
*/
public class XMLUtils {
/**
*
* @param clazz
* 类的字节码文件
* @param xml
* 传入的XML字符串
* @return XML字符串转实体类
*/
public static <T> T parseFromXml(Class<T> clazz, String xml) {
XStream xStream = new XStream(new DomDriver());
xStream.processAnnotations(clazz);
@SuppressWarnings("unchecked")
T t = (T) xStream.fromXML(xml);
return t;
}
/**
*
*
* @param obj
* 实体类
* @return 实体类转XML字符串
*/
public static String toXml(Object obj) {
XStream xStream = new XStream(new DomDriver());
// 扫描@XStream注解
xStream.processAnnotations(obj.getClass());
return xStream.toXML(obj).replaceAll("\\_+", "_");//正则过滤双下划线转为单下划线
}
/**
*
* @Description: 获取xml格式字符串中指定的元素标签片段
* @param xml
* 需要xml格式的字符串
* @param elementId
* 节点名
* @return
*/
public static String getElementString(String xml, String elementId) {
if (StringUtils.isBlank(xml) || StringUtils.isBlank(elementId)) {
return null;
}
// 获取document对象
Document document = Jsoup.parse(xml, "", new Parser(new XmlTreeBuilder()));
// 获取对应的document片段
return document.select(elementId).toString().replaceAll("\\s*", "");
}
/**
*
* @Description: xml字符串节点片段转对象
* @param xml
* @param elementId
* @param clazz
* @return
*/
public static <T> T parseElementObj(String xml, String elementId, Class<T> clazz) {
if (StringUtils.isBlank(xml) || StringUtils.isBlank(elementId)) {
return null;
}
return parseFromXml(clazz, getElementString(xml, elementId));
}
}
3封装实体类:
@Data
@NoArgsConstructor
@AllArgsConstructor
@XStreamAlias("QUERYMSG")
public class QueryMsg {
@XStreamAlias("HEAD")
private Head head;
@XStreamAlias("CONTENT")
private Content content;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@XStreamAlias("HEAD")
public class Head{
private String SEQ;
private String NAME;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@XStreamAlias("CONTENT")
public class Content {
@XStreamAlias("FLG")
private String F_LG;
@XStreamAlias("MSG")
private int M_SG;
}
测试代码如下:
public static void main(String[] args) {
Content content = new Content();
content.setF_LG("1");
content.setM_SG(35);
QueryMsg queryMsg = new QueryMsg(new Head("",""),content);
String xml = XMLUtils.toXml(queryMsg);
System.out.println(xml);
QueryMsg parseFromXml = XMLUtils.parseFromXml(QueryMsg.class, xml);
System.out.println(parseFromXml);
}
运行结果:
<QUERYMSG>
<HEAD>
<SEQ></SEQ>
<NAME></NAME>
</HEAD>
<CONTENT>
<FLG>1</FLG>
<MSG>35</MSG>
</CONTENT>
</QUERYMSG>
QueryMsg(head=Head(SEQ=, NAME=), content=Content(F_LG=1, M_SG=35))
说明: 一般这种需要俩注解就行了:
@XStreamAlias(“别名”) 配置别名
@XStreamImplicit//省略集合根节点
有些时候,xml数据同级含有多个.如下:
<student>
<name>xStream</name>
<age>10</age>
<teacher>
<name>chen</name>
<age>10</age>
</teacher>
<books>
<book>
<bookName>海贼王</bookName>
<price>20.4</price>
</book>
<book>
<bookName>风雨</bookName>
<price>30.5</price>
</book>
</books>
</student>
这就需要如下封装:
@XStreamAlias("student")
public class Student {
private String name;
private int age;
@XStreamAlias("teacher")//给节点起别名.可在此处.其实在对应类上使用即可
private Teacher teacher;
@XStreamAlias("books")//此处给books节点起别名.这种最好在类上给相应的Book类起别名
private List<Book> books;
}
@XStreamAlias("teacher")
public class Teacher {
private String name;
private int age;
}
@XStreamAlias("book")
public class Book {
private String bookName;
private Double price;
}
如果想要的是下面这种,就需要省略对应根节点 @XStreamImplicit
<student>
<name>xStream</name>
<age>10</age>
<teacher>
<name>chen</name>
<age>10</age>
</teacher>
<book>
<bookName>海贼王</bookName>
<price>20.4</price>
</book>
<book>
<bookName>风雨</bookName>
<price>30.5</price>
</book>
</student>
对应的Student类封装如下,其余不变
@XStreamAlias("student")
public class Student {
private String name;
private int age;
@XStreamAlias("teacher")//给节点起别名.默认xml节点为属性名
private Teacher teacher;
@XStreamImplicit
private List<Book> books;
}
如果一个类嵌套很多子类,这样只需要在其父类上使用别名,其余子类不用使用,默认子类以对应的在父类中的属性名为xml节点.否则就是生成类的全路径作为xml节点
1:在上述的封装中我使用了Jsoup.目的是为了获取xml中的某个节点.其中使用了正则除去空格,以及缩进等字符.
2:另外注意的是:在使用XStream的时候如果属性使用的是"_"拼接的.如:
private String stu_name; 在生成xml的时候会默然两个下划线<stu__name></stu__name>
这里我也是用了正则转为一个下划线
3:上面实体类使用了lombok注解,为了免于生成getter与setter