在我们深入研究代码之前,我们需要做出一些决定。我们将使用XML返回数据,但是应该如何设计XML结构?我们的XML响应应该是什么样子的呢?我们不希望任何复杂,所以我们的目标是创建一个XML文档,如下所示:
<converted-values>
<decimal>97</decimal>
<hexadecimal>0x61</hexadecimal>
<octal>0141</octal>
<hyper>&0x61;</hyper>
<binary>1100001B</binary>
</converted-values>
使用这种格式,浏览器可以使用它的文档对象模型(DOM)解析器索引和检索数据。
有很多方法可以创建这个XML文档。为了简单起见,我们首先使用StringBuffer来包装数据和XML标记。
让我们看下在servlet代码中封装的XML数据。
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class AjaxResponseServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
// key is the parameter passed in from the JavaScript
// variable named url (see index.html)
String key = req.getParameter("key");
StringBuffer returnXML = null;
if (key != null) {
// extract the first character from key
// as an int, then convert that int to a String
int keyInt = key.charAt(0);
returnXML = new StringBuffer("\r\n<converted-values>");
returnXML.append("\r\n<decimal>"+
Integer.toString(keyInt)+"</decimal>");
returnXML.append("\r\n<hexadecimal>0x"+
Integer.toString(keyInt,16)+"</hexadecimal>");
returnXML.append("\r\n<octal>0"+
Integer.toString(keyInt,8)+"</octal>");
returnXML.append("\r\n<hyper>&0x"+
Integer.toString(keyInt,16)+";</hyper>");
returnXML.append("\r\n<binary>"+
Integer.toString(keyInt,2)+"B</binary>");
returnXML.append("\r\n</converted-values>");
// set up the response
res.setContentType("text/xml");
res.setHeader("Cache-Control", "no-cache");
// write out the XML string
res.getWriter().write(returnXML.toString( ));
}
else {
// if key comes back as a null, return a question mark
res.setContentType("text/xml");
res.setHeader("Cache-Control", "no-cache");
res.getWriter( ).write("?");
}
}
}
这段代码仅仅设置了一个名为returnXML的StringBuffer。然后我们将传入值转换为十进制、十六进制、等等,将它与一个适当的XML标记,并将它添加到缓冲当中。当我们完成了所有五种转化和添加结束标记(< /converted-values>),我们使用res.getWriter().write( )将响应发送回Ajax客户端。如果我们收到的key为null,我们返回一个问号(表示没有任何XML封装)。
下面,我们来设计客户端HTML页面,如图:
客户端代码显示了如何获取从服务器端发送的XML文档中的数据字段。
<!DOCTYPE HTML PUBLIC "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
<STYLE type="text/css">
.borderless { color:black; text-align:center; background:powderblue;
border-width:0;border-color:green; }
</STYLE>
<title>function</title>
<SCRIPT language="JavaScript" type="text/javascript">
var req;
function convertToXML( ) {
var key = document.getElementById("key");
var keypressed = document.getElementById("keypressed");
keypressed.value = key.value;
var url = "/ajaxcodeconverter-lab2/response?key=" + escape(key.value);
if (window.XMLHttpRequest) {
req = new XMLHttpRequest( );
}
else if (window.ActiveXObject) {
req = new ActiveXObject("Microsoft.XMLHTTP");
}
req.open("Get",url,true);
req.onreadystatechange = callback;
req.send(null);
}
function nonMSPopulate( ) {
xmlDoc = document.implementation.createDocument("","", null);
var resp = req.responseText;
var parser = new DOMParser( );
var dom = parser.parseFromString(resp,"text/xml");
decVal = dom.getElementsByTagName("decimal");
var decimal = document.getElementById('decimal');
decimal.value=decVal[0].childNodes[0].nodeValue;
hexVal = dom.getElementsByTagName("hexadecimal");
var hexadecimal = document.getElementById('hexadecimal');
hexadecimal.value=hexVal[0].childNodes[0].nodeValue;
octVal = dom.getElementsByTagName("octal");
var octal = document.getElementById('octal');
octal.value=octVal[0].childNodes[0].nodeValue;
hyperVal = dom.getElementsByTagName("hyper");
var hyper = document.getElementById('hyper');
hyper.value=hyperVal[0].childNodes[0].nodeValue;
binaryVal = dom.getElementsByTagName("binary");
var bin = document.getElementById('bin');
bin.value=binaryVal[0].childNodes[0].nodeValue;
}
function msPopulate( ) {
var resp = req.responseText;
var xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async="false";
xmlDoc.loadXML(resp);
nodes=xmlDoc.documentElement.childNodes;
dec = xmlDoc.getElementsByTagName('decimal');
var decimal = document.getElementById('decimal');
decimal.value=dec[0].firstChild.data;
hexi = xmlDoc.getElementsByTagName('hexadecimal');
var hexadecimal = document.getElementById('hexadecimal');
hexadecimal.value=hexi[0].firstChild.data;
oct = xmlDoc.getElementsByTagName('octal');
var octal = document.getElementById('octal');
octal.value=oct[0].firstChild.data;
bin = xmlDoc.getElementsByTagName('binary');
var binary = document.getElementById('bin');
binary.value=bin[0].firstChild.data;
hypertextml = xmlDoc.getElementsByTagName('hyper');
var hyper = document.getElementById('hyper');
hyper.value=hypertextml[0].firstChild.data;
}
function callback( ) {
if (req.readyState==4) {
if (req.status == 200) {
if (window.XMLHttpRequest) {
nonMSPopulate( );
}
else if (window.ActiveXObject) {
msPopulate( );
}
}
}
clear( );
}
function clear( ) {
var key = document.getElementById("key");
key.value="";
}
</SCRIPT>
</head>
<body>
<H1>
<CENTER>AJAX CHARACTER DECODER</CENTER>
</H1>
<H2>
<CENTER>Press a key to find its value.</CENTER>
</H2>
<form name="form1" action="/ajaxcodeconverter-lab2" method="get">
<table border="2" bordercolor="black" bgcolor="lightblue" valign="center"
align="center">
<tr>
<td align="center">
Enter Key Here ->
<input type="text" id="key" name="key" maxlength="1" size="1"
οnkeyup="convertToXML( );">
</td>
</tr>
</table>
<br>
<table class="borderless" border="1" valign="center" align="center">
<tr>
<td align="center" colspan="5">
Key Pressed:
<input class="borderless" type="text" readonly id="keypressed"
maxlength="1" size="1">
</td>
</tr>
<tr>
<td align="center"> Decimal </td>
<td align="center">Hexadecimal</td>
<td align="center"> Octal </td>
<td align="center">
Binary
</td>
<td align="center">
HTML
</td>
</tr>
<tr>
<td align="center"><input class="borderless" type="text" readonly
id="decimal" maxlength="6" size="6"></td>
<td align="center"><input class="borderless" type="text" readonly
id="hexadecimal" maxlength="6" size="6"></td>
<td align="center"><input class="borderless" type="text" readonly
id="octal" maxlength="6" size="6"></td>
<td align="center"><input class="borderless" type="text" readonly
id="bin" maxlength="8" size="8"></td>
<td align="center"><input class="borderless" type="text" readonly
id="hyper" maxlength="6" size="6"></td>
</tr>
</table>
</form>
</body>
</html>
记住,这一切都始于我们使用JavaScript写的callback()函数
记得convertToXML()是如何确定浏览器是Internet Explorer或者其他浏览器了吗?我们这里又有同样的问题。当callback()被调用时,它必须检查我们是否正在运行ActiveXObject(Internet Explorer)或XMLHttpRequest(其他所有主流浏览器)。
如果浏览器是Internet Explorer,我们运行msPopulate()来删除XML中的数据。否则,我们运行nonMSPopulate()。有什么区别吗?这与我们如何得到一个XML解析器和解析器提供的API。Mozilla Firefox和Safari都使用新的DOMParser()来获得一个内置解析器解析XML,而且据说Opera很快就会支持这个。Internet Explorer,另一方面,使用新的ActiveXObject(“Microsoft.XMLDOM”)得到微软的XML解析器。
function msPopulate( ) {
var resp = req.responseText;
var xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async="false";
xmlDoc.loadXML(resp);
dec = xmlDoc.getElementsByTagName('decimal');
var decimal = document.getElementById('decimal');
decimal.value=dec[0].firstChild.data;
hexi = xmlDoc.getElementsByTagName('hexadecimal');
var hexadecimal = document.getElementById('hexadecimal');
hexadecimal.value=hexi[0].firstChild.data;
oct = xmlDoc.getElementsByTagName('octal');
var octal = document.getElementById('octal');
octal.value=oct[0].firstChild.data;
bin = xmlDoc.getElementsByTagName('binary');
var binary = document.getElementById('bin');
binary.value=bin[0].firstChild.data;
hypertextml = xmlDoc.getElementsByTagName('hyper');
var hyper = document.getElementById('hyper');
hyper.value=hypertextml[0].firstChild.data;
}
在msPopulate( )这里,我们使用内置的浏览器功能,我已经被吹捧为一个程序员玩。我们开始通过ActiveXObject称微软。XMLDOM(第4行)。接下来,我们来自servlet的响应加载到XML文档(第6行)。
现在我们可以获取文档数据。首先我们获得数据之间的 <decimal></decimal>标记。要做到这一点,我们首先检索XML数据字段信息,通过调用getElementsByTagName(elementName)(第8行),这个函数返回的子节点数组的元素(父节点)与给定的标记。我们得到的子节点数组后,我们可以引用第一个元素的子节点通过调用firstChild。然后我们通过引用数据字段获得子节点的值。所以,总之,我们从dec[0].firstChild.data获取十进制值。
获取XML的十进制值后,第10行的代码更新十进制表单元素。我们现在从XML检索一个值并显示在页面上。我们以这种方式继续,直到我们所有的更新数据字段的值从servlet发送到的XML DOM检索完毕。
function nonMSPopulate( ) {
var resp = req.responseText;
var parser = new DOMParser( );
var dom = parser.parseFromString(resp,"text/xml");
decVal = dom.getElementsByTagName("decimal");
var decimal = document.getElementById('decimal');
decimal.value=decVal[0].childNodes[0].nodeValue;
hexVal = dom.getElementsByTagName("hexadecimal");
var hexadecimal = document.getElementById('hexadecimal');
hexadecimal.value=hexVal[0].childNodes[0].nodeValue;
octVal = dom.getElementsByTagName("octal");
var octal = document.getElementById('octal');
octal.value=octVal[0].childNodes[0].nodeValue;
hyperVal = dom.getElementsByTagName("hyper");
var hyper = document.getElementById('hyper');
hyper.value=hyperVal[0].childNodes[0].nodeValue;
binaryVal = dom.getElementsByTagName("binary");
var bin = document.getElementById('bin');
bin.value=binaryVal[0].childNodes[0].nodeValue;
}
我们创建一个新的DOMParser(第3行),然后在第4行创建一个DOM从servlet获取到的XML字符串。接下来,我们通过调用dom.getElementByTagName("decimal")获取<decimal></decimal>标记(第6行)之间的数据。之后从我们的HTML文档检索十进制表单元素,我们将检索的值以XML的形式发送给我们并且用它来设置适当的字段
使用decVal[0]获取<decimal></decimal>标记之间的数据。如果我们有两个<decimal></decimal>标签,我们会参考第二个标签设置decVal[1]。
这些数据就是从servlet发送的响应:
<converted-values>
<decimal>97</decimal>
<hexadecimal>0x61</hexadecimal>
<octal>0141</octal>
<hyper>&0x61;</hyper>
<binary>1100001B</binary>
</converted-values>