利用AJAX返回xml数据:使用AJAX和XML完成操作
在这里我们可以通过一个普通的静态的xml文件,然后利用AJAX来接收xml的返回效果。当然也可以直接在后台利用DOM动态生成xml文件,并通过AJAX进行显示。
一、接收静态的xml数据:
XML:先创建一个xml页面,然后在此界面定义要接收的节点元素,并给定值(先定义一个根元素,在根元素下定义它的子节点,子节点中再定义子节点,并为节点赋值)。
<?xml version="1.0" encoding="UTF-8"?>
<allarea>
<area>
<id>1</id>
<title>北京</title>
</area>
<area>
<id>2</id>
<title>广东</title>
</area>
<area>
<id>3</id>
<title>上海</title>
</area>
</allarea>
JSP:在jsp页面中创建XMLHttpRequest对象,在创建这个对象的时候,一定要注意浏览器兼容的问题,检查浏览器是否支持XMLHttpRequest对象,如果支持,就创建XMLHttpRequest对象,否则就创建ActiveXObject对象。
//创建XMLHttpRequest对象 需要考虑浏览器兼容的问题
var xmlHttp;
function createXMLHttp(){
if(window.XMLHttpRequest){// code for IE7+, Firefox, Chrome, Opera, Safari
xmlHttp=new XMLHttpRequest();
}else{// code for IE6, IE5
xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
}
}
AJAX向服务器发送请求,使用XMLHttpRequest对象中的open()和send()方法进行请求。
1、open()方法包括三个参数:open(method,url,async)。
第一个参数method是请求的类型,是利用get还是post方式进行请求;
第二个参数url代表文件在服务器上的位置(该文件可以是任何类型的文件,比如.xml和.txt,或者服务器脚本文件);
第三个参数代表async代表是否为异步提交,如果是异步提交就设置为true,选择同步提交的话就设置为false。
一般来说,默认不写就是为异步提交,因为Ajax本身就是Asynchronous JavaScript and XML(异步的JavaScript和 XML),所以async参数总是设置成true的,这标志着在请求开始后,其他代码依然能够执行。
当async=true时,要在响应处于 onreadystatechange 事件中的就绪状态时执行回调函数。
然后通过send()方法向服务器发送请求,
2、send(string) post请求时才使用字符串参数,否则不用带参数(get请求时)
通过 AJAX,JavaScript 无需等待服务器的响应,而是:
在等待服务器响应时执行其他脚本;
当响应就绪后对响应进行处理;
function getCity(){
createXMLHttp();
xmlHttp.open("POST", "${ctx}/jsp/allarea.xml");//
xmlHttp.onreadystatechange=getCityCallback;
xmlHttp.send(null);
}
回调函数:接收服务器返回的内容。先判断readyState是否已经响应完成,也就是可以访问服务器响应并使用它,以及Status状态是否OK,也就是status=200的时候,如果是响应状态为404,则是未找到页面。
通过XMLHttpRequest对象中的responseXML获得xml形式的响应数据,如果不是xml文件,就用responseText属性(获得字符串形式的响应数据)。在这里利用xmlHttp.responseXML.getElementsByTagName()来获取根元素下的所有的节点,然后获取当前页面下拉框中的id属性,并设置每次只能选择一个,且设置第一个为选中状态,再通过for循环遍历,当i小于节点的长度时,获取根元素下的子元素名称为’id’和’title’的节点值,并创建option元素,把节点值设置于option元素中,最后把option元素追加到下拉框中
function getCityCallback(){
if(xmlHttp.readyState == 4 && xmlHttp.status == 200){
// children 取得全部的allarea下的节点
var allarea = xmlHttp.responseXML.getElementsByTagName("allarea")[0].children; //获取下拉框的id值
var select = document.getElementById("city") ;
select.length = 1 ; // 每次选择一个
select.options[0].selected = true ;// 设置第一个为选中的状态
//利用for循环遍历
for(var i=0;i<allarea.length;i++){
var option = document.createElement("option");
var id=allarea[i].getElementsByTagName("id")[0].firstChild.nodeValue;
var title=allarea[i].getElementsByTagName("title")[0].firstChild.nodeValue;
option.setAttribute("value",id) ;
option.appendChild(document.createTextNode(title)) ;
select.appendChild(option) ;
}
}
}
HTML代码:
<body onload="getCity()">
<form action="" method="post" style="text-align: center;padding: 20px;">
<h2 style="color: blue;">请选择喜欢的城市</h2>
<select id="city" name="city" style="width: 200px;height: 30px;">
<option value="0">请选择...</option>
</select>
</form>
</ body >
最后的效果:
二、返回DOM动态的xml数据:
1、首先要设置响应的文本内容类型,创建打印流来输出,创建数组输出流用来存放结果。
2、定义一个工厂API,使应用程序能够获得一个解析器,该解析器从xml文档生成DOM对象树;再定义从xml文档获取DOM文档实例的API,使用这个类,可以从xml中获取文档;创建DOM文件对象的新实例,用来构建DOM节点,Document文档接口表示整个HTML或XML文档,从概念上讲,它是文档树的根,提供对文档数据的主要访问。
3、从数据库查询出数据,利用for循环遍历获取值,将获取到的值添加到集合中。
创建元素节点,Element元素接口表示HTML或XML文档中的元素,先创建一个根元素。然后利用for循环遍历,x是否小于查询的值的大小,小于的话就创建根元素下的子节点,子节点下追加一个文本节点,添加到此节点子列表的末尾,并给定值,设置同级的父目录节点,子节点添加到父节点中,最后把循环的结果添加到文档中,然后再对文档中的数据进行访问。
4、创建TransformerFactory实例,在这里用于创建Transformer对象;创建Transformer对象,这个抽象类的实例可以将源树转换为结果树,一个新的转换器,将源文件的副本执行到结果中,即“恒等变换”,它可以在当线程中执行转换,不能为null。设置对转换生效的输出属性。创建DOMSource文本,以文档对象模型(DOM)树的形式充当转换源树的持有者,使用DOM节点创建一个新的输入源,包含源树的DOM节点。
6、利用内存流输出结果数组,StreamResult充当转换结果的持有者,转换结果可以是XML、纯文本、HTML或其它的形式。从字节流构造一个流结果,通常应该使用流而不是读取器,以便于转换器可以转换指令中包含的指令来控制编码。最后将XML源转换为结果,打印结果集到输出流中,最最后要记得关闭流。
Jsp页面中,只要在open()方法中改变url就可以了,其余的不变,这样就可以显示咱们的DOM动态xml数据啦。
xmlHttp.open("POST", "${ctx}/servlet/TestServlet?type=SelectCity");
servlet源代码:
public void SelectCity(HttpServletRequest request,HttpServletResponse response) throws ParserConfigurationException, TransformerException, IOException{
response.setContentType("text/xml;charset=GBK") ;
PrintWriter out = response.getWriter() ;
ByteArrayOutputStream bos = new ByteArrayOutputStream() ;
Connection con=null;
PreparedStatement ps=null;
ResultSet rs=null;
try{
//定义一个工厂API(创建一个文件工厂实例)
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance() ;
//定义从XML文档获取DOM文档实例的API。使用这个类,应用程序程序员可以从XML获取文档
DocumentBuilder builder = factory.newDocumentBuilder();//创建实例 用来配置参数
//创建DOM文件对象 用来创建树节点 (获取DOM文档对象的一个新实例,用它来构建DOM树)
Document doc = builder.newDocument();
//查询数据
con=DbUtil.getConnection();
ps=con.prepareStatement("select city,cityMC from city");
rs=ps.executeQuery();
List<Test> tests=new ArrayList<Test>();
Test test=null;
while(rs.next()){
test=new Test();
test.setCityMC(rs.getString("cityMC"));
tests.add(test);
}
//遍历获取值
String city=null;
List<String> str=new ArrayList<String>();
for (Test test1 : tests) {
city=test1.getCityMC();
str.add(city);
}
//创建节点 元素接口表示HTML或XML文档中的元素 根元素
Element allarea = doc.createElement("allarea") ;//创建指定类型的元素
for(int x=0;x<tests.size();x++){
Element area = doc.createElement("area") ;
Element id = doc.createElement("id") ;
Element title = doc.createElement("title") ;
//创建文本节点 添加到此节点的子列表的末尾
id.appendChild(doc.createTextNode("" + (x+1))) ;
title.appendChild(doc.createTextNode(str.get(x)));//创建文本节点
area.appendChild(id);//添加子节点
area.appendChild(title);
allarea.appendChild(area);
}
doc.appendChild(allarea);//把根元素加进去
TransformerFactory实例 主要是被用来创建Transformer对象
TransformerFactory tf = TransformerFactory.newInstance();
//创建Transformer对象,可以在单线程中执行转换的Transformer对象 不能为null
Transformer t = tf.newTransformer();
t.setOutputProperty(OutputKeys.ENCODING,"GBK") ;//设置将对转换生效的输出属性
//创建DOMSource文本 以文档对象模型(DOM)树的形式充当转换源树的持有者 使用DOM节点创建一个新的输入源 包含源树的DOM节点
DOMSource source = new DOMSource(doc) ;
//StreamResult充当转换结果的持有者,转换结果可以是XML、纯文本、HTML或其他形式的标记
StreamResult result = new StreamResult(bos) ;//内存流输出
t.transform(source,result) ;//将XML源转换为结果
out.println(bos);
out.close();
}catch(Exception e){
e.printStackTrace() ;
}
}
数据库的数据:
页面显示的结果: