最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

【全部解决】用Docbook生成htmlhelp + 【完全解决】生成的chm中标题和左边的索引目录是乱码的问题

Docbook crifan 6974浏览 0评论

【背景】

已经实现用docbook生成单个和多个HTML了。

但是希望输出的文件是一个完全单个文件,而之前的输出的单个的HTML文件,其图片文件是另外的,不是包含在HTML文件里面的。

所以,就去找这些的东西。

【解决过程】

1.本来是以为完全单个的HTML是xhtml的。

后来发现搞错了,完全单个的HTML是mht类型文件。

2.后来又看到了docbook输出支持htmlhelp文件,即html类型的帮助文件,所以又去折腾用docbook输出为htmlhelp文件。

参考这里:Chapter 25. Other output forms  – HTML Help,新建了个配置文件htmlhelp_crl.xsl:

<?xml version='1.0'?>

<!DOCTYPE stylesheet 
[
<!-- ============== HOME ============== -->
<!-- <!ENTITY xsl_ns_base_cygwin "/cygdrive/e/Dev_Root/docbook/tools/docbook-xsl-ns-1.76.1"> -->

<!-- ============== OFFICE ============== -->
<!ENTITY xsl_ns_base_cygwin "/home/CLi/develop/docbook/tools/docbook-xsl-ns-1.76.1">

]
>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version='1.0'>

<xsl:import href="&xsl_ns_base_cygwin;/htmlhelp/htmlhelp.xsl"/>

<xsl:output 
            encoding="UTF-8"
            indent="no"/>

<xsl:param name="title.font.family">msyhbd</xsl:param>
<xsl:param name="body.font.family">msyh</xsl:param>
<xsl:param name="monospace.font.family">msyh</xsl:param>


</xsl:stylesheet> 

用命令生成htmlhelp:

CLi@PC-CLI-1 ~/develop/docbook/books/VBR/VBR/src
$ XML_CATALOG_FILES="/home/CLi/develop/docbook/config/catalog/catalog.xml" \
>     XML_DEBUG_CATALOG=1 \
>     xsltproc.exe --xinclude -o ../output/htmlhelp/MPEG_VBR.html docbook_htmlhelp_crl.xsl MPEG_VBR.xml
Resolve: sysID docbook_htmlhelp_crl.xsl
-2147483592 Parsing catalog /home/CLi/develop/docbook/config/catalog/catalog.xml
/home/CLi/develop/docbook/config/catalog/catalog.xml added to file hash
Resolve URI docbook_htmlhelp_crl.xsl
Found URI match docbook_htmlhelp_crl.xsl
Resolve: pubID crl.ent sysID null
Found public match crl.ent
Writing pr01s02.html for section
Writing pr01.html for preface(preface)
Writing ch01s02.html for sect1
Writing ch01s03.html for sect1
Writing ch01s04.html for sect1
Writing ch01s05.html for sect1
Writing ch01.html for chapter(ch01_mpeg_related)
Writing ch02s02.html for sect1
Writing ch02s03.html for sect1
Writing ch02s04.html for sect1
Writing ch02s05.html for sect1
Writing ch02s06.html for sect1
Writing ch02s07.html for sect1
Writing ch02s08.html for sect1
Writing ch02.html for chapter(ch02_mp3_term.xml)
Writing ch03s02.html for sect1
Writing ch03s03.html for sect1
Writing ch03.html for chapter(ch03_mpeg_frame.xml)
Writing ch04s02.html for sect1
Writing ch04.html for chapter(ch04_xing_vbri.xml)
Writing ch05s02.html for sect1
Writing ch05s03.html for sect1
Writing ch05.html for chapter(ch05_calc_duration.xml)
Writing ch06s02.html for sect1
Writing ch06s03.html for sect1
Writing ch06s04.html for sect1
Writing ch06.html for chapter(ch06_mp3_related.xml)
Writing ch07.html for chapter(ch07_after_content.xml)
Writing bi01.html for bibliography(reference)
Writing index.html for book
Writing htmlhelp.hhp
Writing toc.hhc
Catalogs cleanup
Free catalog entry crl.ent
Free catalog entry /home/CLi/develop/docbook/tools/docbook-xsl-ns-1.76.1/
Free catalog entry docbook_html.xsl
Free catalog entry docbook_fo.xsl
Free catalog entry /home/CLi/develop/docbook/config/docbook-xsl-ns-1.76.1/
Free catalog entry docbook_html_crl.xsl
Free catalog entry chunk_html_crl.xsl
Free catalog entry docbook_htmlhelp_crl.xsl
Free catalog entry docbook_fo_crl.xsl
Free catalog entry /home/CLi/develop/docbook/config/catalog/catalog.xml
Free catalog entry

2.结果去看生成的文件,是多个零散的文件,所以又按照上面的介绍,去找Microsoft’s HTML Help Workshop,然后找到下载的地方:

Microsoft HTML Help Downloads

HTML Help Workshop and Documentation

结果下载下来的exe被报病毒,所以算了,暂时放弃,等有空再折腾这个吧。

3.后来去将HTML Help Wordshop下载下来,安装,然后再把安装好的路径,加到系统的path环境变量中,这样cygwin和cmd中就都可以直接使用hhc了。

然后就可以去使用hhc了:

Administrator@K470 /cygdrive/e/Dev_Root/docbook/dev/books/VBR/src
$ hhc ../output/htmlhelp/htmlhelp.hhp
Microsoft HTML Help Compiler 4.74.8702

Compiling e:\Dev_Root\docbook\dev\books\VBR\output\htmlhelp\htmlhelp.chm

index.html
pr01.html
pr01s02.html
ch01.html
ch01s02.html
ch01s03.html
ch01s04.html
ch01s05.html
ch02.html
ch02s02.html
ch02s03.html
ch02s04.html
ch02s05.html
ch02s06.html
ch02s07.html
ch02s08.html
ch03.html
ch03s02.html
ch03s03.html
ch04.html
ch04s02.html
ch05.html
ch05s02.html
ch05s03.html
ch06.html
ch06s02.html
ch06s03.html
ch06s04.html
ch07.html
bi01.html
toc.hhc

Compile time: 0 minutes, 0 seconds
60      Topics
364     Local links
16      Internet links
0       Graphics


Created e:\Dev_Root\docbook\dev\books\VBR\output\htmlhelp\htmlhelp.chm, 56,676 bytes
Compression decreased file by 161,663 bytes.

Administrator@K470 /cygdrive/e/Dev_Root/docbook/dev/books/VBR/src

然后去打开生成的htmlhelp.chm,效果还不错:

生成的chm文件的效果

但是文件标题和左边的目录索引部分是乱码,所以要去解决此问题。

4.关于乱码问题,试了很多个参数

 

最后参考别人的帖子:

CHM文件左側選單中文亂碼

chmsee查看文件时乱码

但是最后发现,都解决不了我的问题。

因为我此处生成的hhp文件htmlhelp.hhp本身内容:

[OPTIONS]
Binary TOC=Yes
Compatibility=1.1 or later
Compiled file=MPEG_VBR.chm
Contents file=toc.hhc
Default Window=Main
Default topic=index.html
Display compile progress=Yes
Full-text search=Yes
Language=0x0804 Chinese (CHINA)
Title=MPEG&#31616;&#20171; + &#22914;&#20309;&#35745;&#31639;CBR&#21644;VBR&#30340;MP3&#30340;&#25773;&#25918;&#26102;&#38388;
Enhanced decompilation=No

[WINDOWS]
Main="MPEG&#31616;&#20171; + &#22914;&#20309;&#35745;&#31639;CBR&#21644;VBR&#30340;MP3&#30340;&#25773;&#25918;&#26102;&#38388;","toc.hhc",,"index.html","index.html",,,,,0x2520,,0x603006,,,,,,,,0


[FILES]
index.html
pr01.html
pr01s02.html
ch01.html
ch01s02.html
ch01s03.html
ch01s04.html
ch01s05.html
ch02.html
ch02s02.html
ch02s03.html
ch02s04.html
ch02s05.html
ch02s06.html
ch02s07.html
ch02s08.html
ch03.html
ch03s02.html
ch03s03.html
ch04.html
ch04s02.html
ch05.html
ch05s02.html
ch05s03.html
ch06.html
ch06s02.html
ch06s03.html
ch06s04.html
ch07.html
bi01.html

中,本身已经是中文的Lang,另外title和Main都是“乱码”,即不是中文,而是Unicode形式,所以生成的内容,包括TOC目录和chm标题,都是对应的“乱码”。

另外也去看了TOC文件toc.hhc,其内容也是类似的:

<HTML> <HEAD><meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"></HEAD> <BODY> <OBJECT type="text/site properties"> <param name="ImageType" value="Folder"> </OBJECT> <UL> <LI><OBJECT type="text/sitemap"> <param name="Name" value="MPEG&#31616;&#20171; + &#22914;&#20309;&#35745;&#31639;CBR&#21644;VBR&#30340;MP3&#30340;&#25773;&#25918;&#26102;&#38388;"> <param name="Local" value="index.html"></OBJECT></LI> <UL><LI><OBJECT type="text/sitemap"> <param name="Name" value="&#27491;&#25991;&#20043;&#21069;"> <param name="Local" value="pr01.html"></OBJECT></LI> <UL> <LI><OBJECT type="text/sitemap"> <param name="Name" value="&#22768;&#26126;"> <param name="Local" value="pr01.html#id9224709"></OBJECT></LI> <LI><OBJECT type="text/sitemap"> <param name="Name" value="&#27492;&#25991;&#30446;&#30340;"> <param name="Local" value="pr01s02.html"></OBJECT></LI> </UL><LI><OBJECT type="text/sitemap"> <param name="Name" value="MPEG&#30340;&#30456;&#20851;&#30693;&#35782;"> <param name="Local" value="ch01.html"></OBJECT></LI> <UL>

。。。。

所以,本身hhp和hhc,都是有问题的。

所以还是要继续去找到,为何xsltproc为何输出这种内容,而不是中文汉字,然后再用hhc处理,应该就可以了。

5.后来参考:

编译Zend Framework的手册(4)编译CHM版

找到了那个转换为UTF8的工具:

UTF8转码的PHP

将其内容:

<?php 
function toUtf8($ar) 
{ 
     foreach($ar as $val) 
     { 
        $val = intval(substr($val,2),16); 
        $c = ''; 
         if($val < 0x7F) 
         {        // 0000-007F 
            $c .= chr($val); 
         } 
         elseif($val < 0x800) 
         { // 0080-0800 
            $c .= chr(0xC0 | ($val / 64)); 
            $c .= chr(0x80 | ($val % 64)); 
         } 
         else 
         {                // 0800-FFFF 
            $c .= chr(0xE0 | (($val / 64) / 64)); 
            $c .= chr(0x80 | (($val / 64) % 64)); 
            $c .= chr(0x80 | ($val % 64)); 
         } 
     } 
     return $c; 
} 
function uniDecode($str, $charcode="UTF-8") 
{ 
    $text = preg_replace_callback("/%u[0-9A-Za-z]{4}/", 'toUtf8', $str); 
     return mb_convert_encoding($text, $charcode, 'utf-8'); 
} 

function cp($m) 
{ 
     return iconv('UTF-8', 'GBK', uniDecode('%u' . dechex($m[1])));         
} 

function c($str) 
{ 
     return preg_replace_callback('/&#([0-9]+);/', 'cp', $str); 
} 

if (isset($_GET['fileName'])) 
{ 
    $fileName = $_GET['fileName']; 
} 
else if(isset($argv[1])) 
{ 
    $fileName = $argv[1]; 
} 
else 
{ 
     echo "Usage: In the command line: php scriptName fileName or on the web http://foobar/scriptName.php?fileName=foobar"; 
} 

if (isset($_GET['output'])) 
{ 
    $output = $_GET['output']; 
} 
elseif(isset($argv[2])) 
{ 
    $output = $argv[2]; 
} 
else 
{ 
    $p = pathinfo($fileName); 
    $output = $p['basename']; 
} 

$file = file_get_contents($fileName); 
$file = c($file); 
file_put_contents($output, $file); 
echo 'Success: ' . date('Y-m-d H:i:s', time());

另存为utf8.php,然后又参考:

在Centos 上编译Zend Framework CHM格式手册

先把自己的原先的两个hhp和hhc文件:

htmlhelp.hhp和toc.hhc

放到本地web服务器根目录,然后访问:

http://localhost/utf8.php?fileName=htmlhelp.hhp&output=htmlhelp2.hhp

http://localhost/utf8.php?fileName=toc.hhc&output=toc2.hhc

就可以看到:

Success: 2012-05-09 17:08:30

Success: 2012-05-09 17:08:08

的字样,即生成了新的两个文件:

htmlhelp2.hhp和toc2.hhc

这两个文件,就是转换为UTF8编码之后的文件了。

效果如下:

htmlhelp2.hhp:

[OPTIONS]
Binary TOC=Yes
Compatibility=1.1 or later
Compiled file=MPEG_VBR.chm
Contents file=toc.hhc
Default Window=Main
Default topic=index.html
Display compile progress=Yes
Full-text search=Yes
Language=0x0804 Chinese (CHINA)
Title=MPEG简介 + 如何计算CBR和VBR的MP3的播放时间
Enhanced decompilation=No

[WINDOWS]
Main="MPEG简介 + 如何计算CBR和VBR的MP3的播放时间","toc.hhc",,"index.html","index.html",,,,,0x2520,,0x603006,,,,,,,,0


[FILES]
。。。。。

toc2.hhc:

<HTML>
<HEAD><meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"></HEAD>
<BODY>
<OBJECT type="text/site properties">
<param name="ImageType" value="Folder">
</OBJECT>
<UL>
<LI><OBJECT type="text/sitemap">
<param name="Name" value="MPEG简介 + 如何计算CBR和VBR的MP3的播放时间">
<param name="Local" value="index.html"></OBJECT></LI>
<UL><LI><OBJECT type="text/sitemap">
<param name="Name" value="正文之前">
<param name="Local" value="pr01.html"></OBJECT></LI>
<UL>
<LI><OBJECT type="text/sitemap">
<param name="Name" value="声明">
<param name="Local" value="pr01.html#id9224709"></OBJECT></LI>
<LI><OBJECT type="text/sitemap">
<param name="Name" value="此文目的">
<param name="Local" value="pr01s02.html"></OBJECT></LI>
</UL><LI><OBJECT type="text/sitemap">
<param name="Name" value="MPEG的相关知识">
<param name="Local" value="ch01.html"></OBJECT></LI>
<UL>
<LI><OBJECT type="text/sitemap">
。。。。

然后将他们替换掉原先的两个“乱码”的htmlhelp.hhp和toc.hhc,再去重新生成对应的chm:

hhc ../output/htmlhelp/htmlhelp.hhp

最后就可以解决乱码问题了,生成的chm文件,左边的TOC索引目录和标题,都是可以正常显示中文了:

chm的左边索引和标题可以显示中文了

【总结】

想要生成htmllhelp不难,但是想要解决所生成的中文的chm中的标题,和左边的索引目录是乱码的问题,倒是比较麻烦。需要利用到别人写的将hhp和hhc转换为UTF8编码,然后重新生成的chm,才能解决乱码问题。

有空,还是需要改进此办法,让其用起来更简单点。

比如通过本地php执行对应转码工具

(可以参考这里:如何正确的编译 Zend Framework 手册的 chm 版本

,实现对应功能。或者自己去写对应的python脚本或exe文件,实现对应转码功能。然后命令行中就可以用了。

【后记】

之前折腾过程中,就发现了,对于htmlhelp_crl.xsl中,不能在配置htmlhelp.title等参数的时候,设置中文汉字,否则会导致该xsl后续参数无法正确识别,也就导致后面参数实际没有生效。所以之前设置的一些参数,包括:

<xsl:param name="htmlhelp.encoding">UTF-8</xsl:param>

<xsl:param name="chunker.output.encoding">UTF-8</xsl:param>

都没有生效。

现在无意间继续折腾的结果是,其实同时设置这两个参数,此时生成出来的htmlhelp.hhp和toc.hhc,都是可以正确显示中文的,但是却都是UTF-8(的无BOM)编码,此时用hhc执行的话,会出现:

HHC5003: Error: Compilation failed while compiling toc.hhc".

的错误。然后通过Notepad++,将两个文件转换为ANSI(即本地的中文)编码后,此时再去用:

hhc ../output/htmlhelp/htmlhelp.hhp

就可以正确输出chm文档了。然后所有的标题和索引目录,也都是正常的了。

【总结2】

目前对于解决:

docbook生成的htmlhelp后,最终生成的chm中标题和索引目录是乱码

的最简单的方法是:

1 . 在xsl配置文件htmlhelp_crl.xsl中配置htmlhelp.encoding和chunker.output.encoding都为UTF-8:

<xsl:param name="htmlhelp.encoding">UTF-8</xsl:param>
<xsl:param name="chunker.output.encoding">UTF-8</xsl:param>

这样再用xsltproc处理:

XML_CATALOG_FILES="/cygdrive/e/Dev_Root/docbook/dev/config/catalog/catalog.xml" \
    XML_DEBUG_CATALOG=1 \
    xsltproc.exe --xinclude -o ../output/htmlhelp/MPEG_VBR.html docbook_htmlhelp_crl.xsl MPEG_VBR.xml

所生成的htmlhelp.hhp和toc.hhc就都是UTF-8的编码了,两个文件中的中文,也就都可以正确显示了。

2. 但是由于hhc不能识别UTF-8,所以要通过Notepad++等工具,将htmlhelp.hhp和toc.hhc转换为ANSI编码

3.然后再用hhc处理:

hhc ../output/htmlhelp/htmlhelp.hhp

此时输出的chm中,所有的中文,包括标题,索引目录等,就都可以正常显示了。

【后记2】

后来又添加了相关参数:

<xsl:param name="section.autolabel" select="1"/>
<xsl:param name="section.label.includes.component.label" select="1"/>
<xsl:param name="bibliography.numbered" select="1"/>

使得生成的html中各个章节的编号都全部带编号,然后对应生成的chm中的索引部分,也就都带编号了,达到了最终想要的效果:

chm中也全部都有索引编号了

【后记3】

对于之前用Notepad++将两个文件,htmlhelp.hhp和toc.hhc,从原先的UTF-8转换为本地ANSI编码,对此,还是需要手动去一个个操作,很是不方便。所以,又去折腾了下,找到了Cygwin/Linux下面有没有对应的工具可以实现编码转换的,然后就找到了iconv这个工具。

简单说,iconv,是个Linux/Cygwin下的命令行工具,可以实现对应的编码转换。详细解释可以去看:iconv 中文wiki

其对应的库,是libiconv,Linux下安装其他软件的时候,往往也会需要此库的。

iconv的用法,还是很简单的,假设当前文件是UTF-8编码的utf8.txt,想要将其转换为本地ANSI编码GB18030,对应命令为:

$ iconv -f UTF-8 -t GB18030 utf8.txt > converted_gb18030.txt

另外,多说几句:

去用iconv -l去查看当前支持的哪些编码,可以看到很多我们所常见的编码:

$ iconv -l
...
UTF-8
...
UTF-16
UTF-16BE
UTF-16LE
UTF-32
UTF-32BE
UTF-32LE
...
UCS-2-INTERNAL
UCS-2-SWAPPED
UCS-4-INTERNAL
UCS-4-SWAPPED
...
CP819 IBM819 ISO-8859-1 ISO-IR-100 ISO8859-1 ISO_8859-1 ISO_8859-1:1987 L1 LATIN1 CSISOLATIN1
...
CP1250 MS-EE WINDOWS-1250
CP1251 MS-CYRL WINDOWS-1251
CP1252 MS-ANSI WINDOWS-1252
CP1253 MS-GREEK WINDOWS-1253
...
GBK
CP936 MS936 WINDOWS-936
GB18030
...
BIG-5 BIG-FIVE BIG5 BIGFIVE CN-BIG5 CSBIG5
CP950
...

更多详细的解释,可以去看:iconv(1) – Linux man page

【总结3】

所以,现在可以用更简单的办法例如:

1 . 在xsl配置文件htmlhelp_crl.xsl中配置htmlhelp.encoding和chunker.output.encoding都为UTF-8:

<xsl:param name="htmlhelp.encoding">UTF-8</xsl:param>
<xsl:param name="chunker.output.encoding">UTF-8</xsl:param>

这样再用xsltproc处理:

XML_CATALOG_FILES="/cygdrive/e/Dev_Root/docbook/dev/config/catalog/catalog.xml" \
    XML_DEBUG_CATALOG=1 \
    xsltproc.exe --xinclude -o ../output/htmlhelp/MPEG_VBR.html docbook_htmlhelp_crl.xsl MPEG_VBR.xml

所生成的htmlhelp.hhp和toc.hhc就都是UTF-8的编码了,两个文件中的中文,也就都可以正确显示了。

2. 但是由于hhc不能识别UTF-8编码,所以要将htmlhelp.hhp和toc.hhc转换为本地ANSI的GB18030编码

iconv -f UTF-8 -t GB18030 < ../output/htmlhelp/htmlhelp.hhp > ../output/htmlhelp/htmlhelp_gb18030.hhp
mv ../output/htmlhelp/htmlhelp_gb18030.hhp ../output/htmlhelp/htmlhelp.hhp

iconv -f UTF-8 -t GB18030 < ../output/htmlhelp/toc.hhc > ../output/htmlhelp/toc_gb18030.hhc
mv ../output/htmlhelp/toc_gb18030.hhc ../output/htmlhelp/toc.hhc

3.然后再用hhc处理:

hhc ../output/htmlhelp/htmlhelp.hhp

此时输出的chm中,所有的中文,包括标题,索引目录等,就都可以正常显示了。

转载请注明:在路上 » 【全部解决】用Docbook生成htmlhelp + 【完全解决】生成的chm中标题和左边的索引目录是乱码的问题

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

网友最新评论 (1)

  1. 其实不用这么折腾的, hhc、hhk、hhp和html文件都用“GB2312”编码,就可以解决乱码、索引搜索无效问题
    楠德一见8年前 (2017-06-17)回复
85 queries in 0.199 seconds, using 22.14MB memory