注册
登录
《汉文博士》允许使用者自己编写词典文件。本文简要讲述了词典编译过程和相关配置文件的编写方法。
《汉文博士》的词典编译器可在“文件”菜单中点击“词典编译器”调出。
编译前,需点击“加载”按钮指定配置文件。选定配置文件后,将自动填写输出位置。点击编译按钮后,将编译词典,并自动注册到程序的词典库,供后续检索。

词典编译配置文件是一个XML文件,程序使用配置文件中定义的正则表达式处理指定的文本文件,将文本内容转换词典内容。
提示:程序下载空间的词典源文件目录下,有大量的示例可供参考。
编译配置文件至少应包含如下几类信息:
除了上面必备的信息之外,编译配置文件还支持如下高级特性:
下文以《本草害利》为例,讲解词典的编译制作方法。源文件可在程序下载空间的词典数据库→词典源文件→本草害利目录下载。为方便起见,源文件被压缩成一个7zip文件包,下载后请将文件解压出来,然后在编译器中选择其中的“本草害利.xml”进行编译。
《本草害利》是清代凌奂编著的一部本草医书,书中收录了约三百种中药材,作者基于用药如用兵的思路,按脏腑和效能归类,划分成类似“心部药队〔补心猛将〕”、“肺部药队〔温肺猛将〕”等分类,并逐一讲解各药材的“害”、“利”和“修治”。在本示例中,我们将药材名称作为词头。例如中药材“五味子”的检索结果如下图所示:

源文件开头的部分内容大致如下图所示(未换行,已隐藏长行后面的文本)。

为了编译成词典,我们对原始文件作过一些编辑。例如:
再观察一下文件,由于药材部队出现在药材名称之前,也就是词条标记“★”之前,因此,出现在“★北五味”前面的“心部药队〔补心猛将〕”将无法作为释义写入“北五味”词条,而出现在“★酸枣仁”前的“心部药队〔补心猛将〕”,将成为“北五味”的内容。虽然在这里没关系,因为内容是一样的,“北五味”也缺少药材部队的内容,但到后面切换药材部队的时候,就会错位,造成内容错误。为了补救,我们将根据“药队〔”先忽略掉这里出现的药材部队,另外再使用一个名叫“BowPad”的文本编辑器,通过正则表达式,提取出药材部队和药材的关系,制作了一个名为“本草害利目录.txt”的文件,内容大致如下所示,每行一种药材和药材部队的关系,中间用制表符分隔。编译时,我们将这个文件的内容放在前面先编译,而正文文件的内容放在后面编译,就能得到开头检索结果的效果。
北五味、五味子 心部药队〔补心猛将〕
酸枣仁 心部药队〔补心猛将〕
柏子仁 心部药队〔补心猛将〕
远志肉、远志 心部药队〔补心猛将〕
丹参 心部药队〔补心猛将〕
下面是编译配置文件:
<?xml version="1.0" encoding="gbk"?> <config title="本草害利" author="清·凌奂"> <fields> <field name="category" cssClass="categoryTitle" description="部队" fieldNameVisible="no" mergeAdjacentField="true" adjacentFieldDelimiter="、"/> <field name="content" description="内容" valueType="标记" fieldNameVisible="no" fullText="yes"> <replace pattern="\[([^\]]+)\]\(([^\)]+)\)"> <replacement><![CDATA[<ref q="$2" title="$2">$1</ref>]]></replacement> </replace> <replace pattern="\[([^\]]+)\]" replacement="<ref>$1</ref>"/> <replace pattern="〔.+〕" replacement="<b>$0</b>"/> </field> </fields> <data file="本草害利目录.txt" encoding="GBK" synonymDelimiter="、"> <column field="1"/> </data> <data file="本草害利.txt" encoding="utf-8" synonymDelimiter="、" allowEmptyLine="true"> <word pattern="^★" removePattern="true"/> <row field="2"> <ignore pattern="药队〔" useRegex="false"/> <ignore pattern="(见" useRegex="false" /> <ignore pattern="(同上" useRegex="false" /> </row> </data> </config>
“config”元素中出现的“title”和“author”属性分别表示词典的名称和作者。这些将会显示在检索结果窗口上。
“fields”元素下的“field”元素指定了两个字段。第一个字段将用来显示药材部队,第二个字段用于显示“害”、“利”、“修治”等正文。
第一个字段的代码如下:
<field name="category" cssClass="categoryTitle" description="部队" fieldNameVisible="no" mergeAdjacentField="true" adjacentFieldDelimiter="、"/>
从检索结果窗口可以明显看出,两个字段的显示效果是不一样的。原因是第一个“name="category"”的字段具有“cssClass="categoryTitle"”属性,表示使用类名为“categoryTitle”CSS样式。可以使用的样式,是在程序目录的style.css文件中定义的。程序默认会将字段描述名称(这里是“部队”)显示到检索结果,指定“fieldNameVisible="no"”可以隐藏字段名称。
由于一种药材可能同属于多个药材部队,例如“北五味、五味子”在上面的目录文件中一共出现了三次,因此,需要程序把它们串起来。我们可在配置中指定“mergeAdjacentField="true"”将相邻的相同字段结果串连起来,另外再指定“adjacentFieldDelimiter="、"”,使用逗号将内容分隔开。这样,就得到了开头截图里几个药材部队串连在一起的效果了。
第二个字段的内容较多,代码如下:
<field name="content" description="内容" valueType="标记" fieldNameVisible="no" fullText="yes"> <replace pattern="\[([^\]]+)\]\(([^\)]+)\)"> <replacement><![CDATA[<ref q="$2" title="$2">$1</ref>]]></replacement> </replace> <replace pattern="\[([^\]]+)\]" replacement="<ref>$1</ref>"/> <replace pattern="〔.+〕" replacement="<b>$0</b>"/> </field>
“valueType="标记"”属性表示这个字段的内容是HTML标记(如果不加这个属性,所有内容就会被视为纯文本,也就不会有跳转连接)。
“replace”元素指定了在显示检索结果之前对字段内容的替换操作。“pattern”属性的值是正则表达式,用于匹配文本,而“replacement”属性或元素的内容则表示替代的内容。其中“$1”、“$2”之类的标记表示正则表达式捕获的分组内容。
第一组替换表达式“\[([^\]]+)\]\(([^\)]+)\)”表示替换类似于前文提到的“同[归](当归)[地](地黄)补血”模式。“[归](当归)”将被替换成“<ref q="当归" title="当归">归</ref>”。“ref”元素在程序中有特别的含义,表示词条连接。其中“q”属性表示要检索的词条,“title”属性就是鼠标移上连接所显示的提示文字,“ref”元素的文本就是连接的内容。由于本组替换内容比较复杂,因此我们把它放在一个CDATA节中,避免为替换目标的引号和尖括号编写不直观的实体引用。
第二组替换表达式“\[([^\]]+)\]”表示替换类似于前文提到的“[干姜]”的模式。“[干姜]”将被替换成“<ref>干姜</ref>”。由于要检索的内容和要显示的内容是一样的,所以就不需要“q”属性了。
在安排替换顺序时,要注意先后,必须先替换掉方括号加圆括号的模式,再替换仅有方括号的模式,如果反过来,“[归](当归)”就会被“\[([^\]]+)\]”模式对应的替换组替换成“<ref>归</ref>(当归)”,而“\[([^\]]+)\]\(([^\)]+)\)”就得不到替换文本的机会了。
第三组替换表达式“〔.+〕”表示将“〔害〕”、“〔利〕”和“〔修治〕之类的内容替换成粗体。
字段元素后出现的“data”元素代表词典数据源文件。源文件是文本文件,一般有列布局和行布局。
第一个源文件对应的配置代码如下:
<data file="本草害利目录.txt" encoding="GBK" synonymDelimiter="、"> <column field="1"/> </data>
“encoding”表示该文本文件的文本编码,要注意必须与“file”属性对应文件的编码保持一致,否则就会无法读取。
“synonymDelimiter="、"”指定了词头的同义词分隔符。
注意“data”元素下出现的“column”子元素。这个元素表示这个文档是列布局(按制表符分列),其中第1列隐含表示词头,各个“column”元素表示后面的列,将对应字段内容。因此,这个“column”元素对应第二列,对应的“field="1"”属性表示该列对应前面定义的第1个“field”元素对应的字段(即药材部队)内容。
在本示例中,文件只有两列(大致如下所示),第一列对应的是词头,在“synonymDelimiter="、"”的作用下,诸如“北五味、五味子”的词头被拆分成“北五味”和“五味子”两个词头。第二列“心部药队〔补心猛将〕”对应药材部队字段。
| 北五味、五味子 | 心部药队〔补心猛将〕 |
| 酸枣仁 | 心部药队〔补心猛将〕 |
| 柏子仁 | 心部药队〔补心猛将〕 |
第二个源文件的代码如下:
<data file="本草害利.txt" encoding="utf-8" synonymDelimiter="、" allowEmptyLine="true"> <word pattern="^★" removePattern="true"/> <row field="2"> <ignore pattern="药队〔" useRegex="false"/> <ignore pattern="(见" useRegex="false" /> <ignore pattern="(同上" useRegex="false" /> </row> </data>
由于源文件有大量的空行。按程序的默认设置,空行被作为词条内容的结束标记,而本实例的文件并非如此。因此,我们可以指定“allowEmptyLine="true"”,允许空行出现在词条内容之中。编译器在编译时就会自动将空行忽略掉。
这里出现的“word”元素表示词头,“row”元素表示除词头外用于识别各行对应哪个字段的规则。
“word”元素的“pattern”属性表示行首以五角星开头的行被识别为词头。
由于五角星在这里已经被用来识别词头了,而它实际上并不是词条文本,只是我们为方便程序编译器识别词头而加的标记,因此要把它删掉。removePattern="true"属性,就表示删掉匹配“pattern”属性的内容,这样,行首的五角星就不会出现在词头了。
由于这个“data”元素也有一个“synonymDelimiter="、"”属性,因此,顿号也被用来分隔词头。
“row”元素的“field="2"”属性表示这个元素为第二个字段,即前面定义的“内容”字段定义规则。
由于文档中只有正文内容,没有其它内容了,所以不需要筛选。如果一个文档里有多个字段,可以在“row”元素里指定“pattern”属性,使用正则表达式匹配字段。
三个“ignore”元素在这里表示忽略匹配“pattern”属性内容的行,“useRegex="false"”属性表示“pattern”属性是普通文本,不是正则表达式。如果源文件某一行文本的内容包含这里三个“pattern”中的一个,都会被忽略。
在一个“row”元素内,也可以指定“replace”元素,在写入词典之前替换掉一些内容。
本文讲解了词典编译的工具和配置文件的常见元素和属性设置,并以《本草害利》为例讲解了词典编译配置文件的编写方法。本文讲解的编译配置只是较基础的部分,还有更多的功能将在后续的文章讲解。
词典源文件的示例可在下载区下载 (访问密码: 8518)
从上述设计也可见,《汉文博士》的词典编译器支持多种文本文件布局,比较灵活。字段的概念为建构词典逻辑内容提供了方便。独特的运行时文本替换机制,使得词典源文件可以做得比较简洁,无需嵌入大量标签,也减小了词典文件的空间占用。而程序简繁异体通查和同义词机制便于词条检索,也使词典制作人员可以更专注于创作优质内容,不会被词典程序的功能限制所困扰。