java解析xml串标签_Java反射解析XML字符串并封装到指定的JavaBean

在日常的工作中,我们经常需要处理xml格式的字符串,比如:调用第三方接口返回xml信息,需要解析xml获取相应的结果信息,之前自己写过一个利用 Java反射解析XML字符串,并封装到指定的JavaBean中的方法,最近的工作中又使用到了第三方接口,需要处理接口返回的XML字符串信息,对解 析XML的工具方法做了重新的优化,这里记录总结一下。

首先, 我们看下面xml格式的字符串:

//这里随便在网上搜索的xml字符串,简单做了修改

firstXmlStr = "<?xml  version=\"1.0\" encoding=\"GBK\"?>" +

"" +

"" +

"1001     " +

"Realfighter   " +

"81        " +

"1001号   " +

"" +

"";

假设现在我们需要获取到其中的结果信息,拿到用户的相关信息,并封装到指定的UserBean中,如下:

/**

* xml中需要的信息封装到User

* 这里继承BaseObject用于第二个解析xml的方法

* 注意:User的属性名必须与xml字符串中的标签一致

*/

class User extends BaseObject {

String users_id;//用户ID

String users_name;//用户名

String users_group;//用户分组

String users_address;//用户地址

public String getUsers_id() {

return users_id;

}

public void setUsers_id(String users_id) {

this.users_id = users_id;

}

public String getUsers_name() {

return users_name;

}

public void setUsers_name(String users_name) {

this.users_name = users_name;

}

public String getUsers_group() {

return users_group;

}

public void setUsers_group(String users_group) {

this.users_group = users_group;

}

public String getUsers_address() {

return users_address;

}

public void setUsers_address(String users_address) {

this.users_address = users_address;

}

@Override

public String toString() {

return "User{" +

"users_id=" + users_id +

", users_name='" + users_name + '\'' +

", users_group=" + users_group +

", users_address='" + users_address + '\'' +

'}';

}

}

我们通过以下方法解析xml并封装到指定对象,如下:

/**

* 封装xml信息到指定的Object

*

* @param returnXml

* @param obj

* @return Object

* @throws

* @Title: packReturnByXml

* @author Realfighter

*/

public static Object packReturnByXml(String returnXml, Object obj) {

Field[] fields = obj.getClass().getDeclaredFields();

for (Field field : fields) {

field.setAccessible(true);

String fieldname = field.getName();

try {

Pattern p = Pattern.compile(".*?"

+ fieldname + ">");

//匹配类似:1001     的字符

Matcher matcher = p.matcher(returnXml);

while (matcher.find()) {

Pattern p1 = Pattern.compile(">([^<>]*)

//匹配类似:>1001     

Matcher m1 = p1.matcher(matcher.group(0).trim());

if (m1.find()) {

String value = m1.group(1).trim().equals("") ? null

: m1.group(1).trim();

Class> beanType = field.getType();

String setMethodName = "set"

+ fieldname.substring(0, 1).toUpperCase()

+ fieldname.substring(1);

Method m = obj.getClass().getMethod(setMethodName,

beanType);

m.invoke(obj, value);

}

}

} catch (Exception e) {

continue;

}

}

return obj;

}

测试如下:

@Test

public void testFirstXmlStr() {

User user = (User) packReturnByXml(firstXmlStr, new User());

System.out.println(user.toString());

//执行结果:

//User{users_id=1001, users_name='Realfighter', users_group=81, users_address='1001号'}

}

但是如果我们获取到的xml字符串是以下的类型,上面的方法就存在问题了,因为我们匹配到的不止是一条记录,我们需要的也是多个对象,如下:

secondXmlStr = "<?xml  version=\"1.0\" encoding=\"GBK\"?>" +

"" +

"" +

"1001     " +

"Realfighter   " +

"81        " +

"1001号   " +

"" +

"" +

"1002     " +

"Realfighter2   " +

"82        " +

"1002号   " +

"" +

"";

这时候,我们就需要改进一下上面的packReturnByXml方法,对其中匹配到的对象放入数组返回,如下:

/**

* 解析xml,封装成returnbean数组

*

* @param returnXml

* @param obj

* @return

* @throws IllegalArgumentException

* @throws IllegalAccessException

* @throws SecurityException

* @throws NoSuchMethodException

* @throws InvocationTargetException

*/

public static BaseObject[] packReturnArrayByXml(String returnXml, BaseObject obj)

throws IllegalArgumentException, IllegalAccessException,

SecurityException, NoSuchMethodException, InvocationTargetException {

Field[] fields = obj.getClass().getDeclaredFields();

List objs = new ArrayList();

int count = 0;//临时变量,用于计算可匹配到的对象数目

for (Field field : fields) {

field.setAccessible(true);

String fieldname = field.getName();

Pattern p = Pattern.compile(".*?"

+ fieldname + ">");

Matcher matcher = p.matcher(returnXml);

while (matcher.find()) {

//对象的复制方法

Object _obj = obj.clone();

objs.add(_obj);

count++;

}

if (count > 0) {

//一旦获取到对象数组,结束循环

break;

}

}

BaseObject[] objs2 = new BaseObject[count];

for (int i = 0; i 

Object obj1 = objs.get(i);

for (Field field : fields) {

field.setAccessible(true);

String fieldname = field.getName();

try {

Pattern p = Pattern.compile(".*?"

+ fieldname + ">");

Matcher matcher = p.matcher(returnXml);

int num = 0;

while (matcher.find()) {

if (num == i) {

Pattern p1 = Pattern.compile(">([^<>]*)

Matcher m1 = p1.matcher(matcher.group(0).trim());

if (m1.find()) {

String value = m1.group(1).trim().equals("") ? null

: m1.group(1).trim();

Class> beanType = field.getType();

String setMethodName = "set"

+ fieldname.substring(0, 1)

.toUpperCase()

+ fieldname.substring(1);

Method m = obj1.getClass().getMethod(

setMethodName, beanType);

m.invoke(obj1, value);

}

}

num++;

}

} catch (NullPointerException e) {

continue;

}

}

objs2[i] = (BaseObject) obj1;

}

return objs2;

}

这里需要传入的是一个BaseObject对象,实现Cloneable接口的一个基类,实际的User对象需要继承此对象,以实现clone(),如下:

/**

* 基础的Object对象,实现Cloneable接口,用于调用clone()

*/

class BaseObject implements Cloneable {

@Override

public Object clone() {

Object obj = null;

try {

obj = super.clone();

} catch (CloneNotSupportedException e) {

e.printStackTrace();

}

return obj;

}

}

测试如下:

@Test

public void testSecondXmlStr() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {

BaseObject[] objs = packReturnArrayByXml(secondXmlStr, new User());

for (BaseObject base : objs) {

System.out.println(((User) base).toString());

}

//执行结果:

//User{users_id=1001, users_name='Realfighter', users_group=81, users_address='1001号'}

//User{users_id=1002, users_name='Realfighter2', users_group=82, users_address='1002号'}

}

总结:在XML信息比较简单的时候,不需要封装多个对象信息的时候,我们可以调用第一个方法:packReturnByXml解析xml封装到指定的对象 中,但是当xml信息比较复杂的时候,需要封装多个对象信息的时候,我们就需要将封装的对象继承BaseObject,通过调用 packReturnArrayByXml返回BaseObject数组,通过遍历数组拿到需要的相关信息。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值