65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 XSLT 渲染 COM 对象返回的 XML 数据

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.50/5 (4投票s)

2001年9月11日

6分钟阅读

viewsIcon

142449

downloadIcon

905

这是一个三层应用程序。COM 组件以 XML 格式返回 SQL 数据,然后使用 XSLT 在客户端转换为 HTML。通过使用 XML,所有数据都可以在本地排序和分页,这将给用户带来快速响应!

Sample Image - screen.jpg

引言

本文将向您介绍如何使用 COM 和 XML 构建三层应用程序。在这里,我将向您展示如何构建一个返回 XML 格式数据的 ATL COM 组件,并使用 XSLT 将其转换为 HTML 页面,最后,如何本地排序和分页数据。

您需要一个本地数据源来构建此演示。在我的例子中,我使用本地 SQL Server 中 `pub` 数据库的 `employee` 表。

应用程序架构

Application architecture

如上图所示,整个系统将分为四个部分。用户浏览 ASP 网页,然后 ASP 将在远程服务器上创建 COM 组件,并发出命令从 SQL 数据库检索数据。然后 COM 组件使用 ADO 连接 SQL DB,在记录集返回后,它将记录集封装成 XML 格式,并传回给 ASP。ASP 动态输出 COM 组件返回的 XML 数据,同时添加一些头部信息以通知 Internet Explorer 使用特定的 XSL 文件进行渲染。此时,用户可以看到一个包含数据表的网页,他可以通过点击表头来排序数据,或通过点击表上方的按钮来导航页面。

尽管此应用程序有四个部分,但我是在自己的电脑上构建的,这意味着我安装了带有 IIS 的 Windows 2000 Advance Server 和本地 SQL Server。

COM

好的,让我们一步一步地讨论代码。首先是构建一个 COM 组件,它使用 ADO 从 SQL Server 检索数据。

启动 VC,使用 ATL COM `AppWizard` 创建一个新项目,将其命名为 `xmlrs`。按完成接受所有默认设置值。通过使用 ATL 对象向导(插入 -> 新建 ATL 对象)插入一个简单对象,将其命名为 `xmlrsobj`,并接受所有默认设置。通过右键单击类视图中的 `Ixmlrsobj` 图标添加此对象的方法。选择 `Add Method`,然后在方法名称字段中输入 `ConnectDB`,在参数字段中输入 `[in] BSTR bstrConn`。以同样的方式添加以下两个方法:

GetXmlrs ([in] int intRow, [out, retval] BSTR *xmlrs) 
CloseDB (void)

将代码填充到这些函数中。以下代码应添加到 CPP 文件中,因为 ADO 用于从 SQL Server 检索数据。

#import "C:\Program Files\Common Files\System\ADO\msado15.dll" \
    named_guids no_namespace rename("EOF", "EndOfFile")

COM 使用从 ASP 客户端传入的连接字符串连接到 SQL Server,然后 COM 组件通过 `SELECT` 命令获取特定的记录集。COM 组件依次将记录集封装成 XML 格式。

现在是时候构建您的 COM 对象了。VC 在成功构建后会注册 DLL 文件,然后您就可以在本地使用它了。如果您想将其部署到另一台计算机上,您必须根据您在此处使用的 DCOM 或 COM+ 进行额外的管理工作。

ASP

ASP 文件很简单。只需创建我们上面构建的 COM 对象,调用此对象的 `GetXmlrs` 方法,并使用 `response.write` 输出所有返回的数据。为了让 Internet Explorer 理解它从 ASP 页面获得的信息,我们应该将内容类型设置为 `text/xml`、XML 版本,并指定 XML 样式表。

Response.ContentType = "text/xml"
response.write "<?xml version=""1.0""?>"
response.write "<?xml-stylesheet type=""text/xsl"" href=""xml.xsl""?>"

不要忘记修改 ASP 文件中的连接字符串,以便它可以在您的环境中工作。

XSL

XSL 是一种 XML 渲染机制,它类似于 CSS 对 HTML。通过使用 XSL,我们可以将数据渲染与数据本身分离。

  1. 构建页面骨架的 HTML 代码

    <HTML>
    <BODY id="listing">
    <TABLE width="60%" cellspacing="0">
        <TR>
            <TD> fName </TD>
            <TD> lName </TD>
            <TD> hire_date </TD>
        </TR>
        <TR>
            <TD> fName </TD>
            <TD> lName </TD>
            <TD> hire_date </TD>
        </TR>
    </TABLE>
    </BODY>
    </HTML>

    通过这些 HTML 代码行,我们构建了一个带有空表的网页,我们将在其中填充 XML 数据。

  2. XSL 转换代码

    现在更新代码,通过使用 XSL 代码,我们用存储在 XML 中的数据填充了表格。

    ...
    <xsl:for-each select="Recordset/Record" order-by="fName">
    <xsl:if test="context()[index() $ge$ 0 and index() $lt$ 10]">
        <TR>
            <TD><xsl:value-of select="fName"/></TD>
            <TD><xsl:value-of select="lName"/></TD>
            <TD><xsl:value-of select="hire_date"/></TD>
        </TR>
    </xsl:if>
    </xsl:for-each>
    ...

    看看这些代码。代码对 `` 和 `` 意味着对 XML 文件中每个 `Record` 节点重复这对代码之间的所有代码,并且所有数据都将按 `fName` 字段排序。`Recordset/Record` 遵循 XPath 语法,这意味着根 `Recordset` 的 `Record`。

    下一对代码:`` ``。这对代码用于实现分页功能,它将过滤掉不在当前页面的数据。默认值将只显示前 10 条记录。在处理 `xsl:if` 命令时,计算机将首先计算 `test` 项的值,如果它包含至少一个数据节点,则 `test` 项将为 `true`。在这种情况下,`context()` 和 `index()` 是 XSL 内置函数,`context()` 将返回当前节点,`index()` 返回当前节点按顺序的序列号。`[...]` 表示过滤器,`$ge$` 在格式良好的 HTML 页面中表示 `>=`,而 `$lt$` 表示 `<`。因此代码 `context()[index() $ge$ 0 and index() $lt$ 10]` 意味着对于当前节点,如果其索引值 `>= 0` 且 `< 10`,则 `test` 项将返回 `true`,进而将渲染 `xsl:if` 对之间的 HTML 代码。

    最后但同样重要的是,代码 `` 返回 `fName` 的当前值。通过上面的代码,它将在循环期间渲染表格的内容。

  3. CSS 样式表使输出更美观

    XSL 样式表可以与 CSS 样式表结合使用,使页面更美观。以下代码定义了此示例中使用的 CSS 样式。根据以下行更新 XSL 文件

    ...
    <STYLE>
    BODY {margin:0}
    .row {font:8pt Verdana; border-bottom:1px solid #CC88CC}
    .header {font:bold 9pt Verdana; cursor:hand; 
              padding:2px; border:2px outset gray}
    .up {background-color:#DDFFDD; cursor:hand;}
    .down {background-color:#FFDDDD;}
    </STYLE>
    ...
    <TD class="header"> fName </TD>
    <TD class="header"> lName </TD>
    <TD class="header"> hire_date </TD>
    ...
    <TD class='row'> fName </TD>
    <TD class='row'> lName </TD>
    <TD class='row'> hire_date </TD>
    ...
    <TD class='row'><xsl:value-of select="fName"/></TD>
    <TD class='row'><xsl:value-of select="lName"/></TD>
    <TD class='row'><xsl:value-of select="hire_date"/></TD>
    ...
  4. 用于排序和分页所有数据的 JavaScript

    到目前为止,您已经得到了一个带有 XML 数据表的静态页面。我们通过添加以下 JavaScript 使其与用户交互。这些脚本帮助用户在表格中数据过多时分页导航数据。

    有四个脚本函数

    • `init()` -> 用于初始化第一页;
    • `prevpg()` -> 移动到上一页;
    • `nextpg()` -> 移动到下一页;
    • `sort (key)` -> 根据新关键字排序记录

    然后我们将这些函数与 HTML 项挂钩。

    ...
    <BODY id="listing" onLoad="init()">
    ...
    <p class="down">Click on the head to sort!</p>
    <div class="up" onClick="prevpg()">prev page</div>
    <div class="up" onClick="nextpg()">next page</div>
    ...
    <TD class="header" onClick="sort('fName')">fName</TD>
    <TD class="header" onClick="sort('lName')">lName</TD>
    <TD class="header" onClick="sort('hire_date')">hire_date</TD>
    ...

    注意代码对 `![CDATA[...]]`。这是因为格式良好的 HTML 会编码 `<`,因此我们必须将脚本放入 `![CDATA[...]]` 对中以避免编码。

    现在您应该有一个由 COM 和 XML 提供支持的三层应用程序。享受它吧。您会发现当您浏览页面时,订单不会改变,直到您设置新订单!

许可证

本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。

作者可能使用的许可证列表可以在此处找到。

© . All rights reserved.