原生AJAX或jQuery实现二级联动选择以及解析XML和JSON数据格式
本文以省和城市为例来实现二级联动选择框,包含了DOM4J生成XML数据的方式和使用JSONArray类生成JSON数据格式的方式。以及服务器返回的数据类型XML和JSON格式在JavaScript和jQuery中的解析方法。
项目包结构图:
ProName
|--src
| |-- com
| |--ajax
| |--bean
| | |--City.java
| | |--CreateJSONObject.java
| |--servlet
| |--SelectCityServlet.java
|--WebRoot
|--js
| |--jquery.js
| |--selectCity.js
| |--selectCityjQuery.js
|--WEB-INF
| |--c.tld
| |--web.xml
|--selectCity.jsp
1. 页面代码(selectCity.jsp)
<%@ page language="java" import="java.util.*,com.ajax.bean.City"
pageEncoding="utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%
String path = request.getContextPath();
//初始化省份选择框数据
List<City> provinceList = City.getProvinceList();
request.setAttribute("provinceList", provinceList);
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>省和城市的级联选择实例</title>
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/selectCity.js"></script>
<script type="text/javascript" src="js/selectCityjQuery.js"></script>
</head>
<body>
<p />
一、AJAX原生方式实现省和城市的级联选择:
<p />
<table cellspacing="0" cellpadding="2" align="left" border="0">
<tr>
<td style="width: 20px">
</td>
<td>
省份:
</td>
<td style="width: 100px">
<select id="provinceIdSelect" style="width: 80px"
οnchange="selectProvince()">
<option value="" selected>
全部
</option>
<c:if test="${!empty provinceList }">
<c:forEach var="province" items="${provinceList}">
<option value="${province.id }" ${province.id==provinceId?'selected':''}>
${province.name}
</option>
</c:forEach>
</c:if>
</select>
</td>
<td style="width: 20px">
</td>
<td>
城市:
</td>
<td style="width: 100px">
<select id="cityIdSelect" style="width: 80px">
<option value="0">
全部
</option>
</select>
</td>
</tr>
</table>
<br />
<br />
二、jQuery方式实现省和城市的级联选择:
<p />
<table cellspacing="0" cellpadding="2" align="left" border="0">
<tr>
<td style="width: 20px">
</td>
<td>
省份:
</td>
<td style="width: 100px">
<select id="provinceIdSelectJ" style="width: 80px"
οnchange="selectProvinceJ()">
<option value="" selected>
全部
</option>
<c:if test="${!empty provinceList }">
<c:forEach var="province" items="${provinceList}">
<option value="${province.id }" ${province.id==provinceId?'selected':''}>
${province.name}
</option>
</c:forEach>
</c:if>
</select>
</td>
<td style="width: 20px">
</td>
<td>
城市:
</td>
<td style="width: 100px">
<select id="cityIdSelectJ" style="width: 80px">
<option value="0">
全部
</option>
</select>
</td>
</tr>
</table>
</body>
</html>
2. JS代码
selectCity.js
//创建AJAX引擎
function createXmlhttp () {
var xhr;
if (window.XMLHttpRequest) {
//针对FireFox,Mozillar,Opera,Safari,IE7,IE8
xhr = new XMLHttpRequest();
//针对某些特定版本的mozillar浏览器的BUG进行修正
if (xhr.overrideMimeType) {
xhr.overrideMimeType("text/xml");
}
} else if (window.ActiveXObject) {
//针对IE6,IE5.5,IE5
//两个可以用于创建XMLHTTPRequest对象的控件名称,保存在一个js的数组中
//排在前面的版本较新
var activexName = ["MSXML2.XMLHTTP","Microsoft.XMLHTTP"];
for (var i = 0; i < activexName.length; i++) {
try{
//取出一个控件名进行创建,如果创建成功就终止循环
//如果创建失败,回抛出异常,然后可以继续循环,继续尝试创建
xhr = new ActiveXObject(activexName[i]);
break;
} catch(e){
}
}
}
return xhr;
}
var xmlhttp;
//发送请求
function sendRequest(url ,content){
xmlhttp = createXmlhttp ();
xmlhttp.onreadystatechange = processResponse;
xmlhttp.open("post",url);
xmlhttp.setRequestHeader("content-type","application/x-www-form-urlencoded");
xmlhttp.send(content);
}
//回调方法
function processResponse(){
if (xmlhttp.readyState == 4 ) {
if (xmlhttp.status == 200 ){
//设置城市选择框为默认值
setCityDefault();
//获得服务器返回的XML,并转为DOC对象
var xmldoc = xmlhttp.responseXML;
//DOM解析XML
domParseXml(xmldoc);
//JSON格式解析
// parseJson(xmlhttp.responseText);
}
}
}
//DOM解析XML
function domParseXml(xmldoc){
//遍历服务器响应的XML,并创建对应option标签
//获取显示城市的选择框
var cityId_obj = document.getElementById("cityIdSelect");
//获取具有指定标记名的所有元素节点
// var city = xmldoc.getElementsByTagName("city");
var city = xmldoc.selectNodes("/cities/city");
for (var i=0; i<city.length; i++ ) {
//获取节点文本
var id_txt = city[i].childNodes[0].childNodes[0].data; //data和nodeValue都可以
var name_txt = city[i].childNodes[1].childNodes[0].nodeValue;
//创建节点对象
var id_obj = document.createTextNode(id_txt);
var name_obj = document.createTextNode(name_txt);
//创建城市<option>
var cityOption = document.createElement("option");
//设置value属性
cityOption.setAttribute("value",id_obj);
//设置name属性
cityOption.appendChild(name_obj);
cityId_obj.appendChild(cityOption);
}
}
//解析JSON数据
function parseJson(obj){
//通过eval() 函数可以将JSON字符串转化为对象
var json = eval(obj)
//获取显示城市的选择框
var cityId_obj = document.getElementById("cityIdSelect");
//遍历JSON数组
for (var ind in json) {
//创建城市<option>
var cityOption = document.createElement("option");
//创建节点对象,将文本转为dom对象
var id_obj = document.createTextNode(json[ind].id);
var name_obj = document.createTextNode(json[ind].name);
//设置value属性
cityOption.setAttribute("value",id_obj);
//设置name属性
cityOption.appendChild(name_obj);
cityId_obj.appendChild(cityOption);
}
}
//改变省选择框触发事件,ajax异步请求
function selectProvince(){
var provinceId_obj = document.getElementById("provinceIdSelect");
if ( provinceId_obj.value != "" ) {
var url = "selectCity";
var content = "provinceId=" + provinceId_obj.value ;
//发送AJAX请求
sendRequest(url, content);
} else {
//设置城市选择框为默认值
setCityDefault();
}
}
//设置城市选择框为默认值
function setCityDefault(){
//获取显示城市的选择框
var cityId_obj = document.getElementById("cityIdSelect");
//清除原来的select值
cityId_obj.options.length=0;
//添加默认的option标签
//创建option标签
var defOption_obj = document.createElement("option");
defOption_obj.setAttribute("value","0");
//设置默认选择
var defName_obj = document.createTextNode("全部")
defOption_obj.appendChild(defName_obj);
cityId_obj.appendChild(defOption_obj);
}
selectCityjQuery.js,jquery版本为1.2.6
//创建异步请求
function selectProvinceJ(){
var pidNode = $("#provinceIdSelectJ");
if ( pidNode.val() != "" ) {
//第一种:服务器以JSON响应
// jsonResponseProcess(pidNode);
//第二种:服务器以XML响应
xmlResponseProcess(pidNode);
} else {
//设置城市选择框为默认值
setCityDefaultJ();
}
}
//请求后,返回JSON数据类型
function jsonResponseProcess(pidNode){
var pid = pidNode.val();
$.post("selectCity",
{provinceId : pid},
function(json){
//获取显示城市的选择框
var cidNode = $("#cityIdSelectJ");
//清空之前内容
cidNode.empty();
$(json).each(function(i){
cidNode.append("<option value='" + json[i].id + "'>" + json[i].name + "</option>" );
});
},
"json" //xml, html, script, json, text, _default
);
}
//请求后,返回XML数据类型
function xmlResponseProcess(pidNode){
var pid = pidNode.val();
$.post("selectCity",
{provinceId : pid},
function(xml){
//获取显示城市的选择框
var cidNode = $("#cityIdSelectJ");
//清空之前内容
cidNode.empty();
var id_txt;
var name_txt;
$(xml).find("city").each(function(i){
//children()先取得ID对象,text()再取值
id_txt = $(this).children("id").text();
//另一种取对象方法
name_txt = $("name",this).text();
cidNode.append("<option value='" + id_txt + "'>" + name_txt + "</option>" );
});
},
"xml" //xml, html, script, json, text, _default
);
}
//设置城市选择框为默认值
function setCityDefaultJ(){
var cidNode = $("#cityIdSelectJ");
//删除匹配的元素集合中所有的子节点。
cidNode.empty();
cidNode.append("<option>全部</option>");
}
3. Servlet/javaBean代码
SelectCityServlet.java
package com.ajax.servlet;
import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.ajax.bean.City;
import com.ajax.bean.CreateJSONObject;
import com.ajax.bean.CreateXMLText;
/**
* @author fzbtshy@163.com
*/
public class SelectCityServlet extends HttpServlet {
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// 生成XML和文本文件返回
response.setContentType("text/xml");
response.setCharacterEncoding("UTF-8");
String provinceId = request.getParameter("provinceId");
String provinceXml = null;
List<City> cityList = null;
try {
if (null != provinceId && !"".equals(provinceId)) {
// 根据id获取该省的城市列表
cityList = City.getCityList(Long.valueOf(provinceId));
//DOM4J方式生成XML
provinceXml = dom4jToXml(cityList);
//JSON数据格式返回
// CreateJSONObject json = new CreateJSONObject();
// provinceXml = json.nativeToJson(cityList);
// provinceXml = json.jsonArrayToJson(cityList);
}
response.getWriter().print(provinceXml);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* DOM4J生成XML
*
* @param list
* @return
*/
public String dom4jToXml(List<City> list) {
String strXml = null;
try {
if (null != list && !list.isEmpty()) {
DocumentFactory df = DocumentFactory.getInstance();
// org.dom4j.Document doc = DocumentHelper.createDocument();
org.dom4j.Document doc = df.createDocument("UTF-8");
// 创建根节点
org.dom4j.Element citiesElt = doc.addElement("cities");
for (City po : list) {
// 在节点<cities>下增加子节点<city>
org.dom4j.Element cityElt = citiesElt.addElement("city");
// 在节点<city>下增加子节点<id>
org.dom4j.Element idElt = cityElt.addElement("id");
idElt.addText(String.valueOf(po.getId()));
// 在节点<city>下增加子节点<name>
org.dom4j.Element nameElt = cityElt.addElement("name");
nameElt.addText(po.getName());
}
// 无样式的
strXml = doc.asXML();
}
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("DOM4J:" + strXml);
return strXml;
}
}
City.java
package com.ajax.bean;
import java.util.ArrayList;
import java.util.List;
public class City {
// 主键
private Long id;
// parentId为0代表是省份,否则为城市
private Long parentId;
// 名字
private String name;
/**
* 默认构造器
*/
public City() {
}
/**
* @param id
* @param parentId
* @param name
*/
public City(Long id, Long parentId, String name) {
super();
this.id = id;
this.parentId = parentId;
this.name = name;
}
/**
* @return the id
*/
public Long getId() {
return id;
}
/**
* @param id
* the id to set
*/
public void setId(Long id) {
this.id = id;
}
/**
* @return the parentId
*/
public Long getParentId() {
return parentId;
}
/**
* @param parentId
* the parentId to set
*/
public void setParentId(Long parentId) {
this.parentId = parentId;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name
* the name to set
*/
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "id=" + this.id + ",parentId=" + this.parentId + ",name="
+ this.name;
}
/**
* 测试用 获取省份
*
* @return
*/
public static List<City> getProvinceList() {
List<City> provinceList = new ArrayList<City>();
City city = new City(101L, 0L, "湖南省");
provinceList.add(city);
city = new City(102L, 0L, "广东省");
provinceList.add(city);
city = new City(103L, 0L, "浙江省");
provinceList.add(city);
return provinceList;
}
/**
* 测试用 获取城市
*
* @return
*/
public static List<City> getCityList(Long provinceId) {
List<City> cityList = new ArrayList<City>();
City city = null;
// 编写湖南的城市
if (provinceId.equals(101L)) {
city = new City(151L, 101L, "长沙市");
cityList.add(city);
city = new City(152L, 101L, "永州市");
cityList.add(city);
city = new City(153L, 101L, "衡阳市");
cityList.add(city);
city = new City(154L, 101L, "郴州市");
cityList.add(city);
city = new City(155L, 101L, "常德市");
cityList.add(city);
} else if (provinceId.equals(102L)) {
// 编写广东的城市
city = new City(171L, 102L, "广州市");
cityList.add(city);
city = new City(172L, 102L, "深圳市");
cityList.add(city);
city = new City(173L, 102L, "东莞市");
cityList.add(city);
city = new City(174L, 102L, "中山市");
cityList.add(city);
city = new City(175L, 102L, "佛山市");
cityList.add(city);
city = new City(176L, 102L, "江门市");
cityList.add(city);
} else if (provinceId.equals(103L)) {
// 编写浙江的城市
city = new City(191L, 103L, "杭州市");
cityList.add(city);
city = new City(192L, 103L, "宁波市");
cityList.add(city);
}
return cityList;
}
public static void main(String[] args) {
List<City> province = City.getProvinceList();
for (City p : province) {
System.out.println(p);
}
List<City> city = City.getCityList(101L);
for (City c : city) {
System.out.println(c);
}
}
}
CreateJSONObject.java
package com.ajax.bean;
import java.util.List;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
/**
* 生成json的数据格式
*
* @author fzbtshy@163.com
*/
public class CreateJSONObject {
// 采用json的数据格式返回对象信息
// 冒号后可以为[{pid1:{id:"",name:""}, pid2:{id:"",name:""}}]
// json格式:
// [{
// id: "city.getId()",
// name: "city.getName()",
// },
// {
// id: "city.getId()",
// name: "city.getName()",
// }]
/**
* 字符串拼接的方式
* @param list
* @return 如:[{id:151,name:'长沙市'},{id:152,name:'永州市'}]
*/
public String nativeToJson(List<City> list) {
StringBuilder jsonStr = new StringBuilder(list.size());
if (null != list && !list.isEmpty()) {
int i=0;
jsonStr.append("[");
for (City po : list) {
jsonStr.append("{id:")
.append(po.getId())
.append(",name:'")
.append(po.getName())
.append("'}");
//最后不用加逗号
if ( (++i) != list.size() ){
jsonStr.append(",");
}
}
jsonStr.append("]");
}
System.out.println("Native:" + jsonStr.toString());
return jsonStr.toString();
}
/**
* json-lib.jar
* 依赖包:commons-logging.jar
* common.lang.jar
* commons-beanutils.jar
* commons-collections.jar
* ezmorph.jar
* @param list
* @return
*/
public String jsonArrayToJson(List<City> list ) {
//第一种方式,返回[{"parentId":101,"citys":[],"name":"长沙市","id":151},{"parentId":101,"citys":[],"name":"永州市","id":152}]
// JSONArray js = JSONArray.fromObject(list);
//第二种方式,返回[{"name":"长沙市","id":151},{"name":"永州市","id":152}]
JSONArray js = new JSONArray();
if (null != list && !list.isEmpty()) {
JSONObject obj = null;
for ( City po: list ){
obj = new JSONObject();
obj.put("id", po.getId());
obj.put("name", po.getName());
js.add(obj);
obj = null;
}
}
System.out.println("JSONArray:" + js.toString());
return js.toString();
}
public static void main(String[] args) {
List<City> list = City.getCityList(101L);
CreateJSONObject json = new CreateJSONObject();
json.nativeToJson(list);
json.jsonArrayToJson(list);
}
}
4. web.xml
<servlet>
<servlet-name>SelectCity</servlet-name>
<servlet-class>com.ajax.SelectCityServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SelectCity</servlet-name>
<url-pattern>/selectCity</url-pattern>
</servlet-mapping>