(5)微信二次開發 之 XML格式數據解析


1、首先理解一下html

         html的全名是:HyperText Transfer markup language 超級文本標記語言,html本質上是一門標記(符合)語言,在html里,這些標記是事先定義(規則)好的,並且賦予了其特定的含義。有一套 固定的標記的集合。

         網頁文件的擴展名是 .html或者 .htm,都是可行的。

         文檔聲明:<!doctype html>  這里的doctype不管是大小寫都是可以的,並且兼容html4/html5。

         html中的標記一般都是有開始標簽和結束標簽,例如:<html>...</html>、<body>...</body>等標簽。但是也有一些標簽是沒有內容主體的,可以直接寫成:<br />、<hr />.

         在html里的所有標簽都是有固定含義的,不能自己隨便去定義,雖然有一些是自定義的標簽,但是最終還是繼承和使用html的固定標簽。

         需要學習html4、html5、css2、css3等前段的開發,基礎入門網站:http://www.w3school.com.cn/

         編寫html的時候使用的一些編輯器,例如:notepad++、editplus、hbuilder等。

2、理解XML

         xml的全名是:Extensible Markup Language 可擴展標記語言,在xml文件里的所有標簽都是可以自由定於的。

         xml的擴展名為:.xml

         xml文件頭部信息為:<?xml version="1.0" ?>

         xml文件有且只有一個跟節點

         xml中的節點與節點之間可以允許嵌套

3、微信二次開發中使用XML的理解

         由於微信協議數據傳輸其實就是采用xml格式進行傳輸,所以我們必須要了解xml的格式以及傳輸數據的解析和生成。

         當微信A用戶 -> 發送數據消息 -> 給B用戶,中間需要微信服務器進行中轉。例如:微信文本消息協議格式(該功能的數據傳輸是基於xml格式)

         微信公眾號開發文檔地址:https://mp.weixin.qq.com/wiki

         文本消息格式(用戶發送給服務,服務器接收的格式)如下: 

1 <xml>
2  <ToUserName><![CDATA[toUser]]></ToUserName>
3  <FromUserName><![CDATA[fromUser]]></FromUserName>
4  <CreateTime>1348831860</CreateTime>
5  <MsgType><![CDATA[text]]></MsgType>
6  <Content><![CDATA[你好]]></Content>
7  <MsgId>1234567890123456</MsgId>
8  </xml>

 

 

 

         如圖解析:

          

 

   根據上面的xml格式,<![CDATA[       ]]>這類型的數據是指字符數據,CDATA是由character(字符)和data(數據)的簡稱縮寫。

       每個微信用戶是通過openid來加以區分的,而openid就是根據個人的微信號進行一定的加密算法鎖構成的,openid是由字母、數字、構成的一串字符串(該長度是28位)。在我們自己的微信服務器上收到的還是與原來的微信服務器所轉發過來的xml格式串還是一致的。所以我們就需要在我們自己的服務器的程序里進行解析 xml格式串。

 

4、xml格式解析

         目前在java里面對xml解析有4種方法:

         1、DOM(Documemt Object Model)文檔對象模型,Dom是一次性讀取整個文檔,如果xml文檔比較大,節點比較多的情況下,解析的時候比較消耗資源、內存,性能比較低,不建議使用。

         2、SAX(Simple API for XML)。使用SAX解析,是基於事件驅動方式來解析xml。解析器在讀取xml文件根據讀取的數據產生相應的事件,解析速度快,占用內存少,性能比較好。

         3、DOM4J是第三方類庫,對SAX解析進行了封裝。

         4、JDOM也是第三方類庫,也是對SAX解析進行了封裝。

        

         DOM與SAX解析方式是java自帶的,不需要第三方額外的jar包。二DOM4J和JDOM都是第三方開源的,使用的時候需要下載支持第三方支持的jar包。

        

         

 

 

5、聲明一個xml文件使用4種方式進行解析

  創建一個parseXml的java項目,將創建以一個studentMsg.xml文件,

 

  如圖顯示:

  

  

  編輯xml文件:

  

 1 <?xml version="1.0" ?>
 2 <!-- 所在部門標簽 -->
 3 <department>
 4     <!-- 員工標簽:屬性number是工號 -->
 5     <employee number="001">
 6         <!-- 員工的個人信息 -->
 7         <name>小海</name>
 8         <sex></sex>
 9         <profession>java開發</profession>
10         <hobby>足球</hobby>
11     </employee>
12     <employee number="002">
13         <!-- 員工的個人信息 -->
14         <name>婷菲</name>
15         <sex></sex>
16         <profession>C#開發</profession>
17         <hobby>跑步</hobby>
18     </employee>
19 </department>

         這里的xml文件放在(我本地的位置):

         /Users/wangxianhai/work_sts_01/parseXML/src/com/aixunma/xml/studentMsg.xml

6、聲明XML文檔內容信息的類

 1 package com.aixunma.xml;  2 
 3 /**
 4  * XML文檔內容信息的對應的字段  5  * <p>類的描述:</p>  6  * <p>@Description: TODO</p>  7  * <p>@author 小海</p>  8  * <p>@time:2017年4月29日 下午6:04:00</p>  9  * <p>@Vesion: 1.0</p> 10  */
11 public class XmlParam { 12     
13     public static final String LABLE_EMPLOYEE = "employee"; // 員工標簽
14     public static final String LABLE_NAME = "name"; // 名稱標簽
15     public static final String LABLE_SEX = "sex"; // 性別標簽
16     public static final String LABLE_PROFESSION = "profession"; // 職業標簽
17     public static final String LABLE_HOBBY = "hobby"; // 愛好標簽
18     
19     private int number; 20     private String name; 21     private String sex; 22     private String profession; 23     private String hobby; 24     
25     public int getNumber() { 26         return number; 27  } 28     public void setNumber(int number) { 29         this.number = number; 30  } 31     public String getName() { 32         return name; 33  } 34     public void setName(String name) { 35         this.name = name; 36  } 37     public String getSex() { 38         return sex; 39  } 40     public void setSex(String sex) { 41         this.sex = sex; 42  } 43     public String getProfession() { 44         return profession; 45  } 46     public void setProfession(String profession) { 47         this.profession = profession; 48  } 49     public String getHobby() { 50         return hobby; 51  } 52     public void setHobby(String hobby) { 53         this.hobby = hobby; 54  } 55  @Override 56     public String toString() { 57         StringBuilder builder = new StringBuilder(); 58         builder.append("number=").append(number).append("\n") 59             .append("name=").append(name).append("\n") 60             .append("sex=").append(sex).append("\n") 61             .append("profession=").append(profession).append("\n") 62             .append("hobby=").append(hobby).append("\n"); 63         return builder.toString(); 64  } 65 }

7、實現DOM方式解析xml

 1 package com.aixunma.xml;  2 
 3 import java.io.File;  4 
 5 import javax.security.auth.login.LoginException;  6 import javax.xml.parsers.DocumentBuilder;  7 import javax.xml.parsers.DocumentBuilderFactory;  8 
 9 import org.apache.commons.lang.StringUtils;  10 import org.w3c.dom.Document;  11 import org.w3c.dom.Element;  12 import org.w3c.dom.Node;  13 import org.w3c.dom.NodeList;  14 
 15 /**
 16  * 使用DOM解析xml文件  17  * <p>類的描述:</p>  18  * <p>@Description: TODO</p>  19  * <p>@author 小海</p>  20  * <p>@time:2017年4月29日 下午2:28:27</p>  21  * <p>@Vesion: 1.0</p>  22  */
 23 public class DomPaeseXML {  24     /**
 25  * 解析xml文檔內容  26  * @return
 27  * @throws Exception  28      */
 29     public static String parseXMl() throws Exception {  30         
 31         // 1、創建一個文檔構建工廠對象
 32         final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();  33         
 34         // 2、通過工廠對象創建一個文檔構造器對象
 35         final DocumentBuilder db = dbf.newDocumentBuilder();  36         
 37         // 3、聲明xml文件在本地的路徑,並且加載該xml文件
 38         final String path = "/Users/wangxianhai/work_sts_01/parseXML/src/com/aixunma/xml/studentMsg.xml";  39         final File file = new File(path);  40         
 41         // 4、通過文檔構造器解析文件加載的對象成文檔對象
 42         final Document parse = db.parse(file);  43         
 44         // 5、通過文檔對象獲取頭部節點
 45         final Element headNode = parse.getDocumentElement();  46         
 47         final StringBuilder builder = new StringBuilder();  48         
 49         // 6、通過頭節遍歷下面的子節點列表
 50         final NodeList childNodes = headNode.getChildNodes();  51         if (childNodes == null) {  52             return "";  53  }  54  parseXmlToStr(childNodes, builder);  55         return builder.toString();  56  }  57     
 58     /**
 59  * 將節點列表遍歷生成字符串  60  * @param childNodes 節點列表  61  * @param builder 記錄節點內容  62  * @return
 63      */
 64     public static StringBuilder parseXmlToStr(NodeList childNodes, StringBuilder builder) {  65         // 判斷節點列表是否為空
 66         if (childNodes == null) {  67             return builder;  68  }  69         
 70         // 遍歷節點列表
 71         for (int i = 0; i < childNodes.getLength(); i++) {  72             // 獲取子節點
 73             final Node iemt = childNodes.item(i);  74             // 因為節點又好幾種類型,需要判斷屬於ELEMENT_NODE類型的
 75             if (iemt != null && iemt.getNodeType() == Node.ELEMENT_NODE) {  76                 // 節點的內容值
 77                 final String nodeValue = iemt.getFirstChild().getNodeValue();  78                 // 如果值為為空,則不獲取
 79                 if (StringUtils.isNotBlank(nodeValue)) {  80                     final String nodeName = iemt.getNodeName();  81                     builder.append(nodeName).append("\t").append(nodeValue).append("\n");  82  }  83  }  84             
 85             // 再次獲取子節點的子節點列表
 86             final NodeList childNodesNext = iemt.getChildNodes();  87             parseXmlToStr(childNodesNext, builder); // 繼續回調該方法,獲取子節點下的子節點
 88  }  89         return builder;  90  }  91     
 92     // 測試
 93     public static void main(String[] args) throws Exception {  94         try {  95             final String string = parseXMl();  96  System.out.println(string);  97         } catch (Exception e) {  98             throw new LoginException("解析xml文件失敗");  99  } 100  } 101 }

8、實現SAX方式解析xml

 1 package com.aixunma.xml;  2 
 3 import java.io.File;  4 import java.util.ArrayList;  5 import java.util.List;  6 
 7 import javax.security.auth.login.LoginException;  8 import javax.xml.parsers.SAXParser;  9 import javax.xml.parsers.SAXParserFactory;  10 
 11 import org.apache.commons.lang.math.NumberUtils;  12 import org.xml.sax.Attributes;  13 import org.xml.sax.SAXException;  14 import org.xml.sax.helpers.DefaultHandler;  15 
 16 /**
 17  * SAX解析XML文檔信息  18  * <p>類的描述:</p>  19  * <p>@Description: TODO</p>  20  * <p>@author 小海</p>  21  * <p>@time:2017年4月29日 下午5:38:07</p>  22  * <p>@Vesion: 1.0</p>  23  */
 24 public class SaxParseXML {  25     public static String parseXml() throws Exception {  26         // 1、創建一個SAX解析工廠對象
 27         final SAXParserFactory spy = SAXParserFactory.newInstance();  28         
 29         // 2、通過工廠對象獲取SAX解析對象
 30         final SAXParser parser = spy.newSAXParser();  31         
 32         // 3、加載xml文件
 33         final String path = "/Users/wangxianhai/work_sts_01/parseXML/src/com/aixunma/xml/studentMsg.xml";  34         final File file = new File(path);  35         
 36         
 37         parser.parse(file, new MyDefaultHandler());  38         
 39         return "1";  40  }  41     
 42     public static void main(String[] args) throws Exception {  43         try {  44  parseXml();  45         } catch (Exception e) {  46             throw new LoginException("xml解析失敗");  47  }  48  }  49 }  50 // 內部了繼承SAX的DefaultHandler的類,重新下面的方法,獲取相應的信息
 51 class MyDefaultHandler extends DefaultHandler{  52     
 53     private List<XmlParam> xmlParamList = null;  54     private XmlParam xmlParam = null;  55     private String preTag = null; // 記錄解析時的上一個節點名稱
 56     
 57     /**
 58  * 解析文檔開始:初始化的作用  59      */
 60  @Override  61     public void startDocument () throws SAXException {  62             System.out.println("-------解析xml開始-----");  63             xmlParamList = new ArrayList<XmlParam>();  64  }  65     
 66     /**
 67  * 解析開始節點  68      */
 69  @Override  70     public void startElement (String uri, String localName,  71             String startName, Attributes attributes) throws SAXException {  72         if (XmlParam.LABLE_EMPLOYEE.equals(startName)) { // 判斷是否是employee員工開始標簽
 73             final String attrValue = attributes.getValue("number"); // 工號  74             // 初始化xmlParam對象
 75             xmlParam = new XmlParam();  76             xmlParam.setNumber(NumberUtils.toInt(attrValue, 0)); // 轉化成int類型,默認值是0表示沒有暫時沒有工號
 77  }  78         preTag = startName; // 將正在解析的節點名稱賦給preTag
 79  }  80     
 81     /**
 82  * 解析結束節點  83      */
 84  @Override  85     public void endElement (String uri, String localName, String endName) throws SAXException {  86         if (XmlParam.LABLE_EMPLOYEE.equals(endName)) { // 判斷是否是employee員工結束標簽  87             // 將xmlParam對象加入list集合
 88  xmlParamList.add(xmlParam);  89  }  90         /*
 91  * 注意這里要將preTag為null。當執行到<name>小海</name>的結束的時候,會調用  92  * 這個節點結束方法,如果這里不把preTag置為null,根據startElement(....)方法,preTag的值還是number,  93  * 會執行characters(char[] ch, int start, int length)這個方法  94  * 而characters(....)方法判斷preTag!=null,會執行if判斷的代碼,這樣就會把空值賦值給book  95  *  96  * 總的來說每解析一對節點(不包括文檔頭節點和尾節點)執行方法順序:  97  * startElement(...)->characters(...)->endElement(...)  98          */
 99         preTag = null; 100  } 101     
102     /**
103  * 獲取節點內容 104      */
105  @Override 106     public void characters(char[] ch, int start, int length) { 107         if (preTag != null) { 108             final String content = new String(ch, start, length); 109             if (XmlParam.LABLE_NAME.equals(preTag)) { 110  xmlParam.setName(content); 111             } else if (XmlParam.LABLE_SEX.equals(preTag)) { 112  xmlParam.setSex(content); 113             } else if(XmlParam.LABLE_PROFESSION.equals(preTag)) { 114  xmlParam.setProfession(content); 115             } else if (XmlParam.LABLE_HOBBY.equals(preTag)) { 116  xmlParam.setHobby(content); 117  } 118  } 119  } 120     
121     /**
122  * 解析文檔結束 123      */
124  @Override 125     public void endDocument () throws SAXException { 126          //輸出數據
127          for(XmlParam xmlParam : xmlParamList) { 128  System.out.println(xmlParam.toString()); 129  } 130          System.out.println("-------解析xml結束-----"); 131  } 132 }

9、實現DOM4J方式解析xml

 1 package com.aixunma.xml;  2 
 3 import java.io.File;  4 import java.util.Iterator;  5 import java.util.List;  6 
 7 import org.apache.commons.lang.StringUtils;  8 import org.dom4j.Attribute;  9 import org.dom4j.Document; 10 import org.dom4j.Element; 11 import org.dom4j.io.SAXReader; 12 import org.junit.Test; 13 
14 /**
15  * 使用DOM4J解析XML文檔、生成文檔、操作節點、刪除節點、添加節點 16  * <p>類的描述:</p> 17  * <p>@Description: TODO</p> 18  * <p>@author 小海</p> 19  * <p>@time:2017年4月29日 下午9:35:34</p> 20  * <p>@Vesion: 1.0</p> 21  */
22 public class Dom4jParseXML { 23     
24     private static String PARSE_XML_PATH = "/Users/wangxianhai/work_sts_01/parseXML/src/com/aixunma/xml/studentMsg.xml"; 25     
26     /**
27  * 解析XML文檔 28  * @throws Exception 29      */
30  @Test 31     public void parseXml() throws Exception { 32         // 1、創建SAXReader對象
33         final SAXReader reader = new SAXReader(); 34         
35         // 2、通過SAXReader對象讀取xml文件生成Domcument文檔對象
36         final Document document = reader.read(new File(PARSE_XML_PATH)); 37         
38         // 3、獲取根節點對象
39         final Element root = document.getRootElement(); 40         
41         // 4、遍歷
42  listNodes(root); 43  } 44     
45     /**
46  * 遍歷節點 47  * @param node 48      */
49     public void listNodes(Element node) { 50         // 獲取節點的名稱
51         /*final String nodeName = node.getName(); 52         
53  System.out.println(nodeName);*/
54         
55         // 遍歷屬性節點
56         final List<Attribute> attributes = node.attributes(); 57         for (Attribute attribute : attributes) { 58             System.out.println(attribute.getName() + "=" + attribute.getText()); 59  } 60         
61         // 獲取當前節點的內容
62         if (StringUtils.isNotBlank(node.getTextTrim())) { // 內容不為空的讀取
63             System.out.println(node.getName() + "=" + node.getText()); 64  } 65         
66         //迭代該節點的所有子節點
67         final Iterator iterator = node.elementIterator(); 68         while (iterator.hasNext()) { 69             Element el = (Element) iterator.next(); 70             listNodes(el); // 使用遞歸
71  } 72  } 73 }

10、實現JDOM方式解析xml

 1 package com.aixunma.xml;  2 
 3 import java.io.File;  4 import java.util.List;  5 
 6 import org.apache.commons.lang.StringUtils;  7 import org.jdom.Attribute;  8 import org.jdom.Document;  9 import org.jdom.Element; 10 import org.jdom.JDOMException; 11 import org.jdom.input.SAXBuilder; 12 import org.junit.Test; 13 
14 /**
15  * 使用JDOM解析XML文檔信息 16  * <p>類的描述:</p> 17  * <p>@Description: TODO</p> 18  * <p>@author 小海</p> 19  * <p>@time:2017年5月1日 下午11:24:10</p> 20  * <p>@Vesion: 1.0</p> 21  */
22 public class JdomParseXML { 23     
24     private static String PARSE_XML_PATH = "/Users/wangxianhai/work_sts_01/parseXML/src/com/aixunma/xml/studentMsg.xml"; 25     
26     /**
27  * 解析XML文檔 28  * @throws Exception 29  * @throws JDOMException 30  * @throws Exception 31      */
32  @Test 33     public void parseXml() throws JDOMException, Exception { 34         
35         // 創建一個JDOM的SAX的構造器
36         final SAXBuilder builder = new SAXBuilder(); 37         
38         // 通過構造器獲取文檔對象
39         final Document document = builder.build(new File(PARSE_XML_PATH)); 40         
41         // 獲取文檔的根元素
42         final Element root = document.getRootElement(); 43         
44         // 遍歷
45  listNodes(root); 46  } 47     
48     /**
49  * 遍歷節點 50  * @param node 51      */
52     public void listNodes(Element node) { 53         // 獲取節點的名稱
54         /*final String name = node.getName(); 55  System.out.println(name);*/
56         
57         // 獲取節點所有屬性list集合
58         final List<Attribute> attributes = node.getAttributes(); 59         // 遍歷節點的所有屬性
60         for (Attribute attribute : attributes) { 61             System.out.println(attribute.getName() + "=" + attribute.getValue()); 62  } 63         
64         // 獲取節點存在的內容
65         if (StringUtils.isNotBlank(node.getTextTrim())) { 66             System.out.println(node.getName() + "=" + node.getText()); 67  } 68         
69         // 獲取該節點下的所有子節點
70         List<Element> children = node.getChildren(); 71         for (Element element : children) { 72             listNodes(element); // 遞歸調用
73  } 74  } 75 }

11、四種方式結果展示

  

  

  

  

12、致謝

         感謝各位的閱讀,希望對您有幫助,需要源碼加QQ:963551706 謝謝!

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM