为了根据用户的需求实现数据库或模板定制,常常需要动态地在现有数据库中自动添加设计元素,比如代理、视图或文件夹,或者修改数据库中现有的设计元素。Domino XML Language (DXL) 是一种用于表示 IBM® Lotus® Domino® 数据和设计元素的 XML 格式,可以方便地捕捉设计元素和在数据库中导入或导出设计元素。在本文中,我们介绍 DXL 的概念,并通过用例和详细的实现讲解如何应用 DXL 来动态地添加或修改设计元素,从而完成用户的数据库或模板定制。
Lotus Domino 数据的 XML 表示格式称为 DXL。DXL 描述 Lotus Domino 特有的数据和设计元素,比如视图、表单和文档。XML 已经成为信息交换的标准格式,DXL 为在 Lotus Domino 应用程序中导入和导出数据的 XML 形式提供了基础。DXL 用来详细描述 Lotus Domino 数据库中包含的结构和数据。
DXL 的结构由 Lotus Domino 文档类型定义 (DTD) 文件描述,在默认情况下可以在 Lotus Notes 安装路径(比如 IBM/lotus/notes/xmlschemas)中找到这个文件。这个 DTD 包含 XML 标记的定义,在把外部 XML 数据转换到 Lotus Domino 数据库中时可以用它检验 XML 文档,在把内部 Lotus Domino 数据库导出为 XML 时可以用它理解产生的 XML 文档。
组成 Domino DTD 的实体和元素如下:
- 核心实体。作为数据类型类别的实体,比如 binary、Boolean、float、hex、integer、notesid 和 unid。
- 通用实体。在其他实体或多个元素中引用的实体,比如 acl.levels、color、image.formats、length 和 pixel。
- Lotus Domino 元素。Lotus Domino DTD 中的所有元素。它们表示 Lotus Domino NSF 数据库或 NTF 模板中存储的数据的类型。表 1 列出主要的 Lotus Domino 元素。
表 1. 主要的 Lotus Domino 元素
acl | aclentry | action | actionbar | actionbarstyle | actionhotspot | addedtofile | agent |
---|---|---|---|---|---|---|---|
anchor | area | background | block | border | break | button | caption |
code | column | control | created | database | datetime | doclink | document |
endate | endtime | entrydata | field | fieldchoice | file | filedata | folder |
font | form | formula | frame | gif | globals | imageref | imageresource |
item | itemdata | java | javaapplet | javaarchive | javaproject | javaresource | javascript |
jpeg | keyword | lastaccessed | layout | logentry | lotusscript | modified | name |
note | noteinfo | notesbitmap | noteslaunch | number | object | objectref | page |
par | pardef | parstyle | picture | point | popup | popuptext | region |
revised | richtext | richtextdata | role | run | rundata | schedule | scriptlibrary |
search | section | sendbcc | sendcc | sendsubject | sendto | servlet | sharedfield |
span | startdate | startime | subform | table | tablecell | text | textlist |
textproperties | title | trigger | urllink | view | viewlink | weblaunch | word |
database 元素是 DXL 文件中的重要元素。图 1 显示 XML 模式中的 database 元素。它包含一些属性和子元素。属性描述数据库本身,比如 title、version、path 和 replicaid。子元素包括两种类型:
- 与数据库本身相关的子元素,比如 databaseinfo、acl、fulltextsetting 和 launchsetting。
- database 元素中包含的子元素,比如 note、document、form、subform、page、view、folder 和 agent。
图 1. database 元素及其子元素和属性
在开发应用程序期间,可以使用 Java™ 或 LotusScript® 操作 DXL。它们提供以下功能:
- 把 DXL 导入数据库或模板,以及从数据库或模板导出 DXL
- 处理 DXL 流或文件
DxlExporter 类把 Lotus Domino 数据转换为 DXL。在会话中使用 createDxlExporter 方法创建一个 DxlExporter 对象。使用 exportDxl 方法执行导出操作。exportDxl 的输入可以是 Database、Document、DocumentCollection 或 NoteCollection 对象。输出是一个 String 对象。
DXLImporter 类把 DXL 转换为 Lotus Domino 数据。在会话中使用 createDXLImporter 方法创建一个 DxlImporter 对象。DxlImporter 的输入可以是 String、Stream 或 NotesRichTextItem 对象。输出是一个 Database 对象。
Lotus Domino Designer 还包含 XML4J 解析器和 LotusXSL 处理器,可以使用它们访问对象的 XML 表示、解析和转换 XML 数据以及通过 Java 后端类中的属性和方法生成文档的 XML 表示。
NotesDXLExporter 类把 Lotus Domino 数据转换为 DXL。在 NotesSession 中使用 CreateDXLExporter 方法创建一个 NotesDXLExporter 对象。导出过程的输入可以是 NotesDatabase、NotesDocument、NotesDocumentCollection 或 NotesNoteCollection 对象。输出是 NotesStream 或 NotesRichTextItem 对象或任何其他 XML 处理器。
NotesDXLImporter 类把 DXL 转换为 Lotus Domino 数据。在 NotesSession 中使用 CreateDXLImporter 方法创建一个 NotesDXLImporter 对象。导入过程的输入可以是 string、NotesStream 或 NotesRichTextItem 对象或任何其他 XML 处理器。输出是一个 NotesDatabase 对象。
可以使用 NotesDOMParser 和 NotesSAXParser 解析 DXL。NotesDOMParser 把 DXL 解析为标准的 Document Object Model (DOM) 树。可以使用其他 NotesDOM 类操作 DOM 树。NotesSAXParser 使用一个 Simple API for XML (SAX) 解析器以事件的形式处理 DXL。
在工作流系统中,常常需要定制用户的数据库或模板。有时候,无法在 Notes Java API 或 LotusScript. 中找到适当的接口,从而直接添加或修改数据库或模板。DXL 有助于解决这种难题;它可以添加设计元素或修改任何现有的设计元素和属性。下面讨论几个用例和与 DXL 相关的解决方案,您可以在实际开发中应用这些解决方案
用户的数据库是从组织中的共享模板派生的。通过在 Lotus Domino Designer 中修改共享模板和添加代理,就可以添加与代理相关的函数。但是,这种方法有一些限制:
- 代理的添加是静态的,不能通过用户的首选项控制。
- 代理添加到所有用户的数据库中,所有用户都可以看到添加的函数。
为了解决这个问题,只让特定的用户能够使用函数,可以使用 DXL 技术在特定用户的现有数据库中动态地添加代理。对于这个场景,管理员可以编写一个电子邮件,其中包含一个热点和一个 DXL 文件,然后把电子邮件发送给特定的用户。这些用户接收电子邮件之后,他们可以单击热点并添加代理。
首先,我们来看看热点和 DXL 文件的内容,见清单 1 和清单 2。
清单 1. 热点中的 “AddMyAgent” LotusScript
1 Sub Click(Source As Button) 2 Dim session As New NotesSession 3 Dim stream As NotesStream 4 Dim importer As NotesDXLImporter 5 Dim curdirname As String 6 7 REM Set current database 8 Set db = session.CurrentDatabase 9 curdirname = Curdir() 10 11 Dim workspace As New NotesUIWorkspace 12 Dim uidoc As NotesUIDocument 13 Dim doc As NotesDocument 14 Dim db As NotesDatabase 15 16 REM Get the DXL file from current document 17 Set uidoc = workspace.CurrentDocument 18 Set doc= uidoc.Document 19 Set rtitem = doc.GetFirstItem("Body") 20 21 Forall eo In rtitem.EmbeddedObjects 22 Call eo.ExtractFile( curdirname + eo.source ) 23 End Forall 24 25 REM Open DXL file 26 Set stream = session.CreateStream 27 If Not stream.Open(curdirname + "AddMyAgent.dxl") Then 28 Msgbox "Cannot open AddMyAgent.dxl", , "Error" 29 Exit Sub 30 End If 31 If stream.Bytes = 0 Then 32 Msgbox "File did not exist or was empty", , "Error" 33 Exit Sub 34 End If 35 36 REM Import DXL into new database 37 Set importer = session.CreateDXLImporter 38 importer.ReplaceDBProperties = True 39 importer.ReplicaRequiredForReplaceOrUpdate = False 40 importer.ACLImportOption = DXLIMPORTOPTION_REPLACE_ELSE_IGNORE 41 importer.DesignImportOption = DXLIMPORTOPTION_CREATE 42 Call importer.Import(stream, db) 43 44 REM Sign agents with current user 45 Call db.sign(DBSIGN_DOC_AGENT) 46 Call stream.Close 47 End Sub |
这个过程是用 LotusScript. 编写的。也可以使用 Java 编写它。从第 16 行到第 23 行,它把 DXL 文件从电子邮件中分离出来并保存到磁盘上。从第 25 行到第 42 行,把 DXL 文件读入流中并导入数据库。在第 42 行之后,把名为 MyAgent 的新代理添加到用户的数据库中。在第 45 行,用当前用户签名代理,让代理可以正确地运行。
<?xml version="1.0"?> 20080402T061930,91-0720080901T151520,50-0720080901T151520,49-0720080901T151520,49-0720080402T061930,91-07CN=Administrator/O=ibm20080901T151520,48-07 |
图 2. 特定用户的用户界面
在重新打开数据库之后,用户可以在操作菜单中看到名为 MyAgent 的新代理,见图 2。在窗口的右下部是管理员发来的电子邮件的预览,其中包含热点和 DXL 文件。除了 agent 设计元素之外,还可以把任何其他设计元素导入数据库或模板,见图 3。在这个 DXL 文件中包含 agent、view 和 imageresource 设计元素。把这个文件导入数据库之后,可以在数据库中添加两个代理、两个视图和四个 GIF 资源文件。
图 3. 包含 agent、view 和 imageresource 的 DXL 文件
注意,Java API 和 LotusScript. 提供了许多访问数据库属性及其子集的方法,但是这些方法并不能修改所有属性。可以使用 DXL 技术解决这个问题。可以在 DXL 文件中表示所有数据和设计元素。可以在 DXL 文件中修改属性值,然后把修改后的 DXL 文件导入数据库。这样就可以修改数据库中的属性。
我们来看一个简单的示例。如果希望修改数据库的 launch 属性,可以通过 DXL 技术来实现。
表 2 列出在 Lotus Notes 客户机中打开数据库时可用的选项。如果希望在打开 Lotus Notes 数据库时自动地显示一个框架集(比如 MailFS),那么可以导入清单 3 所示的 Modifydatabaseproperty DXL 文件。
表 2. noteslaunch 元素设置
在 Notes 客户机中打开时 | common.whenopened 或 notes.whenopened | 框架集或导航器名 |
---|---|---|
Restore as lastviewed by user | Restorelastview | 不可应用 |
Open About database document | Openaboutdocument | 不可应用 |
Open designated frameset | Openframeset | MailFS、BorderFrame、ToDoFS 等 |
Open designated navigator | Opennavigator | Folders、Page 等 |
Open designated navigator in its own windows | Opennavigatorwindow | Standard Navigator、Page 等 |
Launch first attachment in About database | Openfirstaboutattachment | 不可应用 |
Launch first doclink in About database | Openfirstdoclink | 不可应用 |
清单 3. Modifydatabaseproperty DXL 文件
<?xml version="1.0"?> |
在使用 Lotus Notes 设计元素时,Lotus Notes 以事件的形式跟踪它们的操作(例如,打开数据库、打开视图或打开文档)。数据库的事件处理函数保存在 databasescript. 元素的 code 元素下面,databasescript. 元素是 database 元素的子元素,见图 4。
图 4. databasescript. 元素及其子元素和属性
数据库事件表示数据库范围内的活动,比如打开和关闭数据库或删除和恢复文档。下面是一些示例:
- PostOpen。打开特定的视图,将用户指引到操作项。
- QueryDocumentDelete。当操作项上的状态字段值是 open 时,禁止用户删除特定的文档。
- PostDocumentDelete。对删除的文档进行存档。
- QueryClose。当分配给数据库的操作项视图中仍然有操作项时,禁止用户关闭数据库。
通过修改 PostOpen 过程,可以改变数据库打开事件的默认处理行为。例如,通过使用 DXL 技术而不是 Lotus Domino Designer,可以添加一个欢迎窗口,让这个欢迎窗口在用户打开数据库时显示出来。使用 DXL 技术的优点是,可以把用于修改 PostOpen 过程的逻辑封装在热点或按钮中。用户可以通过单击按钮应用修改,不需要手工打开 Lotus Domino Designer 进行修改。
为了修改 PostOpen 过程,需要先导出现有的 PostOpen。可以使用 DXL 导出器和 SAX 解析器完成这一步。使用 DXL 导出器把 databasescript. 元素导出到 DXL 流中;见清单 4 中的第 19 行到第 54 行。然后,使用 SAX 解析器解析 DXL 流并找到 databasescript. 元素的 code 元素,见第 77 行到第 164 行。如果找到了处理 PostOpen 的代码,就把显示欢迎窗口的代码插入现有的 PostOpen 过程,见第 124 行到第 141 行。最后,可以使用 DXL 导入器把修改后的 DXL 文件导入数据库,见第 57 行到第 73 行。
清单 4. ModifyDatabaseScript. LotusScript. 文件
1 (Declarations) 2 Dim isPostOpenEvent As Boolean 3 Dim isPostOpenCode As Boolean 4 Dim isCode As Boolean 5 6 Sub Initialize 7 8 Dim session As New NotesSession 9 Dim db As NotesDatabase 10 Dim streamIn As NotesStream 11 Dim streamOut As NotesStream 12 Dim dxlExporter As NotesDXLExporter 13 Dim dxlImporter As NotesDXLImporter 14 Dim saxParser As NotesSAXParser 15 16 REM get current database 17 Set db = session.CurrentDatabase 18 19 REM Create DXL exporter 20 Set dxlExporter = session.CreateDXLExporter 21 22 REM Create the stream that will store the DXL 23 Set streamIn = session.CreateStream 24 Call streamIn.Truncate 25 Set streamOut = session.CreateStream 26 Call streamOut.Truncate 27 28 REM Create note collection 29 Dim nc As NotesNoteCollection 30 Set nc = db.CreateNoteCollection(False) 31 nc.SelectDatabaseScript. = True 32 Call nc.BuildCollection 33 34 REM Export note collection as DXL 35 Set dxlExporter = session.CreateDXLExporter(nc) 36 dxlExporter.OutputDOCTYPE = True 37 38 filename$ = "c:\" & Left(db.FileName, Len(db.FileName) - 3) & "xml" 39 If Not streamIn.Open(filename$) Then 40 Messagebox "Cannot open " & filename$,, "Error" 41 Exit Sub 42 End If 43 streamIn.Truncate 44 45 REM Create the SAX Parser, the results of the parse will be pushed into stream (streamIn) 46 Set saxParser = session.CreateSAXParser(dxlExporter, streamIn) 47 On Event SAX_Characters From saxParser Call SAXCharacters 48 On Event SAX_EndElement From saxParser Call SAXEndElement 49 On Event SAX_StartDocument From saxParser Call SAXStartDocument 50 On Event SAX_StartElement From saxParser Call SAXStartElement 51 52 REM Initiate parsing, by doing this the SAX events are called 53 REM It is in there that the DXL is rewritten and the PostOpen() method was modified. 54 Call dxlExporter.Process() 55 streamIn.Close 56 57 REM Open xml file named after current database 58 If Not streamOut.Open(filename$) Then 59 Messagebox "Cannot open " & filename$,, "Error" 60 Exit Sub 61 End If 62 If streamOut.Bytes = 0 Then 63 Messagebox "File did not exist or was empty",, filename$ 64 Exit Sub 65 End If 66 67 REM Import DXL into new database 68 Dim importer As NotesDXLImporter 69 70 Set importer = session.CreateDXLImporter(streamOut, db) 71 importer.ReplaceDBProperties = ture 72 importer.DesignImportOption =DXLIMPORTOPTION_REPLACE_ELSE_CREATE 73 Call importer.Process 74 75 End Sub 76 77 Sub SAXStartDocument (Source As Notessaxparser) 78 REM Write DXL header 79 Source.Output("<?xml version='1.0'?>" & Chr(10)) 80 End Sub 81 82 Sub SAXStartElement (Source As NotesSAXParser,_ 83 Byval strElementName As String, Attributes As NotesSaxAttributeList) 84 85 Dim i As Integer 86 REM Open Element 87 Source.Output("<" & strElementName) 88 If Attributes.Length > 0 Then 89 For i = 1 To Attributes.Length 90 REM Get the name and value of the attribute 91 strAttrName = Attributes.GetName(i) 92 strAttrValue = Attributes.GetValue(i) 93 REM Check whether current element is code 94 If strElementName = "code" Then 95 bCode = True 96 If strAttrName = "event" Then 97 If strAttrValue = "postopen" Then 98 REM found postopen event 99 bPostOpenEvent = True 100 End If 101 End If 102 End If 103 REM Write the attribute 104 Source.Output(| | & strAttrName & |="| & strAttrValue & |"|) 105 Next 106 End If 107 108 If strElementName = "lotusscript" And bPostOpenEvent Then 109 REM found postopen code 110 bPostOpenCode = True 111 End If 112 113 REM Close the element tag here 114 Source.Output(">") 115 End Sub 116 117 Sub SAXCharacters (Source As Notessaxparser, Byval Characters As String, _ 118 Count As Long) 119 120 If isCode Then 121 Source.Output("<![CDATA[") 122 End If 123 124 If (isPostOpenCode) Then 125 REM insert code into this place 126 Dim header As String 127 Dim pos As Integer 128 Dim newchar As String 129 130 header = "Notesuidatabase" 131 pos = Instr(Characters,header) 132 133 If (pos = 1) Then 134 REM at the begining 135 Else 136 REM found the patten, and insert the code 137 newchar = Left(Characters, pos+16) 138 newchar = newchar + Chr(13) + "Msgbox" + Chr(34) + "Welcome"+ Chr(34) + Chr(13) 139 newchar = newchar + Mid(Characters, pos+ 17) 140 End If 141 Source.Output(newchar) 142 Else 143 Source.Output(Characters) 144 End If 145 146 If bCode Then 147 Source.Output("]]>") 148 End If 149 150 End Sub 151 152 Sub SAXEndElement (Source As NotesSAXParser, Byval ElementName As String) 153 154 REM Terminate the element 155 Source.Output("</" & ElementName & ">" & Chr(10)) 156 157 If ElementName = "lotusscript" And isPostOpenEvent Then 158 isPostOpenCode = False 159 isPostOpenEvent = False 160 Elseif elementName = "code" Then 161 isCode = False 162 End If 163 164 End Sub |
这样就改变了数据库打开事件的处理行为,打开数据库时将会显示一个欢迎窗口。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/14751907/viewspace-580655/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/14751907/viewspace-580655/