返回首页

简介
本文将介绍如何挂钩RoboHelp项目数据库提供的数据页为WebHelp和编译的说明,使用单一架构。我们将介绍问题的情况下,评估解决一些替代,然后讨论实施。在我们的实现,我们将依靠建成的几乎所有的Web浏览器和编译帮助输出以及内部包含的页面上的JavaScript解释器。我们将依靠RoboHelp的单源的布局系统和支持有条件的构建标签,自定义输出选项。
我们的服务器端解决方案,我们也将使用JavaScript,但这里介绍的解决方案框架是不再加上使用服务器端的JavaScript。然而,这篇文章将显示JavaScript解释如何通过使用对象的文字符号,非常适合于封送处理数据,并从客户端的任务。最后,提出的解决方案是通用的,可重用和可扩展。所有项目资源中引用的。ZIP存档下载。有关AJAX和MADCAP软件的注意事项
在进入本文之前,我想请注意,这里描述的是被称为AJAX,或异步JavaScript和XML流行的技术非常相似。我不知道这个词时,我写了这个,但寻找一些关于JavaScript对象文字符号,看看是否有人写了不同的语言分析器的信息后,我发现有关JSON。此外,我了解到,目前还不清楚未来的RoboHelp X5,但狂妄的软件要通过支持RoboHelp项目文件格式。这里有一些这方面的信息的详细信息链接: 目录表
我希望你找到你自己的RoboHelp项目这篇文章有用的提示,代码和资源。当前数据为Web和桌面提供帮助项目的问题
,帮助作者往往面对的是,他们必须通过两个或更多的途径的帮助内容提供给用户提供一个问题:网站提供的帮助页面(WebHelp RoboHelp术语)。独立的帮助系统,在用户的桌面上(编译帮助)。
在这些网页中的内容可能是静态的,不容易改变,但它很可能是许多地区应该是动态的的。 WebHelp的情况下,这个内容可以交付给客户,刚刚当请求发送到服务器的时间。但是,对于编译的帮助,这不是因为理想的分配应该是完全自包含的,决不依赖于用户访问Internet连接的情况下。应用用户为中心的的设计格言
上面的例子也适用于在一个基于互联网的系统的情况下,因为作者和开发人员,我们的目标是,他们是最方便和灵活的方式向最终用户提供信息。
我们设计我们的解决方案正确,不应该有一个在理论上的东西,可以做不能做到在实践中,由于我们缺乏自己的技术远见为用户灵活的情况。案例分析:国际工作人员的公司需要的动态信息
要提供一些动态信息的一个例子,考虑一个虚构的公司,名为"国际工作人员公司(ISC)这两个例子:ISC保持伙伴组织,业务领域,并在公司内部的职称等信息的列表。在ISC的变化,有时因责任旋转,营业额,或物理搬迁,为人们的信息。
ISC具有国际访问的网站,为客户提供服务,为寻求和申请工作。他们还正在考虑提供独立的应用程序,用户可以下载到他们的电脑,使更轻松地访问服务。因此,他们希望能够部署在网络上和在断开连接,桌面部署的帮助系统。他们希望上面的数据出现在输出的原型如下显示如何。原型所需的输出
在这个原型,ISC已确定与绿色背景的动态生成的地区。作为一个快速成长的公司,ISC经常更新这些信息,不想要,必须重新编译他们的帮助项目所有的时间来向他们的客户提供准确的信息。
{S0}问题陈述
检查的要求和原型输出后,我们可以定义我们的问题,声明两部分:我们如何提供一个灵活的机制,包括到我们的RoboHelp项目动态数据,不需要重新编译时,数据的变化?如何能做到这一点,这样相同的基本机制是用于WebHelp和编排的帮助?的要求表
从这个声明中,我们得出以下三个方面的要求:的优先级(3最高) R1
3
解决方案必须提供一种方法,包括动态数据到WebHelp和编译帮助。
R2
2
解决方案应使用相同的基本机制为WebHelp和编排的帮助,以减轻维护和发展。
R3
1
解决方案应该具有可扩展性,以便为今后类似的增加。
继续阅读,看看如何选择和实施一个解决方案,满足所有三个方面的要求,很简单的,可重用,和可扩展。评估可能的解决方案
我们知道现在的规定和一些强耦合的技术关联:WebHelp和编译帮助提供动态数据。确保该解决方案在IE和Netscape,Mozilla和Firefox等工程如果可能的话,使用相同的机制WebHelp和编译帮助。其他评价矩阵
带着这些思想似乎是可行的: 替代
执行计划
R1?
R2的?
R3的?
SA1
内使用浏览器作为数据岛XML吗??/ P>
XML块可用于提供的数据段,并在运行时转换。提供帮助编译的静态副本,并产生动态WebHelp。



SA2
使用一个简单的数据库,如MS Access中
嵌入编译的帮助MDB文件,并调用它从Web服务器上的帮助。



SA3
使用JavaScript的文字对象作为数据存储机制
嵌入静态。js文件作为行李RoboHelp编译帮助文件,WebHelp服务器动态生成JavaScript


是解决方案大纲
解决方案SA3看起来赢家。 SA1和SA2失败的原因是:SA1的:虽然XML是一个用于存储数据的最佳候选,我们不能依赖于用户的浏览器代理能够动态解析XML。因此,我们可以做它的服务器端Web帮助和依赖于Internet Explorer的XSL转换编译的说明。这是可能的,也是它之所以失败,R3的。SA2:SA1的一样,这看起来它工作在已编译的帮助,在渲染时,许多用户在其系统上使用ADODB库。而且,WebHelp,我们可以使用类似的呼吁在服务器端呈现适当的标记。但是,这也是为什么SA2未能满足R3的。
即使我们选择去与SA1或SA2,我们仍然是留下了如何从服务器端的HTML静态内容动态生成的内容。无情,这将导致在客户端使用JavaScript的一小块一小块,如果我们要保持任何类型在我们的项目帮助作者和开发之间的分工。
*注:我没有试过SA1或SA2,但XML和MDB两个想法浮现在脑海时,思考可能的解决方案,但R2中所产生的最终问题,这些解决方案,是站不住脚的。他们实际上可能在R1或R3的太失败,但我给他们在这种分析中的疑点利益。作为解决方案的JavaScript对象常量
HTML是互联网用得上,但密切相关的母语是JavaScript。几乎所有的Web浏览器支持一些JavaScript的基本水平,并编排的帮助,不作为,因为它仅仅是一个围绕IE浏览器的控制的大部分包装。客户端实现
JavaScript可以被嵌入到一个HTML文件和编程方式访问页面时加载改变显示的内容是如何。作为程序员,我们需要做的是找到一种方法嵌入到JavaScript的静态HTML页面的HEAD标签,然后进行格式化的HTML渲染数据调用某些功能。服务器端执行
在后端服务器上,它并没有多大意义,我们连接到我们用什么语言或者什么数据库,只要我们有一个JavaScript对象文本的字符串转换成数据的手段。但是,正如这个例子表明,使用JavaScript的客户端和服务器上都具有一定的优势,当谈到数据封送处理和指挥调度。解决方案框架大纲
我们的解决方案框架将包括以下组件:方式来提供客户端的静态数据,如果一个服务器不可用动态生成的数据。一种方法连接到服务器上的数据源,如果它是可用的,获得最新,最先进的数据和静态数据覆盖。一种方法结构的数据,例如,在客户端内容的最终渲染功能,可以访问相同的方式在WebHelp和编译帮助。
密切相关的,所有这些,将各地在适用情况下使用RoboHelp的条件生成标签。
本文的其余部分将解释这是怎样可以用最少的代码编写和高可重用性和可扩展性的实现。数据库连接
在ISC的情况下,我们将研究如何连接到Microsoft Access数据库数据库,创建一个记录集对象使用ADODB的,然后呈现为一个JavaScript对象中的文本将返回给客户端的HTML通过结果脚本标签。在一个类似的真实情况,我连接到​​现有的系统,它使用的SQL Server作为其基础的数据存储业务层。
在你的情况,你可能会使用PHP和MySQL,或PERL和甲骨文的Java和Cloudscape,或完全不同的东西。唯一的部分,必须为您的JavaScript对象字面看起来是一样的,当返回到客户端。我用的,因为MDB文件格式,可以下载并使用其本地计算机上大多数用户轻松访问这里。数据库架构
首先,让我们的定义MDB文件的架构。不幸的是,我没有这样做第一。我在通过接口的访问计划,但我发现一个伟大的小扭转工程师MDB文件生成其基本的DDL。MDB文件的DDL上市1CREATE表"; lookupquot;( "; lookup_idquot;计数器不为NULL, & #160; "categoryquot; LongInteger默认为0, "; lookup_descquot; CHAR(50), PRIMARY KEY quot; lookup_idquot;,"categoryquot;);创建索引"quot;; lookup_IX0quot lookupquot;("categoryquot; ASC);创建索引"quot;; lookup_IX1quot lookupquot;("lookup_idquot; ASC);CREATE UNIQUE INDEX quot; lookup_PKquot; quot; lookupquot;("; lookup_idquot"; ASC,"; categoryquot; ASC); 创建表quot; paramsquot;( & #160; "; ParamIDquot;计数器不为NULL, "; Namequot; CHAR(50), "; Valuequot; CHAR(50),   ;"; Labelquot; CHAR(100) PRIMARY KEY quot; ParamIDquot;,"Namequot;);CREATE UNIQUE INDEX quot; params_PKquot; quot; paramsquot;("; ParamIDquot"; ASC,"; Namequot; ASC);JavaScript对象文本输出数据包
在这一点上的目标是创建一个简单的JavaScript对象中的文本使用的基础数据库中的数据。该格式将看起来像这样:上市2myData = {1 ':[{' lookup_id':'5','lookup_desc":"导演"},{'lookup_id':'2','lookup_desc":"雇员"},{'lookup_id":'1','lookup_desc":"经理"},{'lookup_id':'4','lookup_desc":"总统"},{'lookup_id':'3','lookup_desc":"监"}... ...] myContact = [{"姓名":"ContactNumber","价值":404 - 555 - 5566, "标签":"联络电话"},{'名称':'联系人","价值":"先生经理","标签":"联系人"},{"姓名":"ContactHours","价值":"周一 - 周五8点到下午5点,&# 160; "标签":"接触时间"};
熟悉使用Perl会认为这是一个关联数组关联数组。在VBScript中,它可能是与Scripting.Dictionary对象实施。 Java和。NET程序员,和其他可能仍然认为它是一个Hashtable。在JavaScript中,它只是文字符号的对象。 JavaScript提供了最简洁的语法这些语言的任何。eval函数
在Perl和JavaScript,这样写的简单的字符串(PERL,代替= GT;:)可以在运行时立即vivified由程序员完成的零解析到当前执行的情况下。这是通过调用eval函数。基本上,EVAL尝试执行字符串代码的解释执行的代码块范围内。许多脚本,如脚本这一进程的图像翻转滥用eval函数,但它在脚本中的主要用途应vivify进入发动机的数据结构,在执行过程中,或允许交互式调试,可以在Mozilla扩展。JavaScript的文字符号
有关JavaScript的文字符号的支持,请参阅下节本参考:ASP代码连接到数据库,并生成JavaScript
下面是一个ASP页,将连接到MDB文件的JScript代码,然后翻译查找值和成JavaScript对象常量的联系信息。请注意,在此ASP脚本,我们还依靠文字符号,以实现在服务器端代码一个灵活的指挥调度。我们使用它在整个查询字符串传递的值。在第9行中,我们使用eval函数vivify翻译的执行上下文数据。
类似的指挥调度系统,可以在其他语言,并在Perl几乎相同。即使在编译语言是可能的,但将需要更复杂的数据,在运行时进行解析。在这种情况下,对脚本的力量在于它可以为​​我们做解析的工作,只要我们采取足够的照顾,认为通过任何缺陷,使正确使用这种语言结构作为尝试/捕捉。清单3 / /加载的JavaScript字符串形式的请求cmdSetAsString = Request.Item("cmdSetquot;);VAR cmdSet = [];VAR jsrv ="";VAR的isValid = FALSE;尝试{ 的eval("cmdSet = ["cmdSetAsString quot;] quot;);赶上(E){}如果(cmdSet.length GT; 0) 的isValid = TRUE;(isValid的!= TRUE){ jsrv ="; JS_Evaluator_Error"="无法实例化对象从字符串\ n'quot;  0;回复于(jsrv); ();}/ /执行每个命令(I = 0;我LT; cmdSet.length;我){ 尝试{   ; / /返回值分配给指定的变量 & #160;jsrv = cmdSet [I]。vnam "="。cmdSet [我] FUNC](cmdSet [I] ARG)quot; \ nquot; & #160; jsrv = cmdSet [我] vnam"。_error = FALSE; \ nquot;; } (E){ jsrv = cmdSet [I] vnam"_error = TRUE; \ nquot;; 回复于(e.description); }}回复于(jsrv);/ /页级别的功能函数的getConnection(){ VAR路径,CONN,connStr; 路径= Server.MapPath("; LookupDB.mdbquot";);  ; CONN = Server.CreateObject的("; adodb.connectionquo​​t";); conn.Provider ="Microsoft.Jet.OLEDB.4.0quot;; conn.Open(路径); 返回CONN;}功能GetListValues​​(listIds){ / /创建一个数据库连接 60; VAR CONN = getConnection()的; VAR RV,我; & #160; RV =""; (VAR我= 0;我LT; listIds.length;我) RV ="\ N"quot; listIds [I]"":quot; PackageListAsJS(listIds [I],   ; ["lookup_id","lookup_desc'],CONN); conn.Close(); 删除CONN; 返回quot; {"; rv.substring(2)"} quot;;}功能PackageListAsJS(listId,arFields,CONN){ VAR rsList,RV;  60; rsList = GetLookups(listId CONN); RV = PackageRecordSetAsJS(rsList,arFields); rsList.Close();&# 160; 删除rsList; 返回RV;}PackageRecordSetAsJS(RS,arFields){ RV =""; VAR numFields = arFields.length; (!RS.EOF) VAR行=""; (VAR I = 0;我LT; numFields; I){ VAR的名称,价值; (行="";)行=行quot;,"; 名称= arFields [我]; 值=字符串(RS(名称)值)。 值= value.replace("\ nquot;,quot; \ \ nquot;); 值= value.replace("\ rquot;,quot; \ \ rquot;);  0; 值= value.replace("'","\ \'quot;); 行=""quot; quot名称;":"quot;价值q​​uot;"quot;;  0; } RV ="{"行quot;}"; & #160; rs.MoveNext(); } / /完成的JavaScript对象 "[quot; rv.substring(1)"] quot;;}功能GetLookups(ID,CONN){ VAR SQL ="SELECT *编号;查找WHERE分类= quot &# 160; quot;; lookup_descquot订单; 返回conn.Execute(SQL);}功能GetContactInfo(){ VAR CONN = getConnection()的; VAR SQL ="SELECT *; PARAMS哪里像名'跟%'quot; rsContact = conn.Execute(SQL); RV = PackageRecordSetAsJS(rsContact,["Namequot;,"Valuequot;,"Labelquot;]); rsContact.Close(); conn.Close(); 删除rsContact;   ; 删除CONN; 返回RV;}安全注意事项的最佳实践
请注意,我不检查这里提到的URI,但我可以这样做,以确保最大的安全性。这将允许你以防止浏览的网址,并输入自己的参数。您可能还需要检查可能的SQL注入战术。即使我们只有通过SELECT语句的基础数据库,黑客就可以尝试终止你的发言,然后执行恶意代码。这是脚本的灵活性可以成为一场噩梦,并汇编和强打字成为有益的严酷。然而,即使在一个编译的服务器端解决方案,如JSP或ASP.NET,你可以写一个比较简单的解析器翻译{:,和[到Hashtable和ArrayList的样式对象实例相结合,并检查每个数据类型的有效性,因此,仍然能够提供一个非常灵活的指挥调度系统,底层的命令处理架构松耦合。但是,说明在此演示的基本概念的目的,我们将坚持以客户端和服务器中使用JavaScript。列入WebHelp和动态页面编译帮助
下面是一个HTML文件的代码将同时包含数据的静态版本和动态调用到generatedata.asp。注意以下几点:静态数据是一种输出调用generatedata.asp的本地保存副本。generatedata.asp呼叫标签RoboHelp的X条件的风格,以确保这只是建设WebHelp时呈现。上市4lt; htmlgt;LT; headgt;LT; titlegt;国际工作人员Companylt / titlegt;LT脚本类型= quot;文/ javascriptquot SRC ="DynamicPage_data.js"GT,LT / scriptgt;LT;脚本类型=";文本/ javascriptquot;风格="X -条件:ONLINE_ALLquot;SRC ="; http://localhost/robohelp/generatedata.asp?cmdSet = {vnam:"MYDATA",功能:"GetListValues​​',参数:[1,2,3]}, {vnam:"myContact",功能:"GetContactInfo",参数:NULL} quot; GT,LT / scriptgt;LT脚本类型= quot;文/ javascriptquot SRC ="applicationcontroller.js"GT,LT / scriptgt;LT;脚本类型=";文本/ javascriptquot; GT;<! - VAR MyApp的= 新MyHelpApplicationController( MyHelpApplicationController.DEPLOYMENT_ENUM.PRODUCTION);/ / - GT;LT; / scriptgt;LT;风格类型=";文本/ cssquot; GT;<! - BODY { 字体家庭:宋体;  60; 字体大小:80%;}H3 { 颜色:海军;}李{ 列表样式:光盘;}在FireFox / *工程,但不是IE:李:前{ 内容:"GT"; 字体重量:大胆; 颜色:海军; 字体大小:85%;}* // / - GT;LT; / stylegt;LT;脚本类型=";文本/ javascriptquot; GT;<! - 功能RenderList(ID){ RV ="LT; ulgt; \ nquot;; &# 160; OBJ = MYDATA [ID]; (VAR我在OBJ){ RV ="\"商标法条约"; LIGT; quot; OBJ [我]。lookup_desc quot; 注意,静态数据是不排除从WebHelp,以确保页面始终正确地呈现了一些数据,即使数据不是当前的。呼叫时,generatedata.asp失败由于网络问题,无法访问的数据库,或以其他方式,这将有助于防止用户受挫。事实上,一个更好的解决方案的数据可能不会改变这一切,经常,甚至可能是简单地从调用缓存输出到服务器的文件系统generatedata.asp。这可以让按下一个按钮更新所有数据段或计划任务,定期生成此输出,无需人工干预。这种替代的灵活性是保持各级,但故障点降到最低。用人为资源位置抽象Facade模式在客户端JavaScript
最后,作为食品的思考,并以一个肥皂箱上的立场一旦JavaScript的灵活性,我现在该实施的产生有助于系统内部的一个应用程序控制器对象提供一个门面隐藏的基本路径,以disparately位于想法资源。JavaScript对象的构造函数和原型
在JavaScript中经常被忽视的功能之一是基于原型的对象系统。这是基于类的语言不同,但提供类似的功能和更灵活的运行时。利用这种非常灵活的系统,而是许多脚本写在程序的风格,在顶层的对象声明的变量万吨。一个更好的方式通过构造
通过使用对象的构造函数有一个更好的办法。这样,所有的变量和对象可以包含在一个单一的对象。这里是一个抽象掉资源的物理位置的详细信息,可用于的例子。这使应用程序员专注于简单地命名为适当的资源和​​离开寻找这些资源的控制器实例的详细信息。一个门面,隐藏不同的部署细节
我用在真实的情况,这是我们必须测试在多种环境,包括本地,发展,分期,生产,和微软编译帮助我们的帮助系统。复杂的因素是:这些环境中,每个人都有资源略有不同,不能完全由于不同地点,不同的网络配置,包括安全限制的相对链接的位置。这是不明智的硬编码的位置路径RoboHelp项目的内容。同样,它是不明智的拨打电话到一个数据库,以得到这些位置的路径,因为这不是在编译的说明适用。
最后,在不同的Web服务器上安装了多个可能需要访问外部的帮助系统共享数据,它是良好的建议,找到这些设施的方式来指向共享资源。
RoboHelp的条件生成标签和客户端JavaScript的混合物,通过一个简单的实现Facade设计模式的可行解决方案。上市5 / /应用程序控制器雇用Facade设计模式功能MyHelpApplicationController(deploymentType){   ; this.baseUrl =""; this.init(deploymentType);}/ *构造部署配置选项的级别枚举* /MyHelpApplicationController.DEPLOYMENT_ENUM = { 本地:1, &# 160;发展:2, 3,分期: 生产:4, HOTSITE:5, COMPILED_HELP:6}MyHelpApplicationController.prototype.init =功能(deploymentType){ 开关(deploymentType){ 案件MyHelpApplicationController.DEPLOYMENT_ENUM.LOCAL: this.baseUrl ="C:\ \ \ \ helpsystem \ \ helpoutdirectory \ \ quot;; 打破; 案件MyHelpApplicationController.DEPLOYMENT_ENUM.DEVELOPMENT: & #160; this.baseUrl ="htt​​p://machine-on-intranet/applicationdir/help/quot;;   ; 打破; 案件MyHelpApplicationController.DEPLOYMENT_ENUM.PRODUCTION: this.baseUrl = "http://www.internationalstaffingcompanysiteurl.com/help/quot;; 60; 打破; 案件MyHelpApplicationController.DEPLOYMENT_ENUM.COMPILED_HELP:  0; this.baseUrl ="。/ quot;; & #160; 打破; }}MyHelpApplicationController.prototype.NavigateUrl =功能(URL){ location.href = this.baseUrl URL;MyHelpApplicationController.prototype.GetScriptReference =功能(URL){ 返回"LT""脚本类型="文/ JavaScript的"SRC ="quot; this.baseUrl网址 ""GT""解决方案上面描述的假设是通过标准的HTML创作或从Word文档中的文件导入帮助创作。帮助在许多项目和重复使用现有的内容,这种做法是很常见。一个更好,更灵活的方式在我看来,只有一个可能会或可能不会招致更多的前期改造现有的内容,转换成一个标准的XML架构中的现有内容。在RoboHelp的XML支持提供支持创作语义丰富的帮助内容
HTML是没有语言的语义,特别是当它涉及到创作的帮助内容! XML被设计为允许标签套发展到允许作者表达自己的想法语义,而不是图形化。根据作者提供的语义,然后应用程序的作者写翻译的代码来生成相应的图形表示。这使得原来的语义意图和最终输出格式之间的多对多关系。不幸的是,HTML,有时给人的感觉更像一个为"无"。
RoboHelp支持一个复杂的XML输入选项,允许内容创作者设计帮助系统,具有丰富的语义结构内容,而不是试图以适合不适合的HTML模式帮助和以用户为中心的成语,。 RoboHelp的XML支持通过XML处理程序,使应用程序开发代码的XSLT转换成相应的HTML或任何其他输出的语义帮助架构。
在这种情况下,帮助作者可以写出来的语义丰富的XML应用程序开发人员,然后针对其应用XSLT转换建立的HTML内容。允许帮助作者创建自己的语义和应用程序开发过程中产生输出,XML允许作者和开发人员的生产力和最终提供一个更好的用户体验。
关于在RoboHelp X5的XML支持的更多信息,请参阅相关资源部分。下载及相关资源下载
参见下载页面右侧部分为一个ZIP文件包含一套完整的静态和动态页面的代码清单和工作的例子。它还包含一个完整的RoboHelp X5的项目,生成WebHelp和编译的帮助输出。有一个readme.txt文件,讲解如何使用IIS。链接
写这篇文章时,我遇到了一些很大的联系,是非常有用的。 - 提供当前主题和RoboHelp创作的技巧。 由Justin达利 - 本文介绍了使用新的XML功能在Macromedia RoboHelp X5的理论和实践。&# 160;彼得特雷西 - ADODB Recordset对象的克隆,用JavaScript编写的。 - 模式是最近软件工程解决问题的学科,从面向对象的社会出现。 - 提供了一个统一的接口,一组中的一个子系统的接口。门面定义了一个更高层次的接口,使得子系统更容易使用。这可以用来简化成一个单一的接口的一些复杂的对象交互。

回答

评论会员:西蒙西格尔 时间:2011/12/04
有趣的文章。我目前正在实施一个使用声明性编程技术和XML数据存储的上下文敏感帮助的框架,但发现这当然值得期待的方式。

西蒙西格尔
评论会员:peterchen 时间:2011/12/04
它hurtsssess!

潘多拉礼品#44:希望。一个让你痛苦。
ABER .. "魏圣美gesagt,DER Scheiss Therapie"

评论会员:UV2003 时间:2011/12/04
我道歉。我只在FireFox测试。也出于某种原因,它总是添加C的主题时,我还没有选定的C。