眾所周知,大家在微信開發工程中,由於微信開發文檔中,對於消息的接收發送都是基礎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<>();