技术开发 频道

结合DB2 pureXML和XForms简化XML应用开发

【IT168 技术文档】

概述

    XML 技术是互联网下一个发展阶段的关键技术,它已成为互联网上表现结构化和半结构化数据的标准格式和数据交换的主要标准。在这种背景下,把 XML 作为一种数据库模型并从中提取信息在数据库领域逐渐受到注意。而且,XML 技术和关系数据库技术的融合能使数据更通用,能被异构系统接受,因此成为很自然的趋势。

简介

    谈到 Web 应用开发,对于开发者来说最关心的两个问题可能就是:如何有效的存储和管理表单数据以及如何能够方便快捷的开发表单。尤其是随着信息化建设的推进,传统的纸质表单、电子文档和基于 HTML 的表单正在成为开发效率的瓶颈。因为在很多应用领域,比如:金融、税务、医疗等行业,它们需要管理的表单可能有成百上千多个,而且这些表单本身都非常复杂,并且可能由于业务的需求会经常改动,这些无疑对传统的 HTML 表单提出了挑战。本文结合新一代 Web 表单技术——XForms 的诸多优势以及 DB2 V9.5 对 XML 数据存储和管理的支持,来阐述如何将两者无缝结合来简化 XML 应用开发。

    DB2 V9.5 的推出为 XML 应用开发提供了很好的数据存储和管理机制,并将这一在信息管理领域有着里程碑式意义的技术称为“DB2 pureXML”。在存储方面,pureXML 将 XML 进行高效的原生态存储;在应用访问方面,支持 SQL 和 XML 两种访问方式。不仅如此,所有关系型的操作方式和数据库工具都可用于 XML 之上,例如索引机制、导入导出、关联查询、高速批量加载、系统优化等等,你可以像管理关系数据一样管理 XML 数据。

什么是 XForms?

    有了强有力的 XML 数据管理基础,另外一个问题就是表单的开发问题了。今天,在 HTML 表单成为 HTML 标准的组成部分的十年后,网络用户所进行的复杂事务正在超越标准的 HTML 表单的能力极限,并且,并不是每一个人都是通过普通的个人电脑来访问表单的,他们更希望不管使用什么样的设备上网,表单都能够正常运行。W3C 的 XForms 给予创作者在改善用户体验时更大的能力和灵活性,W3C XForms 工作小组的主席 Steven Permberton 这样评价 XForms,“XForms 工作小组提供了一个模型使得实现者更容易开发和复用表单部件,将它们结合入 Web 服务,以及带给用户和设备以前不可能的功能性”。

    具体的讲,XForms 是 W3C 组织所推荐的下一代在线表单(早在 2003 年 10 月 14 日就被 W3C 推荐),它吸取了 W3C 标准诸如 :XML Schema, XPath和基于XML的事件,试图突破当前 HTML Forms 模型的一些限制。XForms 最大的特色就是将数据从表现中分离,这为表单在不同的设备上正常显示提供了保证,同时这使得应用开发具有更健壮的数据类型表示,并且能够递交 XML 数据到服务端(替代我们通常使用 name/value 递交的做法,这一优点可以在后面的例子中有所体现);XForms 的另外一个特色之处在于它包含了客户端验证的功能,我们知道,在 HTML 中,许多关于 Forms 验证的功能需要写大量的JavaScript脚本,由于验证的 JavaScript 脚本库依赖于 Forms 中的各个元素,当它们发生变化时,不得不重新更新或维护 JavaScript 验证脚本,XForms 结合了许多关于验证方面的功能,只需要使用简单的 XML 标记就能完成许多验证功能。XForms 的这些特点是不是已经让你感觉到它的强大优势了呢?

如何结合 XForms 开发 pureXML 应用

    下面就从 web 应用开发中的一个方面——表单数据的提交和访问来展示 XForms 如何与 DB2 pureXML 无缝结合来简化 XML 应用开发过程的。学习本文章的代码需要使用 FireFox 2.0,并安装 XForms 扩展插件。

    首先,创建一个 XForms 表单,该表单源自于税务领域的一个缴税明细表单,从浏览器里看到的表单样式图 1 所示:


图 1. XForms 表单示例

    可以看到,表单字段比较多,对于这种比较复杂的表单,如果利用传统的 HTML 表单来获得表单上的数据,我们需要做的是为每一个字段赋一个变量来接收相应的数据,这时,如果用来存储表单数据的是关系型的数据库表,那么我们还需要把得到的每一个字段的值一一存到相应的表列里。即使数据库采用 XML 存储方式,以省去维护诸多关系字段的麻烦,我们仍然需要在后台程序里将表单数据手动的拼装成一个 XML 实例,然后进行存储。可以想象,当表单极其复杂时,两种方式都会存在严重的效率问题。

    那么 XForms 是怎么解决这类问题的呢?下面的程序清单是相应的 XForms 表单片断:


清单 1. 相应的 XForms 表单片断

<?xml version="1.0" encoding="ASCII"?> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ev=“http://www.w3.org/2001/xmo-events” xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:FIXML="http://www.fixprotocol.org/FIXML-4-4"> <head> <title>Instance Data-To-XHTML/XForms Example</title> <xforms:model id="model_FIXML"> <xforms:instance id="instance_model_FIXML" src="tax_instance.xml"/> <xforms:submission id="submit_model_FIXML" action="http://localhost:8080/gdhis/taxServlet" method="post"/> </xforms:model> <link href="gen_default.css" rel="stylesheet"/> </head> <body> <xforms:input ref="/FIXML:FIXML/@r" model="model_FIXML"> <xforms:label>R</xforms:label> </xforms:input> <xforms:input ref="/FIXML:FIXML/@s" model="model_FIXML"> <xforms:label>S</xforms:label> </xforms:input> <xforms:input ref="/FIXML:FIXML/@v" model="model_FIXML"> <xforms:label>V</xforms:label> </xforms:input> <xforms:input ref="/FIXML:FIXML/FIXML:AllocRpt/@AcrdIntAmt" model="model_FIXML"> <xforms:label>Acrd Int Amt</xforms:label> </xforms:input> <xforms:input ref="/FIXML:FIXML/FIXML:AllocRpt/@AvgPx" model="model_FIXML"> ...

    在数据模型中,将接收 XML 实例数据的提交动作设置为一个 Servlet,也就是说当用户提交该表单的时候,是由 URI 为http://localhost:8080/gdhis/taxServlet 的 Servlet 来处理表单数据的。

    处理表单的 Servlet 清单如下,其作用是将表单数据存储到相应的数据库表里(这里,相应的数据表 TAX 的 DDL 也在下面给出)。


清单 2. 数据库表 TAX 的 DDL

CREATE TABLE “DB2ADMIN”. “TAX”( ID INT GENERATED ALWAYS AS IDENTITY ( START WITH 1, INCREMENT BY 1, MINVALUE 1, MAXVALUE 9223372036854775807, NO CYCLE, NO ORDER), TAX_CONTENT XML PRIMARY KEY (ID) );

清单 3. Servlet 代码

import java.io.*; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import javax.servlet.*; import javax.servlet.http.*; import java.util.ArrayList; import java.util.List; public class taxServlet extends HttpServlet{ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Connection conn=null; try{ conn=Database.getConnection(); ServletInputStream in=request.getInputStream(); BufferedReader requestData = new BufferedReader(new InputStreamReader(in)); StringBuffer stringBuffer = new StringBuffer(); String line=null; while ((line = requestData.readLine()) != null) { stringBuffer.append(line); } String sql="insert into tax(tax_content) values ('"+ stringBuffer.toString()+"')"; PreparedStatement ps=conn.prepareStatement(sql); ps.executeUpdate(); ps.close(); } catch(Exception e){ e.printStackTrace(); } finally{ Database.releaseConnection(conn); }

    其中,Database 类的 getConnection()方法通过 JDBC 获取数据库连接。由此可以看出,我们在后台直接可以得到表示表单数据的 XML 实例,并且由于后台数据库直接提供了对该 XML 实例的存储模式,所以我们需要做的只是调用 SQL 语句将得到 XML 实例直接插入相应的数据库表里。这样是不是很有效的解决了前面提到的问题呢?

    同样道理,当我们要显示一个 XML 数据时,也只需要从数据库表里读出相应的 XML 实例,并编写显示数据的 XForms 表单映射就可以了。这里我们在 XForms 中引用 XML 实例时,调用了一个 Servlet,当用户请求该 XForms 时,具有 URI 为http://localhost:8080/gdhis/taxDisplay 的 Servlet 就会读取 id 为 1的表单数据,并把 XML 实例返回给该 XForms 表单,具体的 XForms 代码片断如下:

清单 4. XForms 代码

<?xml version="1.0" encoding="ASCII"?> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ev=“http://www.w3.org/2001/xmo-events” xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:FIXML="http://www.fixprotocol.org/FIXML-4-4"> <head> <title>Instance Data-To-XHTML/XForms Example</title> <xforms:model id="model_FIXML"> <xforms:instance id="instance_model_FIXML" src="http://localhost:8080/gdhis/taxDisplay"/> <xforms:submission id="submit_model_FIXML" action="http://localhost:8080/gdhis/taxServlet?id=1" method="post"/> </xforms:model> <link href="gen_default.css" rel="stylesheet"/> </head> <body> <xforms:input ref="/FIXML:FIXML/@r" model="model_FIXML"> <xforms:label>R</xforms:label> </xforms:input> <xforms:input ref="/FIXML:FIXML/@s" model="model_FIXML"> <xforms:label>S</xforms:label> </xforms:input> <xforms:input ref="/FIXML:FIXML/@v" model="model_FIXML"> <xforms:label>V</xforms:label> </xforms:input> <xforms:input ref="/FIXML:FIXML/FIXML:AllocRpt/@AcrdIntAmt" model="model_FIXML"> <xforms:label>Acrd Int Amt</xforms:label> </xforms:input> <xforms:input ref="/FIXML:FIXML/FIXML:AllocRpt/@AvgPx" model="model_FIXML"> ...

    可以看到,在 XForms 表单的标签 <xforms:instance> 中,对“src“属性值是一个具有 URI 为 http://localhost:8080/gdhis/taxDisplay 的 Servlet,表单的显示部分仍然只需要将字段与相应的 XML 实例的节点对应就可以了。

    通过这样设置后,表单就能够读到从后台传来的 XML 数据实例,显示的数据片断如下:


图 2. 数据片断显示

    相应的 Servlet 代码如下面的程序清单,其作用是调用具有 id 为 1 的 XML 实例,并写到 Response 输出流中,返回给相应的 XForms 表单显示。


清单 5. 对应的 Servlet 代码

public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { int id; Connection conn=Database.getConnection(); String sql="select tax_content from tax where id=?"; PreparedStatement ps = conn.prepareStatement(sql); ps.setInt(1, id); ResultSet rs=ps.executeQuery(); String result=null; while(rs.next()) { result=rs.getString(1); } ServletOutputStream out=response.getOutputStream(); response.setContentType("application/xml"); out.println(result); } catch(Exception e) { e.printStackTrace(); } }

    通过前面的例子,相信你已经对如何结合 XForms 与 pureXML 来简化 XML 应用开发有所体会了。其实,XForms 的许多机制在简化表单开发的作用更是非同一般的。

    比如:XForms 采用 XML Events —— 另一个 W3C 技术标准,为特定文档元素增加事件处理程序,使你省去了很多编写和维护 javaScript 脚本的麻烦,也实现了一些用脚本难以实现的功能,这对日益复杂的 Web 开发是很有帮助的。

    还有一点,就是 XForms 提交的数据是通过由输入验证规则自动生成的代码验证有效的数据,而使用输入验证规则将有助于客户端验证。

    另外,由于 XForms 本身也是 XML 文件,这样,我们就可以像管理 XML 数据一样的方式来管理应用表单,同样可以借助 pureXML 进行有效的管理,这对那些拥有数目庞大的表单的应用开发来说是非常有用的。

总结

    本文以一个具体的实例来阐述如何借助 XForms 的诸多优势以及与 DB2 pureXML 结合使用来简化 XML 应用开发。当然,如果数据库模型仍然有一些关系表列存在时,还需要在后台处理程序中将从 XForms 传来的表单数据做相应的解析,并抽取出相应的关系表列,再分别存储,这无疑会影响整体运行效率,因此,可以总结为当数据模型被设计为纯 XML 模型或者有少量关系列时,选择 XForms 并结合 DB2 puerXML 是一个很好的选择。

0
相关文章