xstream 对XML提供特殊解析

xstream 初学笔记


简介:本章主要写的是,在微信开发中,有发送xml数据,其中用到了xstream这个框架进行javaBean和xml数据的转换,但是在每个标签中,微信需要的接口都需要封装上一个<![CDATA[fromUser]]>东西,所以使用了其中的解析器来,在本章中用到了xpp这个解析类,别的我还没有搞明白,但是xstream框架很丰富,此处指给出一个特例,把JavaBean中的其余属性封装上特殊标签,CreateTime不需要,由此给出了下面的程序.

    需要下载xstream-1.3.1.jar包

    关于xstream的别的功能以及注解,网上很多,再次不多做解释.

第一种方法

package org.liufeng.course.message.resp;

/**
 * 文本消息
 * 
 * @author liufeng
 * @date 2013-05-19
 */
public class TextMessage extends BaseMessage {
	// 回复的消息内容
	private String Content;

	public String getContent() {
		return Content;
	}

	public void setContent(String content) {
		Content = content;
	}
}

package org.liufeng.course.message.resp;

/**
 * 消息基类(公众帐号 -> 普通用户)
 * 
 * @author liufeng
 * @date 2013-05-19
 */
public class BaseMessage {
	// 接收方帐号(收到的OpenID)
	private String ToUserName;
	// 开发者微信号
	private String FromUserName;
	// 消息创建时间 (整型)
	private long CreateTime;
	// 消息类型(text/music/news)
	private String MsgType;
	// 位0x0001被标志时,星标刚收到的消息
	private int FuncFlag;

	public String getToUserName() {
		return ToUserName;
	}

	public void setToUserName(String toUserName) {
		ToUserName = toUserName;
	}

	public String getFromUserName() {
		return FromUserName;
	}

	public void setFromUserName(String fromUserName) {
		FromUserName = fromUserName;
	}

	public long getCreateTime() {
		return CreateTime;
	}

	public void setCreateTime(long createTime) {
		CreateTime = createTime;
	}

	public String getMsgType() {
		return MsgType;
	}

	public void setMsgType(String msgType) {
		MsgType = msgType;
	}

	public int getFuncFlag() {
		return FuncFlag;
	}

	public void setFuncFlag(int funcFlag) {
		FuncFlag = funcFlag;
	}
}

package org.liufeng.course.util;

import java.io.InputStream;
import java.io.Writer;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.liufeng.course.message.resp.Article;
import org.liufeng.course.message.resp.MusicMessage;
import org.liufeng.course.message.resp.NewsMessage;
import org.liufeng.course.message.resp.TextMessage;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;

/**
 * 消息工具类
 */
public class MessageUtil {

	/**
	 * 返回消息类型:文本
	 */
	public static final String RESP_MESSAGE_TYPE_TEXT = "text";

	/**
	 * 文本消息对象转换成xml
	 * alias 起别名,如果没有,根节点将面为com.pacage.textMessage的形式
	 * @param textMessage 文本消息对象
	 * @return xml
	 */
	public static String textMessageToXml(TextMessage textMessage) {
		xstream.alias("xml", textMessage.getClass());
		return xstream.toXML(textMessage);
	}

	public static void main(String[] args) {
		TextMessage textMessage = new TextMessage();
		textMessage.setToUserName("fromUser");
		textMessage.setFromUserName("toUser");
		textMessage.setCreateTime(new Date().getTime());
		textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);
		textMessage.setFuncFlag(0);
		String xml = new MessageUtil().textMessageToXml(textMessage);
		System.out.println(xml);
	}
	
	/**
	 * 扩展xstream,使其支持CDATA块
	 */
	private static XStream xstream = new XStream(new XppDriver() {
		public HierarchicalStreamWriter createWriter(Writer out) {
			return new PrettyPrintWriter(out) {
				// 对所有xml节点的转换都增加CDATA标记
				boolean cdata = true;
				String createTime = "";
				@SuppressWarnings("unchecked")
				public void startNode(String name, Class clazz) {
					if(name!=null&&name.equals("CreateTime")){
						createTime = "CreateTime";
					}else{
						createTime=name;
					}
					super.startNode(name, clazz);
				}
				protected void writeText(QuickWriter writer, String text) {
					if (cdata&&!createTime.equals("CreateTime")) {
						writer.write("<![CDATA[");
						writer.write(text);
						writer.write("]]>");
					} else {
						writer.write(text);
					}
				}
			};
		}
	});
}

第二种方法(注解)

package com.xml.date.CDATA;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface XStreamCDATA {

  
}

package com.xml.date.CDATA;

import com.thoughtworks.xstream.annotations.XStreamAlias;

public class TextMessageDto {
    
    @XStreamAlias("ToUserName")
    @XStreamCDATA
    private String ToUserName;
    
    @XStreamAlias("FromUserName")
    @XStreamCDATA
    private String FromUserName;
    
    private long CreateTime;
    private String MsgType;
    private int FuncFlag;
    
    public String getToUserName() {
        return ToUserName;
    }
    public void setToUserName(String toUserName) {
        ToUserName = toUserName;
    }
    public String getFromUserName() {
        return FromUserName;
    }
    public void setFromUserName(String fromUserName) {
        FromUserName = fromUserName;
    }
    public long getCreateTime() {
        return CreateTime;
    }
    public void setCreateTime(long createTime) {
        CreateTime = createTime;
    }
    public String getMsgType() {
        return MsgType;
    }
    public void setMsgType(String msgType) {
        MsgType = msgType;
    }
    public int getFuncFlag() {
        return FuncFlag;
    }
    public void setFuncFlag(int funcFlag) {
        FuncFlag = funcFlag;
    }

    
}

package com.xml.date.CDATA;

import java.io.Writer;
import java.lang.reflect.Field;
import java.util.Date;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;

/**
 * 消息工具类
* @author 高国藩
* @date 2015年8月6日 上午9:38:53 
*
 */
public class MessageUtil {

   private static XStream xstream = createXstream();

    public static XStream createXstream() {
        return new XStream(new XppDriver() {
          @Override
          public HierarchicalStreamWriter createWriter(Writer out) {
            return new PrettyPrintWriter(out) {
              boolean cdata = false;
              Class<?> targetClass = null;
              @Override
              public void startNode(String name,
                  @SuppressWarnings("rawtypes") Class clazz) {
                super.startNode(name, clazz);
                //业务处理,对于用XStreamCDATA标记的Field,需要加上CDATA标签
                if(!name.equals("xml")){
                  cdata = needCDATA(targetClass, name);
                }else{
                  targetClass = clazz;
                }
              }

              @Override
              protected void writeText(QuickWriter writer, String text) {
                if (cdata) {
                  writer.write(cDATA(text));
                } else {
                  writer.write(text);
                }
              }
            };
          }
        });
      }
    
    private static String cDATA(String text){
        return "<![CDATA["+text+"]]>";
    }
    
    private static boolean needCDATA(Class<?> targetClass, String fieldAlias){
        boolean cdata = false;
        //first, scan self
        cdata = existsCDATA(targetClass, fieldAlias);
        if(cdata) return cdata;
        //if cdata is false, scan supperClass until java.lang.Object
        Class<?> superClass = targetClass.getSuperclass();
        while(!superClass.equals(Object.class)){
          cdata = existsCDATA(superClass, fieldAlias);
          if(cdata) return cdata;
          superClass = superClass.getClass().getSuperclass();
        }
        return false;
      }
    
    private static boolean existsCDATA(Class<?> clazz, String fieldAlias){
        //scan fields
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
          //1. exists XStreamCDATA
          if(field.getAnnotation(XStreamCDATA.class) != null ){
            XStreamAlias xStreamAlias = field.getAnnotation(XStreamAlias.class);
            //2. exists XStreamAlias
            if(null != xStreamAlias){
              if(fieldAlias.equals(xStreamAlias.value()))//matched
                return true;
            }else{// not exists XStreamAlias
              if(fieldAlias.equals(field.getName()))
                return true;
            }
          }
        }
        return false;
      }
    
    /**
     * 文本消息对象转换成xml
     * alias 起别名,如果没有,根节点将面为com.pacage.textMessage的形式
     * @param textMessage 文本消息对象
     * @return xml
     */
    public static String textMessageToXml(TextMessageDto textMessage) {
        xstream.alias("xml", textMessage.getClass());
        return xstream.toXML(textMessage);
    }
    
    public static void main(String[] args) {
        TextMessageDto textMessage = new TextMessageDto();
        textMessage.setCreateTime(new Date().getTime());
        textMessage.setFromUserName("来源");
        textMessage.setToUserName("取出");
        textMessage.setFuncFlag(0);
        textMessage.setMsgType("news");
        String str = MessageUtil.textMessageToXml(textMessage);
        System.out.println(str);
    }
    

    
}

结果
<xml>
  <ToUserName><![CDATA[取出]]></ToUserName>
  <FromUserName><![CDATA[来源]]></FromUserName>
  <CreateTime>1442486285083</CreateTime>
  <MsgType>news</MsgType>
  <FuncFlag>0</FuncFlag>
</xml>



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值