如下是实现过程:
第一步:准备xml文件,并放置在网站根目录下,名为Area.xml- <?xml version="1.0" encoding="utf-8" ?>
- <area>
- <province id="1" name="北京">
- <city id="1" name="北京">
- <county id="1" name="东城区" />
- <county id="2" name="西城区" />
- </city>
- </province>
- <province id="2" name="河北省">
- <city id="1" name="石家庄市">
- <county id="1" name="正定县" />
- <county id="2" name="灵寿县" />
- </city>
- <city id="2" name="邯郸市">
- <county id="1" name="邯郸县" />
- <county id="2" name="永年县" />
- </city>
- </province>
- <province id="3" name="海南省">
- <city id="1" name="海口市">
- <county id="1" name="龙华区" />
- <county id="2" name="秀英区" />
- <county id="3" name="美兰区" />
- </city>
- <city id="2" name="三亚市">
- <county id="1" name="天涯镇" />
- <county id="2" name="凤凰镇" />
- </city>
- </province>
- </area>
复制代码
第二步:创建与xml文件中定义的元素对应的实体类。
<province/>对应province类- public class Province
- {
- private string id;
- /// <summary>
- /// 编号
- /// </summary>
- public string Id
- {
- get { return id; }
- set { id = value; }
- }
- private string name;
- /// <summary>
- /// 名称
- /// </summary>
- public string Name
- {
- get { return name; }
- set { name = value; }
- }
- }
复制代码
<city/>对应City类:- public class City
- {
- private string id;
- /// <summary>
- /// 编号
- /// </summary>
- public string Id
- {
- get { return id; }
- set { id = value; }
- }
- private string name;
- /// <summary>
- /// 名称
- /// </summary>
- public string Name
- {
- get { return name; }
- set { name = value; }
- }
- }
复制代码
<county/>对应county类:- public class County
- {
- private string id;
- /// <summary>
- /// 编号
- /// </summary>
- public string Id
- {
- get { return id; }
- set { id = value; }
- }
- private string name;
- /// <summary>
- /// 名称
- /// </summary>
- public string Name
- {
- get { return name; }
- set { name = value; }
- }
- }
复制代码
第三步:编写服务器端处理程序类:Handler.cs
在这里,查询xml我采用的是System.Xml.XPath命名空间下的XPathSelectElements(string xpath)方法和XPathSelectElement(string xpath)方法,在根据省级编号获取市级编号的方法里面,我使用了xpath表达式(假设传入的省级编号为1):/area/province[@id='1']/city,这个表达式以“/”开头,表示使用绝对路径,因为area为根节点所以从area开始,接着它下面有province元素,当我想获取area下所有province元素中id属性值为1的province元素时,我可以使用/area/province[@id='1'],即在province后面加上[@id='1']这个条件,这时我就获取到了area下id属性为1的province元素了。接着我要获取该province元素下所有的city,那么只需在后面加上/city即可,所以最终的xpath表达式为:/area/province[@id='1']/city。
还有,因为此查询的xml是在当前网站的根目录,如果是在其它地方,那么在查询的时候要加上namespace
将从xml文件中读取到的值组装成对应的实体对象只后,我使用了System.Web.Script.Serialization命名空间下的JavaScriptSerializer类中的Serialize方法将得到的实体对象序列化成json数据返回给客户端。
第四步:编写html和js。- <html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>省市县三级联动下拉列表</title>
- <script src="Scripts/jquery-1.4.1.min.js" type="text/javascript"></script>
- <script type="text/javascript">
- $(function () {
- $.post("/Handler.ashx", { "type": "province" }, function (data, status) {
- if (status == "success") {
- if (data != "failure") {
- data = $.parseJSON(data); //解析服务器返回的json数据
- for (var i = 0; i < data.length; i++) {
- var value = data[i].Id + ":" + data[i].Name; //设置option选项的值,格式为:"编号:名称"
- $("#province").append("<option value='" + value + "'>" + data[i].Name + "</option>");
- }
- }
- }
- }, "text");
- $("#province").change(function () {
- var selectValue = $(this).val(); //获取选择的省级option的值
- var provId = selectValue.split(':')[0]; //取出编号
- var provTxt = selectValue.split(':')[1]; //取出名称
- $("#txtProvince").html(provTxt); //显示选择的省的名称
- $("#city").html("<option>==请选择市==</option>"); //当省级改变时将市级清空
- $("#county").html("<option>==请选择县==</option>"); //当省级改变时将县级清空
- $.post("/Handler.ashx", { "province": provId, "type": "city" }, function (data, status) {
- if (status == "success") {
- if (data != "failure") {
- data = $.parseJSON(data);
- for (var i = 0; i < data.length; i++) {
- var value = data[i].Id + ":" + data[i].Name;
- $("#city").append("<option value='" + value + "'>" + data[i].Name + "</option>");
- }
- }
- }
- }, "text");
- });
- $("#city").change(function () {
- var provId = $("#province").val().split(':')[0];
- var selectValue = $(this).val(); //同上
- var cityId = selectValue.split(':')[0]; //同上
- var cityTxt = selectValue.split(':')[1]; //同上
- $("#txtCity").html(cityTxt); //显示选择的市的名称
- $("#county").html("<option>==请选择县==</option>"); //同上
- $.post("/Handler.ashx", { "province": provId, "city": cityId, "type": "county" }, function (data, status) {
- if (status == "success") {
- if (data != "failure") {
- data = $.parseJSON(data);
- for (var i = 0; i < data.length; i++) {
- var value = data[i].Id + ":" + data[i].Name;
- $("#county").append("<option value='" + value + "'>" + data[i].Name + "</option>");
- }
- }
- }
- }, "text");
- });
- $("#county").change(function () {
- $("#txtCounty").html($(this).val().split(':')[1]); //显示选择的县的名称
- });
- });
- </script>
- </head>
- <body>
- <!--省-->
- <select id="province" name="province">
- </select>
- <!--市-->
- <select id="city" name="city">
- </select>
- <!--县-->
- <select id="county" name="county">
- </select>
- <br />
- <span id="txtProvince" style="color: #ff0000;"></span>- <span id="txtCity" style="color: #ff0000;"></span>- <span id="txtCounty" style="color: #ff0000;"></span>
- </body>
- </html>
复制代码
关于使用jQuery与服务器通信,我使用的是$.post方法,该方法的具体使用可以参考jQuery官方文档,这里我想说的是,遍历后通过对象.属性访问时,这个属性的名字是区分大小写的,这个名字是服务器端定义的名字,因为服务器序列化的是服务器端的实体对象。
在这个例子中,关键点就是如何使用XPath表达式,如何调用System.Xml.XPath命名空间下的XPathSelectElements(string xpath)方法。
最终结果如下图:

代码13,31,50行可以优化。
不建议多次修改DOM结构,可以拼接字符串后一次append
数据源是xml,我会用xslt来解析xml直接输出<option>,这样就不用再前台拼接字符串了。要求所有节点ID不能有相同。- <select id="province" name="province" next="#city">
- </select>
- <select id="city" name="city" next="#county">
- <option>==请选择市==</option>
- </select>
- </form>
- <select id="county" name="county">
- <option>==请选择县==</option>
- </select>
- <script type="text/javascript">
- $("#province,#city").change(function () {
- var nextSelect = $(this.getAttribute("next"));
- //if (nextSelect.size() > 0) {
- nextSelect.find("option:gt(0)").remove();
- var _id = $(this).find("option:selected").val();
- var query = { parentId: _id };
- $.get("/Handler.ashx", query, function (data, status) {
- //...
- nextSelect.append("<option>...</option>....");
- });
- //}
- });
- </script>
复制代码 |