XML无处不在——DB2 9给予你掌握它的力量
上一篇 / 下一篇 2008-02-21 14:52:35 / 个人分类:XML
前言
XML不是新概念了。感谢诸如Ajax这样的新技术,使得它在过去的一些年里发展迅速。但是奇怪的是,到目前为止,数据库却拥有非常少的本地XML特性。
IBM最新的数据库,IBM DB2 9,引入了pureXML,一个解决使用XML进行工作的压力的本地XML特性集合。从新的XML数据类型到XQuery语言,DB2 9使得XML开发变得更加容易。
数据并不会像DBA所想的那样,整齐划一的被整理好,并且像邮箱里的备忘一样标记好。有些时候你遇到了古怪的难以分类的包。必须创建一个特殊域“备注”或“注释”或“杂项”。它们通常是CLOB域,并须足够的长,以容纳可能放进该域的任何文字。
你可以在下面的走查中看到一个例子——一些信息足够标准来波癌症自身的数据栏,而其他信息对每一行都是特别的。这里就不得不提XML数据域的好处了。
CLOB域能容纳任何东西——文字,XML,HTML,自定义描述符。但是对数据库来说,它只是文字。这使得搜索,解析和格式化,以及获取CLOB域中的子数据都比较困难。
然而,XML域将数据作为XML看待,而不是具有括号的数字。那么,你存储在XML域中的数据就是高效可用的了。这就像你在数据表中有一个小的数据表。XML数据可以使用SQL,XMLSQL,XQuery和它们任意的结合来进行搜索。你可以获取特定的数据节点而不是围绕的相关文字或者不相关文字。你甚至可以将它和XML文档关联起来,这种文档每一行都是不同的,使用XSD或者DTD来进行格式化。
这里对你最重要的是,XML数据类型和Ajax以及其他任何可以直接和XML工作的程序一起配合工作。简单的说,它使得令人头痛的基于XML的程序开发变得简单。
本文将逐步教会你如何使用这一高级特性。你首先需要下载免费分发的DB2 9 Express-C。安装它和最新的DB2 9Visual Studio插件,使用它们来创建一个新的Superhero数据库。在引入范例数据包括一些预写入的XML文档以后,你将在VS2005中创建C# Web服务来展示XML数据类型的优势。最后,你将使用预先写好的代码来创建HTML,JavaScript和CSS。在结束前,你将创建一个可以工作的程序,显示当前的hero花名册,在点击一个Hero时触发异步JavaScript调用Web服务,直接从XML域中获取数据,动态生成新的DOM对象。
这里的技术包括:
- DB2 Express-C
- ASP.NET 2.0 (C#)
- Web 服务
- JavaScript以及Ajax技术
- 用来整理页面显示的CSS
安装DB2 9 Express-C
第一步是安装和配置DB2 9 Express-C。当你下载它之后,选择”DB2 Express”下的“Install New”。当给出选项时,选择一个自定义的安装类型。当选择安装什么特性时,注意选择包含在“Client Support”下的“XML Extender”。如图1所示。

当你完成安装以后,你会看到一个选项来继续安装VS2005的DB2插件。如图2所示。选择它。如果你不小心错过了,那么必须重新安装“DB2 Client”或者“IBM Database add-ins for Visual Studio 2005”。

安装之后,进行第一步。Start -> IBM DB2 -> DB2 (or the name you specified for this copy of DB2) -> Set-up Tools -> First Steps。如果只是这次范例,无须安装SAMPLE数据库,除非你想测试你的安装。在这种情况下,选择“Create your own database”,如图3所示。下面将介绍如何创建数据库和所需的表,以及引入范例数据。

将数据库命名为“AJAXDEMO”。选择“Enable database for XML”。根据你的创建情况,你可以看到如图4中的选项。

当你创建了数据库以后,关闭前一步,打开Visual Studio。下面可以测试你的新插件了。
引入AJAXDEMO数据库
你将创建两个表,一个有XML域,一个没有。你可以通过各种方式来操作,如通过控制中心。但是为了展示的目的,打开VS2005,创建一个新的ASP.NET站点“Superpals”,如图5和6.将“Visual C#”作为开发语言。


为了测试你的新Web易用,在Default.aspx的<div>标记中间键入一些文字并运行。当一切正常,结束运行返回IDE。在工具菜单下寻找“IBM DB2 Tools”。图7.你可以通过这个菜单来访问你的DB2 产品,就像你打开开始菜单一样。选择工具-> IBM DB2 Tools->命令编辑器来打开查询窗口。

拷贝List1 中的代码到查询窗口。
| CONNECT TO AJAXDEMO; ------------------------------------------------ -- DDL Statements for table "NULLID "."HEROES_NOXML" ------------------------------------------------ CREATE TABLE "NULLID "."HEROES_NOXML" ( "HEROID" INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY ( START WITH +1 INCREMENT BY +1 MINVALUE +1 MAXVALUE +2147483647 NO CYCLE NO CACHE NO ORDER ) , "HERONAME" VARCHAR(50) NOT NULL , "POWER" VARCHAR(255) , "WEAKNESS" VARCHAR(255) , "NOTES" CLOB(1048576) LOGGED NOT COMPACT ) IN "USERSPACE1" ; -- DDL Statements for primary key on Table "NULLID "."HEROES_NOXML" ALTER TABLE "NULLID "."HEROES_NOXML" ADD CONSTRAINT "CC1158547603783" PRIMARY KEY ("HEROID"); ------------------------------------------------ -- DDL Statements for table "NULLID "."HEROES_XML" ------------------------------------------------ CREATE TABLE "NULLID "."HEROES_XML" ( "HEROID" INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY ( START WITH +1 INCREMENT BY +1 MINVALUE +1 MAXVALUE +2147483647 NO CYCLE NO CACHE NO ORDER ) , "HERONAME" VARCHAR(50) NOT NULL , "NOTES" XML ) IN "USERSPACE1" ; -- DDL Statements for primary key on Table "NULLID "."HEROES_XML" ALTER TABLE "NULLID "."HEROES_XML" ADD CONSTRAINT "CC1158547736768" PRIMARY KEY ("HEROID"); COMMIT WORK; CONNECT RESET; TERMINATE; This creates the following two tables: HEROES_NOXML: HEROID, INTEGER (4), IDENTITY, NOT NULLABLE HERONAME, VARCHAR (50), NOT NULLABLE POWER, VARCHAR (255), NULLABLE WEAKNESS, VARCHAR (255), NULLABLE NOTES, CLOB, NULLABLE HEROES_XML: HEROID, INTEGER (4), IDENTITY, NOT NULLABLE HERONAME, VARCHAR (50), NOT NULLABLE NOTES, XML, NULLABLE Populate the first table by copying the SQL code from Listing 2 into your Command Editor. Listing 2: HEROES_NOXML Data INSERT INTO NULLID.HEROES_NOXML (HERONAME, POWER, NOTES) VALUES ('Mockingbird','Can mimic any sound she hears.','Alter ego: Mariah Carey'); INSERT INTO NULLID.HEROES_NOXML (HERONAME, POWER, WEAKNESS, NOTES) VALUES ('Indigo','Telepathy','Gets cranky if he stays up too late.','Current age: 8. Additional weakness: lactose intolerant.'); INSERT INTO NULLID.HEROES_NOXML (HERONAME, POWER, WEAKNESS, NOTES) VALUES ('Indivisibull','Super strength; can reattach severed body parts.','Not too bright.','Secret origin: a somewhat clumsy man, Hank "Bullhead" Durham fell into a vat of fresh glue and was promptly struck by lightning. Since then, whenever he loses a limb, he has simply to hold it in place and the limb becomes reattached.'); INSERT INTO NULLID.HEROES_NOXML (HERONAME, POWER, WEAKNESS, NOTES) VALUES ('Dayglo','Glows under a black light.','Not having a black light around.','Usually relegated to sidekick, though once played a crucial role in a mission busting an underground pot growers cabal.'); INSERT INTO NULLID.HEROES_NOXML (HERONAME, POWER, WEAKNESS, NOTES) VALUES ('Thumbalina','Ability to text message at light speed.','Thumbsucking (a nervous habit in times of great stress).','Former codename: Twiddle.'); |
下面我们学习如何在VS2005中使用DB2 9插件来创建一个web服务,和异步的JavaScript交互。
创建一个Web服务
你有几个选项来创建一个基于DB2连接的Web服务。新的插件给你一些非常好的工具来加速开发。
在VS中,创建一个到新数据库的连接。选择Tools->Connect to Database和IBM DB2,它作为安装VS 插件时的一个选项。如图8。

当增加新连接时,你可以看到如下选项:
- 选择或者键入服务器名:你可以在这里有一选项。
- 输入服务器上的信息:这可以是你在安装Express-C时指定的User ID和密码。
- 选择或者输入一个数据库名称:默认选择AJAXDEMO,如果你只是创建了唯一这个数据库,否则从下拉菜单中选择。
你可以忽略其他选项和高级属性列表。选择“Test Connection”来保证你的User ID/Password选择框是正确的,并且可以连接到表。如图9.

如果你展开新的连接和其中的一个表,你可以看到通过Visual Studio来成功的连接新的数据库,访问你的数据。右键点击Data Connections,你可以看到从IDE中,你能增加新的连接和创建新的IBM数据库。
你可能在考虑,使得,你已经创建了数据库和表,输入数据,通过你的数据连接,使用DB2 9插件。现在你知道了。但是上下文菜单更加有趣。
右键点击“HEROES_NOXML”。在诸多选项中,你可以看到两个和Web服务关联的项:“Deploy IBM Web Service”和“Generate Web Methods”(图10)。选择“Generate Web Methods”,在“Identify Database Enabled for Web Services”对话框,输入你创建数据库连接的下拉选项的服务器名,以及数据库名“AJAXDEMO”和你以前使用的用户名/密码。

在“IBM Web Service”向导中,输入“HeroData”作为Web服务名。剩下的域将会自动填写。当你创建服务的时候,DB2插件将会自动生成连接数据库的代码,并从指定的表中获取数值。你的代码有点类同List 1中的部分。注意使用IBM.Data.DB2命名空间代替System.Data.SQL。
| using System; using System.Data; using System.Web.Services; using System.Web.Services.Protocols; using System.Web; using IBM.Data.DB2; using System.Data.Common; [WebService()] [WebServiceBinding()] public class HeroData { [WebMethod()] public virtual DataSet select() { IBM.Data.DB2.DB2Connection db2Connection1 = new IBM.Data.DB2.DB2Connection(); IBM.Data.DB2.DB2DataAdapter db2DataAdapter1 = new IBM.Data.DB2.DB2DataAdapter(); IBM.Data.DB2.DB2Command db2SelectCommand1 = new IBM.Data.DB2.DB2Command(); db2Connection1.ConnectionString = "database=AJAXDEMO;user id=db2admin;server=DELL:db2c_DB2;password=changeme"; db2DataAdapter1.SelectCommand = db2SelectCommand1; db2DataAdapter1.SelectCommand.CommandType = CommandType.Text; db2DataAdapter1.SelectCommand.CommandText =@"select * from NULLID.HEROES_NOXML"; db2DataAdapter1.SelectCommand.Connection = db2Connection1; System.Data.DataSet ds = new System.Data.DataSet(); try { db2DataAdapter1.Fill(ds); } catch (DB2Exception ex) { throw ex; } finally { db2Connection1.Close(); } return ds; } } |
为了测试Web服务,编译和运行HeroData.asmx,点击“select”和“Invoke”。你可以看到一些类似图3的代码。
在Visual Studio中,经过粗略估计你大概有2079种不同的方式来连接你的数据。插件将会返回一个DataSet,如List1中所示。一般来说这就够了,特别是使用非XML数据类型。
但是当你看这个例子的时候,你有很多Ajax程序不需要的描述信息。这个特殊结果集在你用于DOM前需要一些JavaScript解析。为了便于使用,它最好是返回一个XmlDataDocument而不是一个DataSet。所以需要改变一些WebMethod代码:
- 改变方法名为“GetNoXML()”。改变名称将会出发一个工具提示下拉框允许你改变全局的名称,你应该抓住这个机会。
- 在方法声明中,将“public virtual DataSet getNoXML()”中的“DataSet”为“XmlDataDocument”。
- 在方法最后,将“return ds;”删除或者注释掉,加上如下代码:
| XmlDataDocument xd = new XmlDataDocument(ds); return xd; |
这就是转变你的DataSet到XML数据的简单方法。编译,测试,结果将如图11所示——更加简短,更加易于Ajax使用。

问题,为什么不工作?
目前一切正常。你建立了你的数据库和数据,和获取结果的Web服务。目前你所需要的就是HTML和JavaScript(和CSS)。在你进入到Ajax部分之前,还有一些问题。
检查一下域和域的内容。大多数域,你可以为数据,栏名和数据本身标识一个标记。但是大部分数据不能符合一般的域。传统的,当获取非结构化数据时,你的数据包需要一个catch-all域来放置任何不能清晰解析的数据。对此可能有一些不同的原因:
- 数据从多个非标准源而来,每个数据都有各自的栏名和域类型;
- 你有很多潜在的名称/值 对来包含它们在你的数据结构中,将会需要一个不合理的打表或者非常复杂的数据库结构。
你有处理这些内容的多种方法,每种方法都有问题。比如,你可以:
- 使用HTML格式将数据存储在CLOB中。问题:HTML数据引入了对所需要的自定义工作区比如UI和数据更新的限制。预格式化的数据对其它应用程序变得更加不可用。
- 使用一个不同的标记,比如对你的JavaScript代码更加有用的JSON。问题:数据仍然对其它应用不可用。对于人来说阅读和更新也变得更加困难,在引入其它源的时候需要自定义的转化代码。
- 将数据存储为文本。问题:在显示你的Web应用时去除任何自定义的格式化选项。
在这个特殊的例子中,大多数数据点,比如“POWER”和“WEAKNESS”,有它们自己的栏。这些栏设置有些时候是null。剩下的数据导入到Notes域,排除了其他类型的格式,对其它应用也是没有太大用处。
使用XML数据类型
你可能看到了最优方法是存储非标准数据为一个XML数据。使用DB2 9的XML数据类型,你可以得到如下好处:
- 你可以使用标准的XML格式存储自定义数据
- 你将一个XSD或者DTD文档和XML栏关联以便让每行存储数据在相同的XML结构中,这其实没有必要。每一行可以有一个完全独立的XML文档和结构。
- XML数据对其它应用程序有用
- XML文档能够使用DB2 的XQuery来搜索
- XML文档可以使用一系列的混合语言搜索——XQuery,SQLXML和SQL。同样的,你可以轻松的混合数据类型,同时查询关系型数据和XML数据。如何混合使用XQuery和SQL,请查看http://www.research.ibm.com/journal/sj/452/ozcan.html
如果你回到上文,查看你早先建立的两个范例表,你将会注意到只有三个域的“XML”版本。这是因为最常用的域将会包含在独立的XML文档中。这是引入这些文档和查看数据类型的好机会。
XML域不能被当场编辑,但是可以作为完整的文档增加和更新。可能最简单的方法是通过IMPORT方法,在http://www.devx.com/ibm/Article/31499文中有详细叙述。为List2-6中的XML数据创建5个独立的XML文件。将这些都保存在一个新目录“C:\PALS”下。
Listing 2: hero1.xml
| <HERO> <NOTE title="Power">Can mimic any sound she hears.</NOTE> <NOTE title="Alter ego">Mariah Carey</NOTE> </HERO> Listing 3: hero2.xml <HERO> <NOTE title="Power">Telepathy</NOTE> <NOTE title="Weakness">Gets cranky if he stays up too late.</NOTE> <NOTE title="Current age">8</NOTE> <NOTE title="Additional weakness">Lactose intolerant.</NOTE> </HERO> Listing 4: hero3.xml <HERO> <NOTE title="Power">Super strength; can reattach severed body parts.</NOTE> <NOTE title="Weakness">Not too bright.</NOTE> <NOTE title="Secret Origin">A somewhat clumsy man, Hank "Bullhead" Durham fell into a vat of fresh glue and was promptly struck by lightning. Since then, whenever he loses a part of his body, he has simply to hold it in place and it becomes reattached.</NOTE> </HERO> Listing 5: hero4.xml <HERO> <NOTE title="Power">Glows under a black light.</NOTE> <NOTE title="Weakness">Not having a black light around.</NOTE> <NOTE title="Note">Usually relegated to sidekick, though once played a crucial role in a mission busting an underground pot growers cabal.</NOTE> </HERO> Listing 6: hero5.xml <HERO> <NOTE title="Power">Ability to text message at light speed.</NOTE> <NOTE title="Weakness">Thumbsucking (a nervous habit in times of great stress).</NOTE> <NOTE title="Former Codename">Twiddle</NOTE> </HERO> |
下面将List7 保存在相同的目录下的heroes.del。这个文件的格式非常简单——特别是一个逗号分割的列表,XDS标记指定了它的源文件。在这个例子中,HeroID域被留空了,因为它是自动申城的标识栏,因此你只有其它的域。
Listing 7: heroes.del
| Mockingbird,<XDS FIL='hero1.xml' /> Indigo,<XDS FIL='hero2.xml' /> Indivisibull,<XDS FIL='hero3.xml' /> Dayglo,<XDS FIL='hero4.xml' /> Thumbalina,<XDS FIL='hero5.xml' /> |
为了建立你的表,打开命令行编辑器窗口,保证你能够连接AJAXDEMO数据库。将List8拷贝到窗口中执行。
Listing 8: insert.sql
| IMPORT FROM 'C:\PALS\heroes.del' OF DEL XML FROM 'C:\PALS' MODIFIED BY IDENTITYMISSING INSERT INTO NULLID.HEROES_XML |
你可以看到消息以“Number of rows committed =5”结尾。如果这样的话,那么你已经成功的引入了HEROES_XML表。为了确认,打开表。在Notes栏,你将看到省略号,如图12所示。

点击其中一个省略号来打开XML文档查看器,将会使用树状视图或者源文件视图显示XML文档。如图13.

注意XML文档的结构已经被故意的选择为最小化当前行的XML节点数目,但是你仍然可以在所需时建立它。这里我决定包含数据名作为节点的“标记”属性,将数据值作为节点值。你可以在下一段中看到JavaScript如何直接操作这一格式。实现这一个解决方案需要一些标准化,你需要从多个数据源中搜集数据。在现在的互联网中,你的源可以通过多种方式标准化。如果你从一个持续格式中引入多个流,比如RSS源,你可以写JavaScript来轻松完成这一个格式。XML数据了型提供了进行这种聚合的最佳资源。
创建一个新的改进过的Web服务
回到HeroData.cs文件。为了方便,将连接字符串从getNoXML()方法中取出,赋予一个类级别的私有变量,如:
private String connString = "…";
自己手动填加List9中的代码,而非通过插件产生以下代码:
Listing 9: getWithXML Webmethod
| [WebMethod()] public virtual XmlDocument getWithXML(int heroID) { DB2Connection conn = new DB2Connection(); conn.ConnectionString = connString; conn.Open(); DB2Command cmd = conn.CreateCommand(); XmlDocument heroXml = new XmlDocument(); String sel = @"select XMLELEMENT (NAME ""HERODATA"", XMLELEMENT (NAME ""HeroName"", HERONAME), XMLELEMENT (NAME ""Notes"", NOTES)) from NULLID.HEROES_XML where HEROID = " + heroID.ToString() + ";"; cmd.CommandText = sel; XmlReader xr = cmd.ExecuteXmlReader(); try { heroXml.Load(xr); } catch (DB2Exception ex) { throw ex; } finally { conn.Close(); } return heroXml; } |
在代码声明段,增加如下:
using System.Xml;
一些关于该方法的注解:
- 就像我提到的,你有一些荒谬的方法来获取数据。你注意到这个特别的技术因为它更加的短。它不包含任何DB2DataAdapter值,而是直接将值独到XmlReader值中。这将更容易的使用XmlDocument.Load()方法来转换为XmlDocument。
- 这里,返回类型是XmlDocument而不是XmlDataDocument,结果是一样的,你将在后面看到它们可以被JavaScript通过responseXML访问。
- 注意被选择的语句,你将看到新的命令:XMLELEMENT。它和其它的XML相关的SQL命令帮助你从SQL语句中格式化你的结果为XML。这里,你创建了一个HERODATA节点,然后使用“HeroName”和XML栏“Notes”来导出。这样的方式使得你可以混合数据类型,快速放回一个持久的高可访问的结果集。
编译和测试HeroData.asmx。你触发你的新getWithXML方法时,将会看到“heroID”域,方法参数。如果你能够一次插入5行到HEROES_XML表中,它将自动的生成HeroID值从1到5。结果如图14所示。

创建HTML页面和一个重复器控制
下面创建一个基本的Web页面。当你开始时,VS已经创建了一个默认的Default.aspx供你使用。打开并加入List 11的代码。
Listing 11: Default.aspx
| <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> <!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 runat="server"> <title>DB2 AJAX Sample</title> </head> <body> <form. id="form1" runat="server"> <div id="heroList"> </div> <div id="notes">Choose a Hero</div> </form> </body> </html> |
第二个<div>标记, “notes”将会自动的在你写下一段的时候引入。它将会存放从Web服务中获取的XML。为了选择特定的行,你需要选择表中的一个ID。最简单的方法是使用Repeater Web对象。
- 切换到设计视图,拖曳Repeater控件到“heroList”<div>标记中。你可以在Toolbox里的Data块的标记中找到它。
- 从Repeater标记中选择一个数据源,你可以从下拉菜单中选择,如图15.

- 选择“Database”作为你的数据源类型。
- 当选择数据连接时,你可能只有一个选项,选择它,如图16.

- 这是你第一次访问这个数据连接,你可以得到一个保存连接到配置文件的提示,你可以选择接受。图17。接受给出的缺省名称“AJAXDEMOConnectionString”。

- 配置Select语句,如图18所示,从下拉框中选择“HEROES_XML”表,选择HEROID和HERONAME域。不要选择NOTES域。这里是直接的表导出而无须WHERE语句。可以使用一个ORDER BY语句来改变表的顺序。底部SELECT语句将会自己写上。

- 在下一页你将可以测试查询,保证你能够正确连上数据库。你可以从表19中看到结果集。

- 最后异步,通过选择HERONAME配置Repeater表,显示控件,HEROID为控件的值。图13。

- 切换回代码视图,你可以看到新的控件。你可以剪切和粘贴它到你的<div>标记。现在,将不会显示任何东西,所以你需要键入一些模板。在<asp:Repeater>控件中,加入HeaderTemplate代码。加入如下的代码:
| <HeaderTemplate> <h3>Available Roster:</h3> <ul class="HeroList"> </HeaderTemplate> |
- 下面,增加ItemTemplate。这将包括一个onclick事件来调用一个JavaScript函数,并且将被选的值的HeroID传递给它。我增加了一些函数如处理onmouseover和onmouseout事件。使用DataBinder对象来获取数据值。
| <ItemTemplate> <li class="heroItem" onclick="getHeroInfo(<%# DataBinder.Eval(Container.DataItem, "HeroID")%>)" onmouseover="this.className='heroItem_hl';" onmouseout="this.className='heroItem';"> <%# DataBinder.Eval(Container.DataItem, "HeroName")%> </li> </ItemTemplate> |
- 最后,增加FooterTemplate来关闭未排序的list。
| <FooterTemplate> </ul> </FooterTemplate> |
这样就完成了Repeater控件。你可以测试它来连接数据库获取数据。但是注意这里调用JavaScript会引发一个错误,我们将会在下一节中解决这个问题。
JavaScript. Ajax A-Go-Go
如果你曾经写过Ajax代码,那么这里就不耽误时间了。拷贝如下代码增加到<head>标记中。或者你可以将它作为一个独立的.js文件并且在Default.aspx中引用它。
Listing 12: JavaScript. Code for Accessing DB2 Web Services
| <script. language="javascript" type="text/javascript"> var request; function createRequest() { try { request = new XMLHttpRequest(); } catch (tryms) { try { request = new ActiveXObject("Msxml2.XMLHTTP"); } catch (otherms) { try { request = new ActiveXObject("Microsoft.XMLHTTP"); } catch (failed) { request = null; } } } if (request == null) alert("Error implementing Ajax functionality"); } function getHeroInfo(heroID) { createRequest(); var url = "http://localhost/Superpals/HeroData.asmx/getWithXML"; request.open("POST", url, true); request.onreadystatechange = showHeroInfo; request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); request.send("heroID=" + heroID); } function showHeroInfo() { if (request.readyState == 4) { if (request.status == 200) { var xmlDoc = request.responseXML.documentElement; var notesList = xmlDoc.getElementsByTagName("HERO")[0].getElementsByTagName("NOTE"); var len = notesList.length; var notesDiv = document.getElementById("notes"); //Clear Notes Span tag while (notesDiv.firstChild) { notesDiv.removeChild(notesDiv.firstChild); } var newSpan, newText; for (var n = 0; n<len; n++) { var newSpan = document.createElement("h3"); newSpan.className = "noteTitle"; var newTextVal = notesList[n].getAttributeNode("title").nodeValue + ": "; var newText = document.createTextNode(newTextVal)newSpan.appendChild(newText); notesDiv.appendChild(newSpan); var newSpan = document.createElement("p"); newSpan.className = "noteValue"; var newTextVal = notesList[n].firstChild.nodeValue; var newText = document.createTextNode(newTextVal)newSpan.appendChild(newText); notesDiv.appendChild(newSpan); } } else { var stat = request.getResponseHeader("Status"); alert(request.status + " | " + stat); } } } </script> |
它做了什么:
- “var request;”:全局声明的请求对象,在多个函数中被使用;
- “function createRequest()”:特定浏览器的XMLHttp初始化。(这个程序在微软IE和Firefox中运行)
- “function getHeroInfo(heroID)”:这是Repeater控件的onclick事件调用的函数。它形成一个向你早先创建的Web服务的请求,特别是HeroData的“getWithXML”。它然后通过POST提交HeroID,发送请求到showHeroInfo来处理。
- “function showHeroInfo()”:程序的主要代码。如果你已经使用了第一个Web服务,根据表而不是一个XML数据类型,那么函数将更加的长,更加的复杂。
当你有比产生一个XML结果集更少的选项来处理它时,你仍然有选择去处理。根据期望的XML结构,我选择了“NOTE”节点来遍历它的子节点。注意一下范例XML结果集:
| var notesList = xmlDoc.getElementsByTagName("HERO")[0].getElementsByTagName("NOTE"); |
正确的解析结果是Ajax程序的业务核心。这里DB2 9使用XML数据类型和查询语言简化了一堆过程使得你能够用极精简的代码来获取想要的数据并且传递给DOM。
在指定相关的XML数据后,代码已经比较清晰和明确了。在基于XML数据创建新的文档节点时,你仍然有一些选择。通过将重要的但是无关联的数据放置在一个XML域中,并且通过指定标题来结构化它,你能够遍历子节点,创建头部和主题而无须多余的异常处理。现在使用“getAttributeNode”来访问“title”属性。
在这里,我简单的使用了<h3>和<p>节点,可以被分开样式化。没有必要解析Notes域。没有必要增加单独的域处理。显然你能够使用不同的标记,如<div>或者<span>甚至是<ul>和<li>标记。
对于格式,增加如下一些代码到你的<head>标记来让页面更加整洁:
Listing 13: Styles
| <style. type="text/css"> ul {font-family:Arial; font-size:.9em; } li { list-style.:none; font-family:Arial; } h3 { font-family:Arial; font-size:1.3em} p { font-family:Arial; font-weight:normal; font-size:.9em} #notes { float:right; border-width:1px; border-style.:solid; width:50%; padding:20px 20px 20px 20px;} #heroList { font-family:Arial; float:left; width:30%; padding:20px 20px 20px 20px;} .heroItem_hl { font-weight:bold; background-color:azure; } .heroItem { font-weight:normal; background-color:white; } </style> |
放到一起
你的完整的Default.aspx页面如图14所示。

由于服务器端程序已经完成,现在可以浏览Default.aspx来检查结果了。
“Available Roster”可以直接从DB2 9数据源中获取数据。选择任何一个,右边将会通过一个C#Web服务调用显示你的XML域内容。每个英雄都有各自的属性,你可以使用一些处理方式来优化显示。
这就是你可以用到的DB2 9的新的XML功能特性。但是不仅仅是这一个。XML无处不在——DB2 9给予你掌握它的力量。
导入论坛 引用链接 收藏 分享给好友 推荐到圈子 管理 举报
TAG: