在请求和响应中使用XML

日期: 2008-07-13 作者:Brett McLaughlin 来源:TechTarget中国

  偶尔使用Ajax的开发人员也会注意到Ajax中的x并意识到它代表XML。XML是编程中最常用的数据格式之一,对于异步应用程序中的服务器响应能够带来切实的好处。在本文中,您将看到服务器如何在请求响应中发送XML。


  现在如果不使用XML就不能进行任何有意义的编程。无论考虑转向XHTML的网页设计人员、使用JavaScript的Web程序员、使用部署描述文件和数据绑定的服务器端程序员,还是研究基于XML的数据库的后端开发人员,都在使用这种可扩展标记语言。因此,XML被认为是Ajax底层的核心技术之一就不足为奇了。


  但是,这种观点反映到Ajax应用程序就表现在其核心对象所选的名称——XMLHttpRequest,这个名称不是很好,因为它并没有反映技术上的实际情况。换句话说,多数人之所以认为XML是Ajax的核心组成部分,仅仅是因为他们想当然地以为XMLHttpRequest对象在任何时候都使用XML。但实情并非如此,本文第一部分给出了原因。实际上,您将看到在多数Ajax应用程序中XML很少出现。


  XML确实有应用在Ajax中,而且XMLHttpRequest也支持这种用法。也确实没有什么能阻挡您向服务器发送XML。在本系列前面的文章中,我们使用普通文本和名/值参数发送数据,但XML也是一种可行的格式。本文将介绍如何来这样做。但最重要的是,我将讨论为何可以使用XML作为请求格式,以及为何在多数情况下不应该使用它。


  XML:到底用没用?


  对Ajax应用程序及它们使用XML的情况很容易犯想当然的错误:这种技术的名称(Ajax)及其使用的核心对象(XMLHttpRequest)都暗示了XML的使用,谈到Ajax应用程序的时候也经常听到XML。但是,这种观点大错特错,如果希望在编写异步应用程序时真正做到胸有成竹,必须知道这种想法是错误的,而且最好知道为什么错误。


  XMLHttpRequest:糟糕的名称和HTTP


  一项技术可能遇到的最糟的境况之一是它变得太炙手可热以至于无法再改变它的一些基本内容。XMLHttpRequest恰恰是这种情形,它是Ajax应用程序中使用的基本对象。听起来它似乎是为通过HTTP请求发送XML或者以某种XML格式发出HTTP请求而设计的。但不论这个对象的名称听起来像什么,实际上它要做的只不过是为客户机代码(在网页中通常是JavaScript)提供一种发送HTTP请求的方式。仅此而已,别无其他。


  因此,如果将XMLHttpRequest改成某种更准确的名称可能更好一些,比如HttpRequest,或者简简单单的Request。但是,现在成千上万的人在应用程序中使用了Ajax,而且我们知道需要几年时间(如果不是十几年的话)大部分用户才会改用Internet Explorer 7.0或Firefox 1.5这些新版本的浏览器,因此这么修改实际上是不可行的。最终我们不得不使用XMLHttpRequest,这就要求开发人员要知道其名不符实的这一事实。


  在一定程度上讲,对于不支持XMLHttpRequest的浏览器(特别是在Windows上)的最佳回溯方法之一就是使用Microsoft IFRAME对象。听起来可不像是XML、HTTP或请求,是不是?当然,所有这些都可能涉及到,但是这正清楚地说明了一点——XMLHttpRequest对象更多的是关于在不重新加载页面的情况发出请求,而不会太多地涉及XML甚至HTTP。


  请求是HTTP而非XML


  另一种常见的错误是认为XML在幕后使用——坦白地说,我也曾这么认为!但是,持这种观点表明您对这种技术还不甚了解。当用户打开浏览器从服务器上请求网页时,会输入http://www.google.com或者http://www.headfirstlabs.com这样的东西。即便不输入http://,浏览器也会在地址栏的这部分加上。第一部分,即http://,是关于如何通信的很直观的线索:通过超文本传输协议HTTP。在网页中编写代码与服务器通信时,无论使用Ajax还是普通的表单POST,甚至超链接,打交道的都是HTTP。


  既然浏览器和服务器之间的所有Web通信都通过HTTP进行,认为XML是XMLHttpRequest幕后所用的某种传输技术的想法就毫无道理了。当然在HTTP请求中可以发送XML,但是HTTP是一个精确定义的协议,短时间内不可能消失。除了在请求中明确使用XML,或者服务器用XML发送响应之外,XMLHttpRequest对象使用的只是普普通通的HTTP。因此,当再有人对您说 “哦,称为XMLHttpRequest是因为在幕后使用XML”的时候,您最好一笑了之,并耐心地解释什么是HTTP,告诉他们虽然XML可以通过HTTP发送,但XML是一种数据格式而不是传输协议。通过这样的讨论,加深对它的理解。


  使用XML(真正)


  到目前为止,我说的只是Ajax在哪些地方不使用XML。但Ajax中的x和XMLHttpRequest中的XML仍然有其实际意义,在Web应用程序中使用XML有多种选择。这一节将讨论基本的选择,剩下的部分再深入探讨细节问题。


  XML选项


  在异步应用程序中XML有两种基本的用法:


  ·以XML格式从网页向服务器发送请求
  ·以XML格式在网页中从服务器接收请求


  其中第一种用法,即用XML发送请求,需要将请求的格式设置为XML,可以使用API来完成,也可以与文本连成字符串,然后将结果发送到服务器。按照这种思路,主要的任务就是通过既符合XML规则又能被服务器理解的方式构造请求。因此这里的关键实际上是XML格式,得到需要发送的数据之后,只需要用XML语法将其包装起来。本文后面讨论XML在Ajax应用程序中的这种用法。


  第二种用法,即用XML接收请求,需要从服务器上接收响应,然后从XML提取数据(同样,可以用API或者采用蛮力方法)。这种情况下,关键在于来自服务器的数据,而您恰好需要从XML 中提取这些数据以便使用。这是本系列下一期文章的主题,到那时候我们再详加讨论。


  一点忠告


  再详细讨论使用XML的细节之前,首先给您一句忠告:XML不是一种简洁、快速和节省空间的格式。在后面几节以及本系列的下一期文章中将看到,在上下文中使用XML确实有一些很好的理由,XML与普通文本的请求和响应(特别是响应)相比也确实有一些长处。但是,和普通文本相比,XML通常总会占用更多的空间,速度也更慢,因为需要在消息中增加XML所需要的标签和语义。


  如果需要编写速度很快、看起来像桌面应用的程序,XML可能不是最佳选择。如果从普通文本开始,然后发现确实需要XML,那么就使用它;但是如果从一开始就使用XML,基本上可以肯定一定会降低应用程序的响应性。多数情况下,与将文本转化成下面这种XML相比,发送普通文本会更快一些(使用类似name=jennifer的名/值对):


  jennifer
 
  看看哪些地方使XML增加了处理时间:将文本包装成XML;发送额外信息(要注意我没有包含任何包围元素、XML头或者可能出现在实际请求中的其他任何内容);让服务器解析XML、生成响应、用XML包装响应,并将它发送回网页;让网页解析响应,最后使用它。因此要清楚什么时候使用XML,不要一开始就认为它在很多情况下都能够加快应用程序;但,它可以增强灵活性,这就是我们现在要讨论的。


  从客户机到服务器的XML


  我们来看看将XML作为从客户机向服务器发送数据的格式。我们首先讨论技术上的实现,然后花些时间分析什么时候适合什么时候不适合使用它。


  发送名/值对


  在您编写的90% Web应用程序中,最终都会使用名/值对发送到服务器。比方说,如果用户在网页表单中输入姓名和地址,可能希望数据采用下列形式:


  firstName=Larry
  lastName=Gullahorn
  street=9018 Heatherhorn Drive
  city=Rowlett
  state=Texas
  zipCode=75080
 
  如果使用普通文本把这些数据发送到服务器,可以使用清单1所示的代码。类似于本系列第一期文章中使用的那个例子。请参阅参考资料。


  清单1. 使用普通文本发送名/值对


  function callServer() {
    // Get the city and state from the Web form
    var firstName = document.getElementById(“firstName”).value;
    var lastName = document.getElementById(“lastName”).value;
    var street = document.getElementById(“street”).value;
    var city = document.getElementById(“city”).value;
    var state = document.getElementById(“state”).value;
    var zipCode = document.getElementById(“zipCode”).value;


    // Build the URL to connect to
    var url = “/scripts/saveAddress.php?firstName=” + escape(firstName) +
      “&lastName=” + escape(lastName) + “&street=” + escape(street) +
      “&city=” + escape(city) + “&state=” + escape(state) +
      “&zipCode=” + escape(zipCode);


    // Open a connection to the server
    xmlHttp.open(“GET”, url, true);


    // Set up a function for the server to run when it’s done
    xmlHttp.onreadystatechange = confirmupdate;


    // Send the request
    xmlHttp.send(null);
  }
 
  将名/值对转化成XML


  如果希望这样使用XML作为数据格式,首先要做的是找到一种基本XML格式来存储数据。显然,名/值对可以全部转化成XML元素,以其中的名称作为元素名,值作为元素的内容:


  Larry
  Gullahorn
  9018 Heatherhorn Drive
  Rowlett
  Texas
  75080
 
  当然,XML要求有一个根元素;如果使用文档片段(XML文档的一部分)的话则需要一个封闭元素。因此可能需要将上述XML转化成下面的形式:


  


    Larry
    Gullahorn
    9018 Heatherhorn Drive
    Rowlett
    Texas
    75080
  

 
  现在基本上可以准备在Web客户机上创建这种结构并发送到服务器了。


  通信,口头上的


  在网络上传输XML之前,需要保证服务器以及发送数据的脚本能够接受XML。现在对很多人来说这么强调似乎有点多余,认为这是理所当然的,但是很多新手往往认为只要通过网络发送XML,就能够被正确地接收和解释。


  实际上,需要两个步骤来保证发送的XML的数据能够被正确地接收:


  ·保证向其发送XML的脚本能够接受XML数据格式。
  ·保证脚本认可发送数据所采用的特定XML格式和结构。


  这两方面都可能要求您进行人际沟通,必须明确地告知对方!严格地说,如果确实需要发送XML数据,多数脚本作者都会帮助您,因此寻找能够接受XML的脚本应该不难。但是,仍然需要保证格式是脚本所希望的格式。比方说,假设服务器接受下列格式的数据:


  
    Larry
    Gullahorn
    9018 Heatherhorn Drive
    Rowlett
    Texas
    75080
  

 
  看起来和上面的XML类似,只有两点不同:


  ·来自客户机的XML封装在address元素,但是服务器要求数据封装在profile元素中。
  ·来自客户机的XML使用了zipCode元素,而服务器希望邮政编码放在zip-code元素中。


  从大的层面上来说,这些小问题仅仅是服务器接收和处理数据的区别,但是服务器会彻底失败,在网页上(可能向其用户)显示意义含糊的错误消息。因此必须明确服务器的期望的格式,并把要发送的数据塞进那种格式。然后,只有在这时才会涉及到从客户机向服务器发送XML数据的真正的技术问题。


  向服务器发送XML


  当向服务器发送XML的时候,更多的代码用于获取数据和包装成XML,而不是真正的传输数据。实际上,只要准备好发送到服务器的XML字符串,发送工作就和普通文本一样了,如清单2所示。


  清单2. 用XML发送名/值对


  function callServer() {
    // Get the city and state from the Web form
    var firstName = document.getElementById(“firstName”).value;
    var lastName = document.getElementById(“lastName”).value;
    var street = document.getElementById(“street”).value;
    var city = document.getElementById(“city”).value;
    var state = document.getElementById(“state”).value;
    var zipCode = document.getElementById(“zipCode”).value;


    var xmlString = “” +
      ”  ” + escape(firstName) + “” +
      ”  ” + escape(lastName) + “” +
      ”  ” + escape(street) + “” +
      ”  ” + escape(city) + “” +
      ”  ” + escape(state) + “” +
      ”  ” + escape(zipCode) + “” +
      “
“;


    // Build the URL to connect to
    var url = “/scripts/saveAddress.php”;
 
    // Open a connection to the server
    xmlHttp.open(“POST”, url, true);


    // Tell the server you’re sending it XML
    xmlHttp.setRequestHeader(“Content-Type”, “text/xml”);


    // Set up a function for the server to run when it’s done
    xmlHttp.onreadystatechange = confirmupdate;


    // Send the request
    xmlHttp.send(xmlString);
  }
 
  大部分代码都很简单,只有少数地方值得提一下。首先,请求中的数据必须手工格式化为XML。阅读了三篇关于使用文档对象类型的文章之后,再来讨论它是不是很简单了?虽然不禁止在JavaScript中使用DOM创建XML文档,但是在通过GET或POST请求发送到网络上之前必须将DOM对象转化成文本。因此使用常规字符串操作来格式化数据更简单一些。当然,这样很容易出现错误和误输入,因此在编写处理XML的代码时必须非常小心。


  建立XML之后,按照和发送文本基本相同的方式打开连接。对于XML最好使用POST请求,因为有些浏览器限制了GET请求字符串的长度,而 XML可能很长,可以看到清单2中把GET改成了POST方法。此外,XML通过send()方法发送,而不是附加在请求URL最后的参数。这些都是非常细微的区别,很容易修改。


  但是必须编写一行新的代码:


  xmlHttp.setRequestHeader(“Content-Type”, “text/xml”);
 
  看起来很难理解,它只不过是告诉服务器要发送的是XML而不是一般的名/值对。无论哪种情况,发送的数据都是文本,但这里使用text/xml或者XML作为普通文本发送。如果使用名/值对,对应的行应该是:


  xmlHttp.setRequestHeader(“Content-Type”, “text/plain”);
 
  如果忘记告诉服务器发送的是XML,就会出现问题,因此不要忘掉这一步骤。


  完成这些之后,剩下的就是调用send()并传入XML字符串了。服务器将收到您的XML请求,并(假设已经做好了准备工作)接受XML,解释它,然后返回响应。实际上要做的只有这么多——XML请求只需要稍微修改代码。


  发送XML:好还是不好?


  在结束XML响应的XML请求(以及本文)之前,我们花点时间讨论一下在请求中使用XML的感受。前面已经提到,就传输而言XML完全不是最快的方式,但是还有更多因素要考虑。


  构造XML不是简单的事情


  首先必须认识到,对于请求来说构造XML不是简单的事。如清单2所示,数据很快就会和XML语义纠缠在一起:


  var xmlString = “” +
    ”  ” + escape(firstName) + “” +
    ”  ” + escape(lastName) + “” +
    ”  ” + escape(street) + “” +
    ”  ” + escape(city) + “” +
    ”  ” + escape(state) + “” +
    ”  ” + escape(zipCode) + “” +
    “
“;
 
  似乎还不坏,但是要知道这是只有六个字段的XML片段。开发的多数Web表单都有十到十五个字段,虽然不一定所有的请求都使用Ajax,但是应该考虑这种情况。至少要花和实际数据同样多的时间来处理尖括号和标签名称,有可能使本来很少的输入变得非常大。


  这里的另一个问题前面已经提到,即必须手工创建XML。使用DOM不是一种好的选择,因为没有简单易行的办法将DOM对象转化成在请求中发送的字符串。因此像这样使用字符串处理是最好的办法,不过也是一种维护起来最困难和新开发人员最难理解的方法。在这个例子中,所有XML都在一行中构造完成,如果分为多步只会更加混乱。


  XML没有为请求增加任何东西


  除了复杂性的问题之外,和普通文本以及名/值对相比,在请求中使用XML实际上没有多少好处(如果有的话)。要注意,本文坚持使用前面用名/值对发送的同一些数据(请参阅清单1)来用XML发送。我没有提什么数据能用XML但是不能用普通文本发送,这是因为实际上没有任何东西可用XML而不能用普通文本发送。


  事实上这就是XML和请求的底线:不是一定非要这么做不可。在本系列的下一期文章中将看到服务器可以使用XML实现普通文本很难做到的一些事情,但请求不属于这种情况。因此除非和只接受XML的脚本(确实存在这样的脚本)打交道,在请求中最好使用普通文本。


  结束语


  通过本文,您现在可能已经开始对Ajax中的XML有一些更深的理解了。您知道Ajax应用程序不一定要使用XML,XML也不是数据传输中的什么法宝。还知道从网页向服务器发送XML不是多么难的事情。更重要的是,您知道为了确保服务器能够处理和响应请求需要做什么:必须保证服务器脚本接受XML,而且能够识别用于发送数据的格式。


  您还应该非常清楚XML对于请求来说并不一定是很好的数据格式。在以后的文章中,您将看到XML在某些情况下是有利的,但在多数请求中,它只会降低速度和增加复杂性。因此虽然通常我都会建议您马上应用在文章中学到的内容,但是对本文来说,我建议您在应用这里学到的知识时最好三思而后行。XML请求在Ajax应用程序中有自己的价值,但是并不像您所想象的那么大。


  在下一期文章中,我们将讨论服务器如何使用XML做出响应,以及Web应用程序如何处理这些响应。令人高兴的是,服务器能够将XML发送回Web应用程序,这样做的理由比较充分,因此那篇文章中的技术细节更实用,目前您只需要知道XML为何并非一定是最佳选择——至少对发送请求而言。您可以尝试使用XML作为请求数据格式实现某些Web应用程序,然后再换回普通文本,看看哪种办法更快更简单。下一期文章再见。

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

相关推荐

  • 八个超实用的jQuery技巧攻略

    jQuery是JavaScript最好的库之一,主要用于制作动画、事件处理,支持Ajax及HTML脚本客户端。文中分享了8个超实用的jQuery代码技巧攻略,希望你会喜欢。

  • BEST:SOAP/XML和REST的替代方案

    虽然拥有大量的机架服务器,以及大量软件开发人员的组织,基于web和集成服务的SOAP和REST很适合他们,但也会出现问题。

  • Spring 烂!差!

    有些人可能对Spring的第一印象不太好,它真的很烂,很差吗,也许这只是你的一种偏见,它也有是自己的优点的。

  • 基于SOA架构的业务安全性研究

    SOA在提供价值链上企业之间信息共享和业务流程自动化的同时,也给业务信息安全带来了负面影响,且存在安全隐患,这些你知道吗?