使用 Domino XML (DXL) 可以使其他应用程序能够创建、查看和更新 Lotus Notes/Domino 6.x 中的 Notes 文档。通过 LotusScript 代理,可以查看 DXL 格式的 Notes 文档,从 DXL 创建文档,还可以从 DXL 更新文档。
Domino XML (DXL) 是 Domino 设计元素的 XML 格式表示,这种 XML 使用 Notes/xmlschemas 目录中的 Domino DTD。(Lotus Notes/Domino 7 还将包括 XML 模式文档。)DXL 为将 Domino 应用程序数据暴露给其他平台提供了一种很好的方式。例如,DXL 允许以 XML 格式导出和导入 Domino 数据和设计元素。DXL 最初是在 Lotus Domino 5 中引入的,在更新的版本中,DXL 已成为 Lotus Domino 的核心的一部分。(developerWorks: Lotus 文章 "Lotus Domino 与 IBM WebSphere 集成解决方案: Domino XML" 对 DXL 作了很好的介绍)。
在本文中,我们讨论了 Lotus Domino 6.5.x 中创建的 DXL 框架的一些关键组件,这些组件用于浏览、创建和更新 Domino 数据。这个框架由一个 Domino 数据库组成,该数据库包含三个 LotusScript 代理,分别用于浏览、更新和创建 Notes 文档。本文假设您是一名有经验的应用程序开发人员,拥有使用 Lotus Domino 和 XML 的经验。
我们的定制 DXL 框架简化了任何客户机对 Notes 对象的访问。有很多方法可以从不同的编程平台访问 Domino 对象。然而,面对某种给定的场景,每种访问方法都呈现着其特有的挑战。例如,常规 Java 应用程序使用的 DIIOP 访问方法不能穿越传统的防火墙,因为这些防火墙只允许 HTTP 传输。因此,不存在与应用程序无关的开箱即用的方式来创建或读取文档。这就说明了为什么 XML 是很好的选择。如果您正在构建有特殊需求(例如防火墙)的 Microsoft .Net 客户机或常规 Java 客户机,那么这里的 DXL 框架可以提供一个良好的解决方案。
例如,您可以使用 DXL 框架来构建一个应用程序,这个应用程序允许用户:
- 在 Notes 视图中查看一组 Notes 文档。
- 从该组文档中选择一个文档,并查看该 Notes 文档的细节。
- 在选定的文档上更新值。
- 创建新的 Notes 文档。
图 1 说明了组成这个 DXL 框架的关键设计元素。
图 1. DXL 框架

如图 1 所示,我们的 DXL 框架由一个 Domino 数据库(database.nsf)组成,该数据库包含三个 LotusScript 代理:
- [DXLUpdateDoc] 接受 DXL 格式的 XML,并处理来自客户机的请求,以更新具有给定 UNID 的选定文档。
- [DXLCreateDoc] 接受 DXL 格式的 XML,并处理客户机请求,以创建一个新的文档。
- [DXLViewDoc] 返回具有给定 UNID 的选定文档的 XML。
我们将在后面描述这些代理的内部工作原理。此外,您可以使用 Notes 视图的本地功能通过?ReadViewEntries URL 命令呈现 XML 数据,从选定的 Notes 视图中请求 XML 数据。
在本文中,我们主要关注 DXL 框架的服务器端组件。(要下载图 1 中所示的样本代理,请查看本文后面的下载小节)。
![]() ![]() |
![]()
|
现在让我们看看如何安排视图和文档的 DXL 格式。图 2 展示了一个视图的 DXL。
图 2. 一个 Notes 视图 DXL 格式

在图 2 中:
- 蓝色的圆圈表示元素。
- 灰色的椭圆表示属性。
- 黄色的矩形表示字符数据。
- 绿色的箭头表示“含有一个……”。
- 黑色的箭头表示聚合。
如图 2 所示,viewentries 是顶层元素。它包含一个或多个 viewentry 元素,这些元素又各自包含一个或多个 entrydata 元素。每个 entrydata 元素可以包含以下几个元素中的一个:text、number、datetime 和 numberlist。
注:在这一节中,我们讨论 DXL viewentries 元素,该元素含有 DXL 格式的视图的内容。不要将它与 DXL 视图元素混淆,后者是 DXL 格式的视图的实际描述。
图中还给出了我们在 XML 处理过程中使用的关键属性。对于 viewentries 元素,我们使用 toplevelentries 来得到一个视图中所有文档的计数。从 viewentry 我们可以得到 UNID (存储起来供以后使用),从 entrydata 可以得到 columnnumber 属性,以便用于查找需要的字段值。
下面是视图 DXL 代码的一个片段:
<?xml version="1.0" encoding="UTF-8"?> <viewentries toplevelentries="26"> <viewentry position="1" unid="F0C7DF1BE84F48B685256F0800720716" noteid="1392" siblings="26"> <entrydata columnnumber="0" name="$18"> <number>0</number></entrydata> <entrydata columnnumber="1" name="$17"> <text>Styles, Ron</text></entrydata> <entrydata columnnumber="2" name="$12"> <text></text></entrydata> <entrydata columnnumber="3" name="CompanyName"> <text></text></entrydata> <entrydata columnnumber="4" name="$16"> <text>R Styles@ABC</text></entrydata> <entrydata columnnumber="5" name="$21"> <text>NotesMail/HQ/ABC</text></entrydata> </viewentry> ...... </viewentries> |
图 3 演示了 Notes 文档 DXL (在这里就是 database.nsf 中的一个 Person 文档)。
图 3. 一个 Notes 文档的 DXL 格式

在本文中,我们主要关注上面关于 DXL Notes 文档的图中所显示的元素和属性。(我们不使用 noteinfo 和 updatedby 元素,所以图 3 没有给出这两个元素)。如演示所示,document 是顶层元素,它包含一个或多个 item 元素。每个 item 元素各自又可以包含以下元素中的一个:text、number、datetime、numberlist 和 textlist。item 元素的关键属性是 name,用于查看我们感兴趣的字段值。
下面是一个例子文档的 DXL 代码的片段:
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE document SYSTEM 'xmlschemas/domino_6_5_1.dtd'> <document xmlns="http://www.lotus.com/dxl" version='6.5' maintenanceversion='1.0' replicaid='85256F080071E637' form='Person'> <noteinfo >......</noteinfo> <updatedby>......</updatedby> <item name='Title'><text/></item> ...... <item name='Owner' authors='true' names='true' protected='true'><text> CN=Ron Styles/OU=HQ/O=ABC</text></item> </document> |
至此我们对视图和文档的 DXL 格式已经有所理解,现在让我们看看,当一个客户机查看样本数据库的 All Documents 视图中的文档列表时在内部所发生的一系列事件:
- 用户打开常规客户机应用程序,输入用户 ID 和密码。(或者,也可以在配置文件中提供)。
- 客户机应用程序使用 ?ReadViewEntries 查询字符串,针对目标数据库视图创建到 Domino 服务器的一个 HTTP 请求。在这里,这个视图就是样本 All Documents 视图,该视图显示例子数据库中的所有文档。
- Domino 服务器验证用户,处理请求,并在 HTTP 响应中将 XML 数据返回给客户机。
- 客户机应用程序处理从服务器收到的 XML 数据,并显示 All Documents 视图中的文档列表。
图 4 演示了这个过程。
图 4. 查看文档

当一个客户机打开 All Documents 视图中的一个 Notes 文档时,将进行以下步骤:
- 像上一节中描述的那样,用户打开 All Documents 视图。
- 用户选择一个要打开的文档。
- 客户机应用程序获得所选文档的 UNID,并发送一个针对 URI 为 /ViewDXLDoc?Open&unid=<doc UNID> 的目标数据库的 HTTP 请求到 Domino 服务器。
- Domino 服务器处理该请求,验证用户并处理代理请求,输出 DXL 格式的文档(文档的 UNID 是在请求中发送的)。
- 常规客户机收取 DXL 文档的 XML 数据并加以处理。
- 为用户显示所选文档的一个细节视图。
图 5 展示了这个过程。
图 5. 打开一个文档

当用户创建一个新的 Notes 文档时,将进行以下步骤:
- 用户启动客户机应用程序,选择用于创建新文档的菜单选项。
- 用户在应用程序中看到一个常规的表单。用户填好该表单,并提交/保存表单。
- 应用程序提取表单数据,将其格式化为 XML(遵从 DXL 文档格式),然后调用 DXLCreateDoc 代理。这样将在 HTTP 请求中发送 DXL 内容。
- Domino 服务器验证用户,并处理代理请求。
- DXLCreateDoc 代理处理 DXL 文档中的 XML 数据,返回的消息被发送到客户机。
- 用户看到关于表单提交动作的成功/失败消息。
图 6 展示了这些步骤。
图 6. 创建一个文档

![]() ![]() |
![]()
|
在这一节中,我们研究 [DXLViewDoc]、[DXLUpdateDoc] 和 [DXLCreateDoc] 这几个 LotusScript 代理的内部工作原理。这些代理是 DXL 框架的关键组件。我们研究每个代理的代码片段,解释每个片段所做的工作。(要下载这些代理的完整代码,请查看下载小节)。
[DXLViewDoc] 代理返回选定文档的 XML。该代理首先设置一些标准变量。我们使用会话文档上下文方法获得文档对象。对 HTTP 请求的响应是通过标准打印语句来处理的。首先将响应内容类型初始化为 text/xml。还要捕捉错误。
Sub Initialize Dim s As New notessession Dim db As notesdatabase Dim doc As notesdocument Dim doc1 As notesdocument Set doc1 = s.DocumentContext Print "Content-type: text/xml" On Error Goto err1 Set db = s.currentdatabase Dim stg As String |
然后通过请求 URL 的查询字符串查找传入的 UNID,并进行最小错误检查。
stg = doc1.Query_String(0) If Len(stg) < 5 Then Goto err1 End If If Instr(stg,"unid=") < 1 Then Goto err1 Else stg = Right(stg,Len(stg)-Instr(stg,"=")) End If |
得到一个有效的 UNID 后,首先获取 Notes 文档的一个句柄,接着使用 NotesDXLExporter 将内容导出到 XML,并确保 XML 中不需要提供 DTD。
Set doc = db.GetDocumentByUnID(stg) Dim exporter As NotesDXLExporter Dim stream As notesstream Set exporter = s.CreateDXLExporter exporter.OutputDOCTYPE=False Set stream = s.CreateStream Call exporter.SetInput(doc) Call exporter.SetOutput(stream) Call exporter.Process |
然后从 stream 对象获得文本,并将文本输出到客户机。
Print stream.ReadText() End err1: Print "You reached in error" Resume End Sub |
[DXLUpdateDoc] 代理处理客户机请求,以更新所选定的文档。我们使用请求的 Request_Content 属性来获得由客户机发送的实际 XML 的句柄,并将其输送到 stream 对象。
Dim x As NotesItem Dim stream As NotesStream Set x =doc.GetFirstItem("Request_Content") ........... ..... Call stream.WriteText(x.Text) |
然后实例化 NotesDXLImporter,以便在数据库上下文中使用 stream,并规定这次的导入是更新而不是创建。
Dim imp As NotesDXLImporter Set imp = session.CreateDXLImporter(stream, db) imp.DocumentImportOption=DXLIMPORTOPTION_UPDATE_ELSE_IGNORE imp.ReplicaRequiredForReplaceOrUpdate = False Call imp.Process |
[DXLCreateDoc] 代理处理客户机请求,以创建一个新的文档。该代理与 DXLUpdateDoc 代理很相似。它们之间的主要区别是,在使用 stream (在数据库上下文中)的过程中,我们规定了这次的导入类型是创建,从而可以创建一个新的文档。
imp.DocumentImportOption=DXLIMPORTOPTION_CREATE
....
![]() ![]() |
![]()
|
在本文中,我们描述了如何利用 Lotus Notes/Domino 6 中提供的 DXL 特性,然后描述了如何用定制的 LotusScript 代理创建一个框架,用于查看和更新已有的 Notes 文档。这个框架被设计用来简化对 Notes 对象的访问。它使用 XML 而不是 HTML,因此,对于任何知道如何处理 XML 的应用程序来说,它处理起来比较简单。由于它是通过 HTTP 协议传输的,因此可以通过防火墙。
本文的目的是为您提供必要的预备知识,以便能够使用我们描述的 DXL 框架来设计用来访问和处理 Domino 数据的应用程序。在设计用于 Web(JSR168 portlets)和丰富客户机(Eclipse RCP)的应用程序时,也可以使用这个框架。