(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
文本消息格式(用户发送给服务,服务器接收的格式)如下:
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1348831860</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[你好]]></Content>
<MsgId>1234567890123456</MsgId>
</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文件:
<?xml version="1.0" ?>
<!-- 所在部门标签 -->
<department>
<!-- 员工标签:属性number是工号 -->
<employee number="001">
<!-- 员工的个人信息 -->
<name>小海</name>
<sex>男</sex>
<profession>java开发</profession>
<hobby>足球</hobby>
</employee>
<employee number="002">
<!-- 员工的个人信息 -->
<name>婷菲</name>
<sex>女</sex>
<profession>C#开发</profession>
<hobby>跑步</hobby>
</employee>
</department>
这里的xml文件放在(我本地的位置):
/Users/wangxianhai/work_sts_01/parseXML/src/com/aixunma/xml/studentMsg.xml
6、声明XML文档内容信息的类
package com.aixunma.xml; /**
* XML文档内容信息的对应的字段
* <p>类的描述:</p>
* <p>@Description: TODO</p>
* <p>@author 小海</p>
* <p>@time:2017年4月29日 下午6:04:00</p>
* <p>@Vesion: 1.0</p>
*/
public class XmlParam { public static final String LABLE_EMPLOYEE = "employee"; // 员工标签
public static final String LABLE_NAME = "name"; // 名称标签
public static final String LABLE_SEX = "sex"; // 性别标签
public static final String LABLE_PROFESSION = "profession"; // 职业标签
public static final String LABLE_HOBBY = "hobby"; // 爱好标签 private int number;
private String name;
private String sex;
private String profession;
private String hobby; public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getProfession() {
return profession;
}
public void setProfession(String profession) {
this.profession = profession;
}
public String getHobby() {
return hobby;
}
public void setHobby(String hobby) {
this.hobby = hobby;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("number=").append(number).append("\n")
.append("name=").append(name).append("\n")
.append("sex=").append(sex).append("\n")
.append("profession=").append(profession).append("\n")
.append("hobby=").append(hobby).append("\n");
return builder.toString();
}
}
7、实现DOM方式解析xml
package com.aixunma.xml; import java.io.File; import javax.security.auth.login.LoginException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import org.apache.commons.lang.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList; /**
* 使用DOM解析xml文件
* <p>类的描述:</p>
* <p>@Description: TODO</p>
* <p>@author 小海</p>
* <p>@time:2017年4月29日 下午2:28:27</p>
* <p>@Vesion: 1.0</p>
*/
public class DomPaeseXML {
/**
* 解析xml文档内容
* @return
* @throws Exception
*/
public static String parseXMl() throws Exception { // 1、创建一个文档构建工厂对象
final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); // 2、通过工厂对象创建一个文档构造器对象
final DocumentBuilder db = dbf.newDocumentBuilder(); // 3、声明xml文件在本地的路径,并且加载该xml文件
final String path = "/Users/wangxianhai/work_sts_01/parseXML/src/com/aixunma/xml/studentMsg.xml";
final File file = new File(path); // 4、通过文档构造器解析文件加载的对象成文档对象
final Document parse = db.parse(file); // 5、通过文档对象获取头部节点
final Element headNode = parse.getDocumentElement(); final StringBuilder builder = new StringBuilder(); // 6、通过头节遍历下面的子节点列表
final NodeList childNodes = headNode.getChildNodes();
if (childNodes == null) {
return "";
}
parseXmlToStr(childNodes, builder);
return builder.toString();
} /**
* 将节点列表遍历生成字符串
* @param childNodes 节点列表
* @param builder 记录节点内容
* @return
*/
public static StringBuilder parseXmlToStr(NodeList childNodes, StringBuilder builder) {
// 判断节点列表是否为空
if (childNodes == null) {
return builder;
} // 遍历节点列表
for (int i = 0; i < childNodes.getLength(); i++) {
// 获取子节点
final Node iemt = childNodes.item(i);
// 因为节点又好几种类型,需要判断属于ELEMENT_NODE类型的
if (iemt != null && iemt.getNodeType() == Node.ELEMENT_NODE) {
// 节点的内容值
final String nodeValue = iemt.getFirstChild().getNodeValue();
// 如果值为为空,则不获取
if (StringUtils.isNotBlank(nodeValue)) {
final String nodeName = iemt.getNodeName();
builder.append(nodeName).append("\t").append(nodeValue).append("\n");
}
} // 再次获取子节点的子节点列表
final NodeList childNodesNext = iemt.getChildNodes();
parseXmlToStr(childNodesNext, builder); // 继续回调该方法,获取子节点下的子节点
}
return builder;
} // 测试
public static void main(String[] args) throws Exception {
try {
final String string = parseXMl();
System.out.println(string);
} catch (Exception e) {
throw new LoginException("解析xml文件失败");
}
}
}
8、实现SAX方式解析xml
package com.aixunma.xml; import java.io.File;
import java.util.ArrayList;
import java.util.List; import javax.security.auth.login.LoginException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory; import org.apache.commons.lang.math.NumberUtils;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler; /**
* SAX解析XML文档信息
* <p>类的描述:</p>
* <p>@Description: TODO</p>
* <p>@author 小海</p>
* <p>@time:2017年4月29日 下午5:38:07</p>
* <p>@Vesion: 1.0</p>
*/
public class SaxParseXML {
public static String parseXml() throws Exception {
// 1、创建一个SAX解析工厂对象
final SAXParserFactory spy = SAXParserFactory.newInstance(); // 2、通过工厂对象获取SAX解析对象
final SAXParser parser = spy.newSAXParser(); // 3、加载xml文件
final String path = "/Users/wangxianhai/work_sts_01/parseXML/src/com/aixunma/xml/studentMsg.xml";
final File file = new File(path); parser.parse(file, new MyDefaultHandler()); return "1";
} public static void main(String[] args) throws Exception {
try {
parseXml();
} catch (Exception e) {
throw new LoginException("xml解析失败");
}
}
}
// 内部了继承SAX的DefaultHandler的类,重新下面的方法,获取相应的信息
class MyDefaultHandler extends DefaultHandler{ private List<XmlParam> xmlParamList = null;
private XmlParam xmlParam = null;
private String preTag = null; // 记录解析时的上一个节点名称 /**
* 解析文档开始:初始化的作用
*/
@Override
public void startDocument () throws SAXException {
System.out.println("-------解析xml开始-----");
xmlParamList = new ArrayList<XmlParam>();
} /**
* 解析开始节点
*/
@Override
public void startElement (String uri, String localName,
String startName, Attributes attributes) throws SAXException {
if (XmlParam.LABLE_EMPLOYEE.equals(startName)) { // 判断是否是employee员工开始标签
final String attrValue = attributes.getValue("number"); // 工号
// 初始化xmlParam对象
xmlParam = new XmlParam();
xmlParam.setNumber(NumberUtils.toInt(attrValue, 0)); // 转化成int类型,默认值是0表示没有暂时没有工号
}
preTag = startName; // 将正在解析的节点名称赋给preTag
} /**
* 解析结束节点
*/
@Override
public void endElement (String uri, String localName, String endName) throws SAXException {
if (XmlParam.LABLE_EMPLOYEE.equals(endName)) { // 判断是否是employee员工结束标签
// 将xmlParam对象加入list集合
xmlParamList.add(xmlParam);
}
/*
* 注意这里要将preTag为null。当执行到<name>小海</name>的结束的时候,会调用
* 这个节点结束方法,如果这里不把preTag置为null,根据startElement(....)方法,preTag的值还是number,
* 会执行characters(char[] ch, int start, int length)这个方法
* 而characters(....)方法判断preTag!=null,会执行if判断的代码,这样就会把空值赋值给book
*
* 总的来说每解析一对节点(不包括文档头节点和尾节点)执行方法顺序:
* startElement(...)->characters(...)->endElement(...)
*/
preTag = null;
} /**
* 获取节点内容
*/
@Override
public void characters(char[] ch, int start, int length) {
if (preTag != null) {
final String content = new String(ch, start, length);
if (XmlParam.LABLE_NAME.equals(preTag)) {
xmlParam.setName(content);
} else if (XmlParam.LABLE_SEX.equals(preTag)) {
xmlParam.setSex(content);
} else if(XmlParam.LABLE_PROFESSION.equals(preTag)) {
xmlParam.setProfession(content);
} else if (XmlParam.LABLE_HOBBY.equals(preTag)) {
xmlParam.setHobby(content);
}
}
} /**
* 解析文档结束
*/
@Override
public void endDocument () throws SAXException {
//输出数据
for(XmlParam xmlParam : xmlParamList) {
System.out.println(xmlParam.toString());
}
System.out.println("-------解析xml结束-----");
}
}
9、实现DOM4J方式解析xml
package com.aixunma.xml; import java.io.File;
import java.util.Iterator;
import java.util.List; import org.apache.commons.lang.StringUtils;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.junit.Test; /**
* 使用DOM4J解析XML文档、生成文档、操作节点、删除节点、添加节点
* <p>类的描述:</p>
* <p>@Description: TODO</p>
* <p>@author 小海</p>
* <p>@time:2017年4月29日 下午9:35:34</p>
* <p>@Vesion: 1.0</p>
*/
public class Dom4jParseXML { private static String PARSE_XML_PATH = "/Users/wangxianhai/work_sts_01/parseXML/src/com/aixunma/xml/studentMsg.xml"; /**
* 解析XML文档
* @throws Exception
*/
@Test
public void parseXml() throws Exception {
// 1、创建SAXReader对象
final SAXReader reader = new SAXReader(); // 2、通过SAXReader对象读取xml文件生成Domcument文档对象
final Document document = reader.read(new File(PARSE_XML_PATH)); // 3、获取根节点对象
final Element root = document.getRootElement(); // 4、遍历
listNodes(root);
} /**
* 遍历节点
* @param node
*/
public void listNodes(Element node) {
// 获取节点的名称
/*final String nodeName = node.getName(); System.out.println(nodeName);*/ // 遍历属性节点
final List<Attribute> attributes = node.attributes();
for (Attribute attribute : attributes) {
System.out.println(attribute.getName() + "=" + attribute.getText());
} // 获取当前节点的内容
if (StringUtils.isNotBlank(node.getTextTrim())) { // 内容不为空的读取
System.out.println(node.getName() + "=" + node.getText());
} //迭代该节点的所有子节点
final Iterator iterator = node.elementIterator();
while (iterator.hasNext()) {
Element el = (Element) iterator.next();
listNodes(el); // 使用递归
}
}
}
10、实现JDOM方式解析xml
package com.aixunma.xml; import java.io.File;
import java.util.List; import org.apache.commons.lang.StringUtils;
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.junit.Test; /**
* 使用JDOM解析XML文档信息
* <p>类的描述:</p>
* <p>@Description: TODO</p>
* <p>@author 小海</p>
* <p>@time:2017年5月1日 下午11:24:10</p>
* <p>@Vesion: 1.0</p>
*/
public class JdomParseXML { private static String PARSE_XML_PATH = "/Users/wangxianhai/work_sts_01/parseXML/src/com/aixunma/xml/studentMsg.xml"; /**
* 解析XML文档
* @throws Exception
* @throws JDOMException
* @throws Exception
*/
@Test
public void parseXml() throws JDOMException, Exception { // 创建一个JDOM的SAX的构造器
final SAXBuilder builder = new SAXBuilder(); // 通过构造器获取文档对象
final Document document = builder.build(new File(PARSE_XML_PATH)); // 获取文档的根元素
final Element root = document.getRootElement(); // 遍历
listNodes(root);
} /**
* 遍历节点
* @param node
*/
public void listNodes(Element node) {
// 获取节点的名称
/*final String name = node.getName();
System.out.println(name);*/ // 获取节点所有属性list集合
final List<Attribute> attributes = node.getAttributes();
// 遍历节点的所有属性
for (Attribute attribute : attributes) {
System.out.println(attribute.getName() + "=" + attribute.getValue());
} // 获取节点存在的内容
if (StringUtils.isNotBlank(node.getTextTrim())) {
System.out.println(node.getName() + "=" + node.getText());
} // 获取该节点下的所有子节点
List<Element> children = node.getChildren();
for (Element element : children) {
listNodes(element); // 递归调用
}
}
}
11、四种方式结果展示
12、致谢
感谢各位的阅读,希望对您有帮助,需要源码加QQ:963551706 谢谢!
(5)微信二次开发 之 XML格式数据解析的更多相关文章
- iOS开发笔记3:XML/JSON数据解析
这篇主要总结在iOS开发中XML/JSON数据解析过程用到的方法.XML数据解析主要使用SAX方式的NSXMLParser以及DOM方式的GDataXML,JSON数据解析主要使用NSJSONSeri ...
- 小猪cms微信二次开发之怎样分页
$db=D('Classify'); $zid=$db->where(array('id'=>$this->_GET('fid'),'token'=>$this->tok ...
- Java微信二次开发(一)
准备用Java做一个微信二次开发项目,把流程写在这里吧. 第一天,做微信请求验证 需要导入库:servlet-api.jar 第一步:新建包com.wtz.service,新建类LoginServle ...
- iOS开发之解析XML格式数据
XML格式的数据是一种数据的传输格式.因为它方便编写.结构清晰,所以深受程序猿的喜爱,非常多人都喜欢使用XML格式数据传输或者作为程序的配置信息. 如今我将来实如今iOS中解析XML格式数据,语言使用 ...
- yii2 输出xml格式数据
作者:白狼 出处:http://www.manks.top/yii2_xml_response.html.html本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文 ...
- Android中解析XML格式数据的方法
XML介绍:Extensible Markup Language,即可扩展标记语言 一.概述 Android中解析XML格式数据大致有三种方法: SAX DOM PULL 二.详解 2.1 SAX S ...
- R语言XML格式数据导入与处理
数据解析 XML是一种可扩展标记语言,它被设计用来传输和存储数据.XML是各种应用程序之间进行数据传输的最常用的工具.它与Access,Oracle和SQL Server等数据库不同,数据库提供了更强 ...
- Android使用DOM生成和输出XML格式数据
Android使用DOM生成和输出XML格式数据 本文主要简单解说怎样使用DOM生成和输出XML数据. 1. 生成和输出XML数据 代码及凝视例如以下: try { DocumentBuilderFa ...
- Controller接收处理json、xml格式数据
1.RequestBody接收json格式的数据,并直接转为对象. User.java使用lombok依赖包 @Data @AllArgsConstructor @NoArgsConstructor ...
随机推荐
- 获取JVM的dump文件
获取JVM的dump文件的两种方式 1. JVM启动时增加两个参数: #出现 OOME 时生成堆 dump: -XX:+HeapDumpOnOutOfMemoryError #生成堆文件地址: -XX ...
- 关于Android开发的几点建议
绝不要在UI线程中做数据处理的工作,这会让你的app变慢,带来极差的用户体验. 要按照google发布的Design指导意见来设计app,比如一个holo主题app会给用户带来更好的用户体验. 不要复 ...
- CoreCLR源码探索(四) GC内存收集器的内部实现 分析篇
在这篇中我将讲述GC Collector内部的实现, 这是CoreCLR中除了JIT以外最复杂部分,下面一些概念目前尚未有公开的文档和书籍讲到. 为了分析这部分我花了一个多月的时间,期间也多次向Cor ...
- 用js实现图片的无缝滚动效果
实现图片的无缝滚动就是要让你的图片集在一定时间里自动切换,那就需要js里的定时器来控制时间. js中关于定时器的方法有两种:setTimeout和setInterval.它们接收的参数是一样的,第一个 ...
- [编织消息框架][JAVA核心技术]jdk动态代理
需要用到的工具 jdk : javac javap class 反编译 :JD-GUI http://jd.benow.ca/ import java.lang.reflect.Invocation ...
- sub,dl,dt,排版,横向滚动条,浮动元素居中,box-sizing
1.sub标签 下标 2.dl,dt,dd用的地方通常是具有标题,而标题下对应有若干列表简单的(栏目标题+对应标题列表)和标题对应下面有内容.在使用时候我们能简洁html代码情况下,学会灵活使用dl ...
- BroadcastReceiver简单应用实例
BroadcastReceiver是android四大组件之一,主要用于接收广播,它的简单实现方法如下: 1.定义继承BroadcastReceiver的MyReceiver类: /** * Crea ...
- Android下使用busybox的ifconfig
busybox ifconfig eth0 10.0.16.45 netmask 255.255.254.0 broadcast 10.0.16.186busybox route add defaul ...
- Springboot在IDEA中执行,开启热部署
仅适用IDEA中,eclipse中不需要设置 一.开启idea自动make功能 1 - Enable Automake from the compiler PRESS: CTRL + SHIFT + ...
- jquery处理checkbox(复选框)是否被选中
现在如果一个复选框被选中,是用checked=true,checked="checked"也行 要用prop代替attr会更好,虽然在jQuery1.6之前版本的attr()方法能 ...