4.3.4 响应消息对象转XML
公众账号服务器接收并处理完用户发送的消息后,需要返回特定的XML结构对消息进行响应。为了方便在程序中以对象的方式操作消息,我们已经在4.2.3节中将各种类型的响应消息封装成了Java对象。现在要解决的问题是如何将响应消息对象转换成XML字符串,这就需要用到4.3.2节中介绍的XStream类库,实现代码如下:
- /**
- * 扩展xstream使其支持CDATA
- */
- private static XStream xstream = new XStream(new XppDriver() {
- public HierarchicalStreamWriter createWriter(Writer out) {
- return new PrettyPrintWriter(out) {
- // 对所有XML节点的转换都增加CDATA标记
- boolean cdata = true;
- @SuppressWarnings("unchecked")
- public void startNode(String name, Class clazz) {
- super.startNode(name, clazz);
- }
- protected void writeText(QuickWriter writer, String text) {
- if (cdata) {
- writer.write("<![CDATA[");
- writer.write(text);
- writer.write("]]>");
- } else {
- writer.write(text);
- }
- }
- };
- }
- });
- /**
- * 文本消息对象转换成XML
- *
- * @param textMessage 文本消息对象
- * @return xml
- */
- public static String messageToXml(TextMessage textMessage) {
- xstream.alias("xml", textMessage.getClass());
- return xstream.toXML(textMessage);
- }
- /**
- * 图片消息对象转换成XML
- *
- * @param imageMessage 图片消息对象
- * @return xml
- */
- public static String messageToXml(ImageMessage imageMessage) {
- xstream.alias("xml", imageMessage.getClass());
- return xstream.toXML(imageMessage);
- }
- /**
- * 语音消息对象转换成XML
- *
- * @param voiceMessage 语音消息对象
- * @return xml
- */
- public static String messageToXml(VoiceMessage voiceMessage) {
- xstream.alias("xml", voiceMessage.getClass());
- return xstream.toXML(voiceMessage);
- }
- /**
- * 视频消息对象转换成XML
- *
- * @param videoMessage 视频消息对象
- * @return xml
- */
- public static String messageToXml(VideoMessage videoMessage) {
- xstream.alias("xml", videoMessage.getClass());
- return xstream.toXML(videoMessage);
- }
- /**
- * 音乐消息对象转换成XML
- *
- * @param musicMessage 音乐消息对象
- * @return xml
- */
- public static String messageToXml(MusicMessage musicMessage) {
- xstream.alias("xml", musicMessage.getClass());
- return xstream.toXML(musicMessage);
- }
- /**
- * 图文消息对象转换成XML
- *
- * @param newsMessage 图文消息对象
- * @return xml
- */
- public static String messageToXml(NewsMessage newsMessage) {
- xstream.alias("xml", newsMessage.getClass());
- xstream.alias("item", new Article().getClass());
- return xstream.toXML(newsMessage);
- }
由于XStream本身不支持CDATA,上面的代码首先对XStream做了扩展,使其支持在生成XML各元素值时添加CDATA标记。接着,通过方法重载定义了6个messageToXml()方法,用于将响应消息对象转换成XML。
说明 XML解析器通常会解析XML文档中的所有文本。当某个XML元素被解析时,其标签之间的文本也会被解析,所以,在XML元素中,“<”和“&”是非法的,因为“<”会被解析器解释为新元素的开始,而“&”会被解析器解释为字符实体的开始,因此不能这样写:。
那么,对于XML标签内的文本的确需要包含“<”或“&”时该如何处理?这就要用到转义字符或CDATA,本书采用的是后者。CDATA指的是不应由XML解析器进行解析的文本数据(Unparsed Character Data),CDATA标记由“<![CDATA[”开始,由“]]>”结束,标记内的所有文本都会被解析器忽略。因此,上面那段XML的正确写法应该是:。