众所周知,大家在微信开发工程中,由于微信开发文档中,对于消息的接收发送都是基础xml数据的(太坑了),所以我们需要对XML进行解析转换;
1.我们先引入所需要的依赖 dom4j (解析xml的),xstream(可以将对象,以及复杂对象转换为xml);
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>jdom</groupId>
<artifactId>jdom</artifactId>
<version>1.1</version>
</dependency>
<!-- 转换xml类 -->
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.5</version>
</dependency>
先给大家介绍一下Java 内置的 jaxp xml 解析器获取的方法,以及Document对象(可以忽视不看)
/** * 获取 jaxp XML 解析器 * 位于javax 包中,Java 内置支持 * @throws ParserConfigurationException */ public static DocumentBuilder getJaxpXmlBuilder() throws ParserConfigurationException { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); return builder; } /** * jaxp 获取Document 对象,通过一个文件/流对象 * @throws ParserConfigurationException * @throws IOException * @throws SAXException */ public static Document getJaxpDocument(DocumentBuilder builder,Object file) throws Exception { DocumentBuilder xmlBuilder; if((xmlBuilder=builder)==null) { xmlBuilder=getJaxpXmlBuilder(); } if(file instanceof File) { return xmlBuilder.parse((File)file); }else if(file instanceof InputStream) { return xmlBuilder.parse((InputStream)file); }else { return null; } }
获取dom4j xml 解析器获取的方法,以及Document对象
/** * dom4j * 初始化,获取document 对象通过输入url的方式 * @param readObject 可以是流,也可以是文件,也可以是URL ,也可以是InputSource * @return * @throws DocumentException */ public static org.dom4j.Document getDom4jDocument(Object readObject) throws DocumentException { SAXReader reader =new SAXReader(); org.dom4j.Document document ; if(readObject instanceof InputStream) { document =reader.read((InputStream)readObject); }else if(readObject instanceof File) { document =reader.read((File)readObject); }else if(readObject instanceof URL) { document =reader.read((URL)readObject); }else if(readObject instanceof InputSource){ document =reader.read((InputSource)readObject); }else { //没有匹配的的XML document =null; } return document; }
-------------------------------------------重点方法-------------------
2.开始编码 --我会对下面utils类进行解释
先介绍使用XStream 将XML 转换为一个对象,将一个对象转换为XML的方法,并附上实际demo;(需要引入 XStream 包)
(1)XStream 将XML 转换为对象
/** * 将xml 字符串转换为 pojo 对象 * 确保已经引入xstream 的jar 包 * 以及类上面使用了@XStreamAlias("你定义的"); * @param poClass,转化po的Class * @param xml * @return */ @SuppressWarnings("unchecked") public static <T> T xmlToPojo(Class<T> poClass,String xml) { XStream xstream =new XStream(); xstream.processAnnotations(poClass); xstream.processAnnotations(getInnerClasses(poClass)); return (T)xstream.fromXML(xml); }
(2). XStream 将一个XML 流转换为对象;
/** * 将inputstream转换为 pojo 对象 * 确保已经引入xstream 的jar 包 * 以及类上面使用了@XStreamAlias("你定义的"); * @param poClass * @param xml * @return */ @SuppressWarnings("unchecked") public static <T> T streamToPojo(Class<T> poClass,InputStream stream) { XStream xstream =new XStream(); xstream.processAnnotations(poClass); xstream.processAnnotations(getInnerClasses(poClass)); return (T)xstream.fromXML(stream); }
(3).XStream 将对象转换为xml
/** * 使用 xstream 将一个人pojo 对象转换为xml 字符串 * 确保已经引入xstream 的jar 包 * 以及类上面使用了@XStreamAlias("你定义的"); * @param pojo * @return */ public static <T> String pojoToXml(T pojo) { Class<?> poClass = pojo.getClass(); XStream xstream =new XStream(); xstream.processAnnotations(poClass); xstream.processAnnotations(getInnerClasses(poClass)); return xstream.toXML(pojo); }
getInnerClasses()方法:
/** * 得到一个类的内部类 * @param clz * @return */ public static Class<?>[] getInnerClasses(Class<?> clz) { Class<?>[] innerClasses = clz.getClasses(); if (innerClasses == null) { return null; } List<Class<?>> result = new ArrayList<>(); result.addAll(Arrays.asList(innerClasses)); for (Class<?> inner : innerClasses) { Class<?>[] innerClz = getInnerClasses(inner); if (innerClz == null) { continue; } result.addAll(Arrays.asList(innerClz)); } return result.toArray(new Class<?>[0]); }
关于以上方法的demo 如下,让大家加深理解:
package com.baseknow.testclass; import java.util.List; import com.thoughtworks.xstream.annotations.XStreamAlias; //pojo @XStreamAlias("xml") public class XmlPojo { @XStreamAlias("timespace") private String times; @XStreamAlias("unionid") private String unionid; @XStreamAlias("openid") private String openid; @XStreamAlias("items") private List<Msg> msg; public XmlPojo(String times,String unionid,String openid){ this.times =times; this.unionid =unionid; this.openid =openid; } @XStreamAlias("item") public static class Msg{ @XStreamAlias("content") private String content; @XStreamAlias("tocode") private String code; public Msg(String content,String code){ this.content=content; this.code=code; } } public List<Msg> getMsg() { return msg; } public void setMsg(List<Msg> msg) { this.msg = msg; } public String getTimes() { return times; } public void setTimes(String times) { this.times = times; } public String getUnionid() { return unionid; } public void setUnionid(String unionid) { this.unionid = unionid; } public String getOpenid() { return openid; } public void setOpenid(String openid) { this.openid = openid; } }
main方法:--大家可以进行测试
public static void main(String[] args) { XmlPojo po =new XmlPojo("123","123","123"); Msg msg =new Msg("ss","ss"); Msg msg2 =new Msg("ss1","ss1"); List li =new ArrayList<>(); li.add(msg2);li.add(msg); po.setMsg(li); String pojoToXml = XmlParseUtils.pojoToXml(po); System.out.println(pojoToXml); //转pojo XmlPojo poo = XmlParseUtils.xmlToPojo(po.getClass(), pojoToXml); System.out.println(poo); }
OK,XStream 的常用方法就到这里,对于我来说,用XStream 就够了,很强大,很好扩展,更多需要学习它的api,下面介绍几个也会用到的方法
使用common.io 包下的 IOUtils 可以很方便的将input stream 转换为xml 字符串
public static String xmlStreamToString (HttpServletRequest request) throws Exception{ String result =IOUtils.toString(request.getInputStream(), "utf-8"); return result; }
dom4j 将xml数据流转换为map
public static Map<String,String> xmlTOMap(HttpServletRequest request) throws Exception{ Map<String,String> map =new HashMap<String,String>(); SAXReader reader =new SAXReader(); InputStream ins=null; try { ins =request.getInputStream(); } catch (IOException e) { e.printStackTrace(); } Document docment =reader.read(ins);//读取流对象 Element root=docment.getRootElement(); List<Element> list =root.elements(); for(Element ele:list) { map.put(ele.getName(), ele.getText()); } return map; }
使用dom4j将XML转换为Map
public static Map<String,String> StrXmlTOMap(String strXml) throws Exception{ Map<String,String> map =new HashMap<String,String>(); Document docment = DocumentHelper.parseText(strXml); Element root=docment.getRootElement(); List<Element> list =root.elements(); for(Element ele:list) { map.put(ele.getName(), ele.getText()); } return map; }
(4)将Map转换为Xml
/* * Map转换成Xml */ public static String MapToXml(Map<String,Object> parameters){ StringBuffer sb = new StringBuffer(); sb.append("<xml>"); Set es = parameters.entrySet(); Iterator it = es.iterator(); while(it.hasNext()) { Map.Entry entry = (Map.Entry)it.next(); String k = (String)entry.getKey(); String v = (String)entry.getValue(); if ("attach".equalsIgnoreCase(k)||"body".equalsIgnoreCase(k)||"sign".equalsIgnoreCase(k)) { sb.append("<"+k+">"+"<![CDATA["+v+"]]></"+k+">"); }else { sb.append("<"+k+">"+v+"</"+k+">"); } } sb.append("</xml>"); return sb.toString(); }
完整版附上:
package com.baseknow.utils; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Properties; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathFactory; import org.apache.commons.io.IOUtils; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * xml 工具类 * 包含jaxp 解析器的创建; * Xpath 解析器的创建; * dom4j 解析器 * dom4j 解析器创建; * 获取XML document 对象; * 获取Node attriute * xml 的转换 * @author iscys * */ public class XmlParseUtils { /** * 使用 xstream 将一个人pojo 对象转换为xml 字符串 * 确保已经引入xstream 的jar 包 * 以及类上面使用了@XStreamAlias("你定义的"); * @param pojo * @return */ public static <T> String pojoToXml(T pojo) { Class<?> poClass = pojo.getClass(); XStream xstream =new XStream(); xstream.processAnnotations(poClass); xstream.processAnnotations(getInnerClasses(poClass)); return xstream.toXML(pojo); } /** * 将xml 字符串转换为 pojo 对象 * 确保已经引入xstream 的jar 包 * 以及类上面使用了@XStreamAlias("你定义的"); * @param poClass * @param xml * @return */ @SuppressWarnings("unchecked") public static <T> T xmlToPojo(Class<T> poClass,String xml) { XStream xstream =new XStream(); xstream.processAnnotations(poClass); xstream.processAnnotations(getInnerClasses(poClass)); return (T)xstream.fromXML(xml); } /** * 将inputstream转换为 pojo 对象 * 确保已经引入xstream 的jar 包 * 以及类上面使用了@XStreamAlias("你定义的"); * @param poClass * @param xml * @return */ @SuppressWarnings("unchecked") public static <T> T streamToPojo(Class<T> poClass,InputStream stream) { XStream xstream =new XStream(); xstream.processAnnotations(poClass); xstream.processAnnotations(getInnerClasses(poClass)); return (T)xstream.fromXML(stream); } /** * 使用common 包将流转换为字符串 * @param stream * @return * @throws Exception */ public static String xmlStreamToString (InputStream stream) throws Exception{ String result =IOUtils.toString(stream, "utf-8"); return result; } /** * 获取 jaxp XML 解析器 * 位于javax 包中,Java 内置支持 * @throws ParserConfigurationException */ public static DocumentBuilder getJaxpXmlBuilder() throws ParserConfigurationException { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); return builder; } /** * 获取xpath的实例对象 */ public static XPath getXpath() { XPathFactory factory = XPathFactory.newInstance(); XPath xpath = factory.newXPath(); return xpath; } /** * jaxp 获取Document 对象,通过一个文件/流对象 * @throws ParserConfigurationException * @throws IOException * @throws SAXException */ public static Document getJaxpDocument(DocumentBuilder builder,Object file) throws Exception { DocumentBuilder xmlBuilder; if((xmlBuilder=builder)==null) { xmlBuilder=getJaxpXmlBuilder(); } if(file instanceof File) { return xmlBuilder.parse((File)file); }else if(file instanceof InputStream) { return xmlBuilder.parse((InputStream)file); }else { return null; } } /** * dom4j * 初始化,获取document 对象通过输入url的方式 * @param readObject 可以是流,也可以是文件,也可以是URL ,也可以是InputSource * @return * @throws DocumentException */ public static org.dom4j.Document getDom4jDocument(Object readObject) throws DocumentException { SAXReader reader =new SAXReader(); org.dom4j.Document document ; if(readObject instanceof InputStream) { document =reader.read((InputStream)readObject); }else if(readObject instanceof File) { document =reader.read((File)readObject); }else if(readObject instanceof URL) { document =reader.read((URL)readObject); }else if(readObject instanceof InputSource){ document =reader.read((InputSource)readObject); }else { //没有匹配的的XML document =null; } return document; } /** * dom4j * 获取根节点 * @param readObject可以是流,也可以是文件,也可以是URL ,也可以是InputSource * @return * @throws DocumentException */ public static Element getDom4jRootElement(Object readObject) throws DocumentException { org.dom4j.Document document = getDom4jDocument(readObject); Element root = document.getRootElement(); return root; } /** * 将node 属性key value 存放到 Properties 中;eg: * <test name ="mytest" class="com.XX.XX"> * 将name ->mytest * class -> com.XXX.XXX * 存入Properties * */ public static Properties parseNodeAttributes(Node n) { Properties attributes = new Properties(); NamedNodeMap attributeNodes = n.getAttributes(); //判断是否为空 if (attributeNodes != null) { for (int i = 0; i < attributeNodes.getLength(); i++) { Node attribute = attributeNodes.item(i); attributes.put(attribute.getNodeName(), attribute.getNodeValue()); } } return attributes; } /** * 得到一个类的内部类 * @param clz * @return */ public static Class<?>[] getInnerClasses(Class<?> clz) { Class<?>[] innerClasses = clz.getClasses(); if (innerClasses == null) { return null; } List<Class<?>> result = new ArrayList<>(); result.addAll(Arrays.asList(innerClasses)); for (Class<?> inner : innerClasses) { Class<?>[] innerClz = getInnerClasses(inner); if (innerClz == null) { continue; } result.addAll(Arrays.asList(innerClz)); } return result.toArray(new Class<?>[0]); } }
-----为了怕大家对xstream 注解不了解,大致就是这样的
@XStreamAlias("xml") //在xstream 注解转化时候,会将类名变为xml ,下面也一样 public class Pojo { @XStreamAlias("namealia") private String name; @XStreamAlias("agelia") private String age; @XStreamAlias("lists") private List<InnerPojo> list =new ArrayList<>();