Delphi 如何操作HHK文件?

cyradg2008 2014-01-20 05:33:03
HHK文件时CHM帮助的索引文件,大致格式如下:
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<HTML>
<HEAD>
<meta name="GENERATOR" content="Microsoft® HTML Help Workshop 4.1">
<!-- Sitemap 1.0 -->
</HEAD><BODY>
<UL>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Abandon">
<param name="Name" value="ASP Abandon 方法">
<param name="Local" value="met_abandon.asp.htm">
</OBJECT>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Abs">
<param name="Name" value="VBScript Abs 函数">
<param name="Local" value="vbscript\func_abs.asp.htm">
</OBJECT>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="AbsolutePage">
<param name="Name" value="ADO Recordset 对象">
<param name="Local" value="ado\ado_ref_recordset.asp.htm">
</OBJECT>
</UL>
</BODY></HTML>

由于我有一堆的索引需要建立,我只知道索引名和对应的HTML文档,在HTML Help WorkShop里面一个个加进去实在太慢,想用Delphi批量生成,请问Delphi如何操作类似的内容?用XML试过,报一堆的错误,显然用XML无法操作。
...全文
243 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
cyradg2008 2014-01-23
  • 打赏
  • 举报
回复
最后感谢各位,对于类似<param name="Name" value="Year">,取出引号之间的内容就简单了,"是个字符,所以可以直接正则:"[^"]*"即可分段取出。
cyradg2008 2014-01-23
  • 打赏
  • 举报
回复
想了个折中方案,就是把<LI>全部枚举出来并记录offset,这个简单,而且不会stack overflow,然后再根据offset来拷贝出相应的每个<LI>段,这样可能效率低点,但还能接受。
Frank6600 2014-01-22
  • 打赏
  • 举报
回复
写错了,是<[^>]+>
cyradg2008 2014-01-22
  • 打赏
  • 举报
回复
引用 16 楼 frank_lee_cn 的回复:
老兄,不要完全用正则嘛。 正则虽好,OO框架也不错。 用正则取出你想要取的内容, 用OO的机制来处理才对。 你用 Matchs('<[^>+]>')取得一个MatchCollection 即每一行是一个 <.........> 用for取出MatchCollection每一行内容, 再用正则做后续判断,根据判断结果调用不同的类方法。 这样子会吧? 个人觉得这么做简单些。 你试试?
TPerlRegEx使用<[^>+]>做正则表达式匹配失败,没有任何结果。TPerlRegEx使用((?!不需要的字符串)[\w\W])*做正则表达式,是可以匹配出其中一段的,例如<LI>aaa</LI><LI>bbb</LI>,如果用正则<LI>([\w\W]*)</LI>(实际上也可以用<LI>(.*)</LI>,也可以,但是那个点.实在不稳定,有些环境失效,搞不懂),匹配出来的是<LI>aaa</LI><LI>bbb</LI>,即全部,用正则<LI>((?!<LI>)[\w\W])*</LI>(此处用点代替[\w\W]无法匹配)可以匹配第一段,即<LI>aaa</LI>,然后可以继续匹配第二段<LI>bbb</LI>。 不过非常悲催,((?!不需要的字符串)[\w\W])*做正则表达式经常会引起stack overflow 错误,而且无法调试,在工程的属性里把Max stacksize改成最大以后有缓解,但是今天我操作时还是碰到了stack overflow,据说这是内存堆栈引起的错误。 由于<param name=之类的太多了,所以我觉得还是先把<LI>分段,目前stack overflow没有很好解决,或者说:匹配一段字符,但是其中又不包含某段字符的正则表达式我没写正确。
pathletboy 2014-01-21
  • 打赏
  • 举报
回复
<param name="Name" value="(.*)">\r\n<param name="Name" value="(.*)">\r\n<param name="Local" value="(.*)">


cyradg2008 2014-01-21
  • 打赏
  • 举报
回复
用了([\n.]*)来匹配包含换行在内的所有字符,输出只有一个换行,其他全部消失,搞不懂。
cyradg2008 2014-01-21
  • 打赏
  • 举报
回复
正则表达式我的想法如下: 1、先把<HTML></HTML>之间的内容先匹配出来 2、再把<BODY></BODY>之间的内容匹配出来 3、再把<UL></UL>之间的内容匹配 4、再逐个匹配<OBJECT></OBJECT>之间内容,得到具体的索引信息。 目前问题是TPerlRegEx如何匹配例如像<HMTL></HTML>之间任何多行的内容?正则表达式如何书写?
cyradg2008 2014-01-21
  • 打赏
  • 举报
回复
正在考虑正则表达式,使用了TPerlRegEx,但是不知道TPerlRegEx只能处理单行文本,多行本之会处理第一行,其他行全部消失了,是什么原因?例如文本如下: a b 注意是两行,TPerlRegEx的正则表达式为(.*),为全部,输出结果只有a,其他行全部消失。
pathletboy 2014-01-21
  • 打赏
  • 举报
回复
引用 9 楼 cyradg2008 的回复:
5楼兄弟,你那样只是限定了一个链接,事实上,HHK可以允许一个关键字对应几个链接,格式如下:
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="ActiveConnection">
<param name="Name" value="ADO ActiveConnection 属性">
<param name="Local" value="ado\prop_comm_activeconn.asp.htm">
<param name="Name" value="ADO Record 对象">
<param name="Local" value="ado\ado_ref_record.asp.htm">
<param name="Name" value="ADO Recordset 对象">
<param name="Local" value="ado\ado_ref_recordset.asp.htm">
</OBJECT>
你那个方法会漏信息。
另外,我用的是Delphi,TPerlRegEx类好像无法实现你那种效果

我只抛砖引玉,根据你顶楼数据给出的表达式,要会变通,自己根据你的实际情况变化。

(<param name="Name" value="(.*)">\r\n)+<param name="Local" value="(.*)">


Frank6600 2014-01-21
  • 打赏
  • 举报
回复
老兄,不要完全用正则嘛。 正则虽好,OO框架也不错。 用正则取出你想要取的内容, 用OO的机制来处理才对。 你用 Matchs('<[^>+]>')取得一个MatchCollection 即每一行是一个 <.........> 用for取出MatchCollection每一行内容, 再用正则做后续判断,根据判断结果调用不同的类方法。 这样子会吧? 个人觉得这么做简单些。 你试试?
cyradg2008 2014-01-21
  • 打赏
  • 举报
回复
晕哦,TPerlRegEx使用正则表达式<[lL][iI]>((?!<[lL][iI]>)[\w\W])*</[oO][bB][jJ][eE][cC][tT]>解析以下内容居然崩溃 <LI> <OBJECT type="text/sitemap"> <param name="Name" value="ActiveConnection"> <param name="Name" value="ADO ActiveConnection 属性"> <param name="Local" value="ado\prop_comm_activeconn.asp.htm"> <param name="Name" value="ADO Record 对象"> <param name="Local" value="ado\ado_ref_record.asp.htm"> <param name="Name" value="ADO Recordset 对象"> <param name="Local" value="ado\ado_ref_recordset.asp.htm"> </OBJECT> 哎,不知道什么原因会崩溃,perl的正则规律搞不懂。
cyradg2008 2014-01-21
  • 打赏
  • 举报
回复
找打了一个例子,移植成功:<[lL][iI]>((?!<[lL][iI]>)[\w\W])*</[oO][bB][jJ][eE][cC][tT]>,多亏原始表达式解释清楚,原始表达式为((?!字符串).)*,(?!字符串)表示不包含字符串,.表示除\n以外的任何字符,由于我的TPerlRegEx对.的实际效果我自己也糊涂了,无规律可言,经常不起作用,所以改成[\w\W],居然可以,这样可用通过TPerlRegEx的Match,MatchAgain不断的一个个枚举。(此时GroupCout还是为1,搞不懂)。
cyradg2008 2014-01-21
  • 打赏
  • 举报
回复
楼上能指点一二吗?我在<OBJECT>....</OBJECT>无法匹配了,因为有多个重复的,一匹配就是一片,GroupCount为1,无法得到实际数目。这一片<OBJECT>内容最多,回到TString方式用正则就没意义了。
Frank6600 2014-01-21
  • 打赏
  • 举报
回复
这种情况我喜欢写状态机。 也可以用正则代替状态机: 用正则取出所有的 <....> 然后Loop每个 <....> 再用正则取出 <TagName , ParaName="ValueName" 针对相应的状况,调用相关的Event, 在Event里面做相关的处理。
cyradg2008 2014-01-21
  • 打赏
  • 举报
回复
可能标题我没说清楚,呵呵,因为一个CHM文件的索引要经常变(增加),一加就是一批,HTML WORKSHOP不支持批量增加的方式,一个个加要累死人,所以想自己做个,因为很多网页的名称和内容比较有规律,可以自己做一些批量处理。
cyradg2008 2014-01-21
  • 打赏
  • 举报
回复
8楼的兄弟,我不是仅仅保存那么简单,其实这个主题我也没问如何保存,保存就是照搬格式而已,如何读取才是关键,我问的也是如何读取,用TString一个个if then ,不如正则格式来的快,保存我是会使用TString的。
cyradg2008 2014-01-21
  • 打赏
  • 举报
回复
5楼兄弟,你那样只是限定了一个链接,事实上,HHK可以允许一个关键字对应几个链接,格式如下: <LI> <OBJECT type="text/sitemap"> <param name="Name" value="ActiveConnection"> <param name="Name" value="ADO ActiveConnection 属性"> <param name="Local" value="ado\prop_comm_activeconn.asp.htm"> <param name="Name" value="ADO Record 对象"> <param name="Local" value="ado\ado_ref_record.asp.htm"> <param name="Name" value="ADO Recordset 对象"> <param name="Local" value="ado\ado_ref_recordset.asp.htm"> </OBJECT> 你那个方法会漏信息。 另外,我用的是Delphi,TPerlRegEx类好像无法实现你那种效果
Frank6600 2014-01-21
  • 打赏
  • 举报
回复
不明白你为什么用正则那么麻烦! 你的目的是根据你知道的索引名和对应的HTML文档位置,生成HHK文件,不是吗? 用一个简单类,对TStringList增加内容, 最后保存到*.HHK,不是OK了吗? 如果你还要问,对TStringList增加什么内容? 当然是一行一行地增加你贴的那些HTML。 明白?
cyradg2008 2014-01-21
  • 打赏
  • 举报
回复
逐个匹配出<LI>项目实际上变成了匹配以<LI>开头,</OBJECT>结尾之间的所有内容,但是这段内容之间不能再出现<LI>字符串。目前我只知道[^<LI>]表示不能出现<、L、I、>四个之中的任意一个字符,可惜的不是字符串,如何满足不能连续出现<LI>四个字符的正则表达式?
cyradg2008 2014-01-21
  • 打赏
  • 举报
回复
我手头上的TPerlRegEx使用([\w\W]*)正则表达式表示匹配所有字符,包括中文和换行,这样使用:<[hH][tT][mM][lL]>([\w\W]*)</[hH][tT][mM][lL]>就可以匹配出<HTML>...</HTML>之间的所有内容,但是问题又来了,由于<LI>项目是多个,例如: <LI> <OBJECT type="text/sitemap"> <param name="Name" value="AbsolutePosition"> <param name="Name" value="ADO Recordset 对象"> <param name="Local" value="ado\ado_ref_recordset.asp.htm"> </OBJECT> <LI> <OBJECT type="text/sitemap"> <param name="Name" value="ActiveCommand"> <param name="Name" value="ADO Recordset 对象"> <param name="Local" value="ado\ado_ref_recordset.asp.htm"> </OBJECT> 如果是用正则表达式<LI>([\w\W]*)</OBJECT>,会把两个LI都匹配出来,如果我想匹配第一个<LI>,第二个不匹配,即后续用MatchAgin一个个匹配出来,如何实现?网上找到了一个:<[lL][iI]>((.(?!<[lL][iI]>))*.)</[oO][bB][jJ][eE][cC][tT]>,意思是匹配<LI>和</OBJECT>之间不再出现<LI>字符串的字符串,这样,第二个<LI>就会丢弃,因为不符合匹配原则,不过比较悲催,这个正则表达式还是不支持换行,事实上,一旦出现换行,没有任何可以匹配,怎么换行这么啰嗦?
加载更多回复(1)

16,748

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 语言基础/算法/系统设计
社区管理员
  • 语言基础/算法/系统设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧