使用FOP转换Docbook到PDF时遇到的错误及解决 (一)

本文记录了我在配置使用Apache FOP时遇到的错误以及解决方法。一方面是做个记录,将来再遇到此类问题时可以查询;另一方面也希望对其它遇到同样问题的人有所帮助。

  1. 问题:fo:inline错误

    解决

    转换vim使用进阶到PDF时,遇到了下面这样一个问题(完整错误信息见fo:inline错误):

    javax.xml.transform.TransformerException: org.apache.fop.fo.ValidationException: file:/home/easwy/tmp/advancedvim/pdf/vim_advanced_usage.fo:173:59: Error(173/59): fo:inline is not a valid child element of fo:flow.
    	at org.apache.fop.cli.InputHandler.transformTo(InputHandler.java:168)
    	at org.apache.fop.cli.InputHandler.renderTo(InputHandler.java:115)
    	at org.apache.fop.cli.Main.startFOP(Main.java:166)
    	at org.apache.fop.cli.Main.main(Main.java:197)
          

    看错误提示,是说fo:inline不是fo:flow元素的有效子结点。在网上搜了一下没找到有用的信息。仔细检查出错的位置,终于发现错误的原因,错误出在下面这个语句:

    
    <emphasis role='bold'> [文件浏览] </emphasis>
    <para>
      ...
    </para>
     

    在上面的emphasis元素是一个inline元素,对于这种inline元素来讲,一定要包含在某个块元素中。而上面的语句中,emphasis不属于任何一个para,所以出现上述错误。

    把上面的语句改成下面的形式,错误消除:

    
    <para><emphasis role='bold'> [文件浏览] </emphasis></para>
    
    <para>
      ...
    </para>
     
  2. 问题:转换PNG插图时出现空指针异常

    解决

    还是在转换vim使用进阶时,出现下面的空指针异常(详细错误信息见PNG插件导致的空指针异常):

    严重: Exception
    java.lang.NullPointerException
    	at org.apache.fop.cli.InputHandler.transformTo(InputHandler.java:168)
    	at org.apache.fop.cli.InputHandler.renderTo(InputHandler.java:115)
    	at org.apache.fop.cli.Main.startFOP(Main.java:166)
            at org.apache.fop.cli.Main.main(Main.java:197) 
          

    经排除,这个异常是在转换下面的语句时发生的:

    
      <informalfigure>
        <mediaobject>
          <alt>在vim中使用gdb调试 - vimgdb</alt>
          <imageobject>
            <imagedata fileref='http://easwy.com/blog/uploads/2009/03/vimgdb2-300x216.png' align='center'/>
    
          </imageobject>
        </mediaobject>
        <caption align='center'><link xlink:href='http://easwy.com/blog/uploads/2009/03/vimgdb2.png' xlink:show='new'>点击查看大图</link></caption>
      </informalfigure>
       

    如果把imagedata中文件的URL换成JPG格式的图像文件,则转换正常。一旦使用PNG格式的文件,就会出现上面的空指针异常提示。在网上也没找到解决办法,查看了一下自己的FOP版本:

    FOP Version 0.94      
        

    猜想可能这是旧版本的BUG,于是下载了最新的FOP trunk版本,进行编译:

    
    svn co http://svn.apache.org/repos/asf/xmlgraphics/fop/trunk/
    ant all 

    使用这个版本再进行转换,果然错误消除。

  3. 问题:zh_cn hyphenation的问题

    解决

    在我的docbook文档中,都加有xml:lang=’zh-CN’这样的标志,指明本文档的语言是中文简体。

    但每次进行PDF文件转换时,都有下面的提示:

    严重: Couldn't find hyphenation pattern zh_cn
          

    在网上搜了一下,感觉这应该不是一个问题。对其它西文语言如英语、法语等,它们以单词为单位,单词之间采用空格隔开,如果单词太长需要换行时,就要在合适的地方加上一个连字符”-“。但对中文来讲,根本没有这个需要。所以这个错误提示忽略即可。

    不过,如果提示你找不到其它语言的hyphenation,例如找不到en_US的hyphenation,就需要到Objects For Formatting Objects(OFFO)去下载,出于版权方面的考虑,hyphenation缺省不再包含在FOP中了。

原创文章,请阅读页脚的许可方式,转载请注明:转载自易水博客 [ http://easwy.com/blog/ ]

本文链接地址: http://easwy.com/blog/archives/fop-errors-and-solution/

文章的脚注信息由WordPress的wp-posturl插件自动生成

vim使用进阶系列文章PDF版本下载

前几天把Apache FOP的环境搭建好后,就尝试着把vim使用进阶的docbook文档转换成PDF格式,但是转换没有成功,出现了一些错误。

昨晚调试了一个晚上,终于成功的把docbook转换成PDF了,大致浏览了一下,转换出来应该说效果还是很不错的,只是插图变得很不清晰,大概和我转换时采用的配置有关。不过现在没时间调整了,大家将就着看吧。

我已经把转换后的PDF文档上传,在文章vim使用进阶: 目录中可以找到下载链接。现在,这一系列文章将按照”署名-非商业性使用-相同方式共享”的创作共用许可协议发布,详情请见每页页脚的声明。

另外,我把下一步的写作提纲也列在vim使用进阶: 目录中了,如果你有什么感兴趣的主题,请留言提出来,对于具有普遍性的主题,我也会列入我的写作提纲。

Enjoy it!

原创文章,请阅读页脚的许可方式,转载请注明:转载自易水博客 [ http://easwy.com/blog/ ]

本文链接地址: http://easwy.com/blog/archives/advanced-vim-skills-pdf-download/

文章的脚注信息由WordPress的wp-posturl插件自动生成

如何将cscope安装到指定目录

登录博客,看到joecgs问

easwy:您好,感谢您的这一系列的文章,帮助我很快地熟悉使用vim,谢谢。
我现在是用远程的shell来写程序,服务器没有安装cscope,而又不能获取root权限。所以,我想能不能通过和安装vim一样的方式来安装cscope?

随着Linux的普及,使用Linux进行软件开发的人也越来越多。而大多数公司都采用这种方式:提供一台高性能的中央服务器做为开发编译服务器,每个人登录这台服务器进行开发编译。在这种情况下,用户通常没有root权限,怎么安装应用程序呢?

其实,Linux作为老牌多用户操作系统UNIX的一个分支,这当然不是一个问题。多用户操作系统中,允许用户根据自己的喜好安装软件,是再自然不过的事情了。

做法也很简单,UNIX的程序,一般都使用autoconf来自动检测安装环境完成配置,然后再进行编译、安装,这三步就是俗称的三板斧。

在使用autoconf进行配置时,可以使用参数来更改缺省的配置,比如,通过使用–prefix参数,就可以改变程序的安装目录,还有一些其它参数,允许用户打开或关闭某些特性。每个程序所支持的参数不一定相同,可以通过./configure –help命令查看程序支持哪些参数。

回到joecgs的问题上来,如果想把cscope安装到自己的HOME目录下,其实只需要在configure时,指定–prefix=$HOME就可以了,全部命令如下:

cd cscope-15.7
./configure --prefix=$HOME
make
make install 

如果你留心一下,我们在编译vim时,也可以指定–prefix参数。其实,对绝大多数支持autoconf的程序来说,都可以用这一参数来指定你程序的安装位置,不信你试试!

原创文章,请阅读页脚的许可方式,转载请注明:转载自易水博客 [ http://easwy.com/blog/ ]

本文链接地址: http://easwy.com/blog/archives/install-cscope-to-home/

文章的脚注信息由WordPress的wp-posturl插件自动生成

重设MySQL root密码

在安装MySQL时,随便设了一个密码,现在怎么也想不起来了,只好重设MySQL的root密码。

在网上搜到一篇文章:Resetting a forgotten MySQL root password,按照文章里的办法恢复成功。把步骤记录如下。

首先停止MySQL服务:

    # /etc/init.d/mysql stop
    Stopping MySQL database server: mysqld.
  

接下来,使用mysqld_safe命令在后台启动MySQL服务器,这里使用了–skip-grant-tables选项,允许不使用密码连接MySQL数据库:

    # /usr/bin/mysqld_safe --skip-grant-tables &
    [1] 5933
    nohup: ignoring input and redirecting stderr to stdout
    Starting mysqld daemon with databases from /var/lib/mysql
    mysqld_safe[5972]: started
  

接下来,登录数据库,并更新root用户的密码:

    # mysql --user=root mysql
    Reading table information for completion of table and column names
    You can turn off this feature to get a quicker startup with -A

    Welcome to the MySQL monitor.  Commands end with ; or \g.
    Your MySQL connection id is 1
    Server version: 5.0.51a-24 (Debian)

    Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

    mysql> update user set Password=PASSWORD('new-password-here') WHERE User='root';
    Query OK, 3 rows affected (0.00 sec)
    Rows matched: 3  Changed: 3  Warnings: 0

    mysql> flush privileges;
    Query OK, 0 rows affected (0.00 sec)

    mysql> exit
    Bye
  

现在,把mysqld_safe切换到前台,并使用CTRL-C结束它的运行:

    # fg
    /usr/bin/mysqld_safe --skip-grant-tables
    ^C
    STOPPING server from pid file /var/run/mysqld/mysqld.pid
    mysqld_safe[6005]: ended
  

然后重新启动MySQL服务:

    # /etc/init.d/mysql start
    Starting MySQL database server: mysqld.
    Checking for corrupt, not cleanly closed and upgrade needing tables..
  

现在,就可以使用新设置的root连接数据库了:


    # mysql --user=root --pass=new-passwd-here
    Welcome to the MySQL monitor.  Commands end with ; or \g.
    Your MySQL connection id is 681
    Server version: 5.0.51a-24 (Debian)

    Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

    mysql> quit
    Bye
  

原创文章,请阅读页脚的许可方式,转载请注明:转载自易水博客 [ http://easwy.com/blog/ ]

本文链接地址: http://easwy.com/blog/archives/reset_mysql_root_password/

文章的脚注信息由WordPress的wp-posturl插件自动生成

解决Google中短的元说明问题

今天在Google的网站管理员工具里看到有三个”短的元说明”的提示,点进去一看,有三个页面的元说明的确都很短,不超过20个字。可以仔细一看文章链接,应该这些文章的元说明不会这么短才是呀?

这里解释一下什么说”元说明”,元说明其实是一段描述性信息,主要用来简要描述一个页面的内容。当其它人在Google搜索到你的页面时,如果你提供了元说明文字,则Google会把你提供的元说明显示给用户。因此,元说明其实对用户决定是否造访你的网站有很大影响,如果元说明和用户所搜索的内容不符时,或者对用户吸引力不够时,用户当然不会访问你的网页。

在我WordPress的主题里,如果文章提供了摘要文本的话,会自动把这段摘要文本作为元说明放在页面中。例如,在我的主题模板中,有类似下面这样的话:

<?php
if ($post->post_excerpt) {
    $description     = $post->post_excerpt;
} else {
    $description = substr(strip_tags($post->post_content),0,220);
} ?>
<meta name="description" content="<?php echo $description; ?>" /> 

这段话的意思如果本文的摘要存在,就把搞要作为本文的元说明,否则就把该文章的前220个字符作为元说明。

检查一下那三篇提示”短元说明”的文章,在它们的摘要里,都出现了字符,看来是这个干扰了Google,它遇到第一个双引号时,就以为content属性的内容结束了。

知道了原因,改起来就容易了,只需要把这句话改一下:

<meta name="description" content="<?php echo htmlspecialchars($description, ENT_QUOTES); ?>" /> 

函数htmlspecialchars()会把摘要信息中的HTML特殊字符,例如<, >, "等都转换HTML中的entity名称,避免它们扰乱HTML文本。

这个问题,其实在我写wp-posturl插件时就遇到过了,现在又遇到了一次。看来以后在HTML属性内部使用PHP代码时,一定要记得转换特殊HTML字符。

原创文章,请阅读页脚的许可方式,转载请注明:转载自易水博客 [ http://easwy.com/blog/ ]

本文链接地址: http://easwy.com/blog/archives/fix_short_meta_descriptions/

文章的脚注信息由WordPress的wp-posturl插件自动生成

Android SDK 1.5预览版发布

刚刚在网上看到,Android SDK 1.5预览版已经发布。

在Android SDK 1.5中将包含很多用户关心的新功能,例如软键盘、语音识别、视频功能,以及更好的与Google产品结合。

刚刚尝试访问Google Developer网站,发现页面打不开,看来今天有太多的人访问了。^_^

原创文章,请阅读页脚的许可方式,转载请注明:转载自易水博客 [ http://easwy.com/blog/ ]

本文链接地址: http://easwy.com/blog/archives/android-sdk-15-update-release/

文章的脚注信息由WordPress的wp-posturl插件自动生成

关于vi/vim中:s命令的参数分隔符

Karl问道

请问下面这个命令中的等号是什么意思
:%s= *$== 删除行尾空白

这是vim初学者普遍感到疑惑的一个问题,为什么:s命令后有时候是”/”,有时候是”:”,还有时候是”=”甚至其它符号?

其实在vim的很多命令里,都允许用户自行定义分隔符。上面的命令等同于大家常见的:

:%s/ *//

只不过:s命令的参数分隔符由”/”变成了”=”。

但这样做有什么好处呢?

在上面的例子里你看不到把”/”换成”=”有什么好处,但如果你想替换的是”/usr/local/share/fonts/msfonts/simsun.ttc”这样的内容呢?如果你还使用”/”做为命令分隔符,你要对上面这个路径中的每一个”/”都使用”\”转义一下。但如果你用”=”作为分隔符的话,就不必如此了。

不仅仅:s命令可以这样做,其它具备多个参数的命令也可以,例如vimgrep命令。

看看vim中文手册里怎么说吧::help E146

原创文章,请阅读页脚的许可方式,转载请注明:转载自易水博客 [ http://easwy.com/blog/ ]

本文链接地址: http://easwy.com/blog/archives/vim_command_parameter_separator/

文章的脚注信息由WordPress的wp-posturl插件自动生成

使用Apache FOP将Docbook文档转换成PDF

在写完一个简单的Docbook 5.0例子后,刚好有网友希望我把2009以前vim使用进阶系列文章转换成PDF文档。于是就开始搭建FOP的环境,没想到花费了两天时间,才总算把Apache FOP转换Docbook文档到PDF的环境搭建起来,期间走了很多弯路。

本文简单介绍一下在Debian Lenny上搭建FOP转换环境的过程。下一篇文章介绍一下如何在Windows上搭建FOP环境。另外还会再写一篇文章,列出我在搭建环境过程中遇到的问题以及解决方法,希望对遇到类似问题的人有帮助。

按下面的步骤搭建环境,你可以在这里下载到Easwy的FOP配置及示例文件。

  1. 安装相关软件

    在Debian上安装软件是非常容易的事,只要下面一条命令,就可以把Docbook相关的软件全部安装完成。

    aptitude install docbook-xml docbook-xsl xsltproc fop 

    上面的命令会把它们所依赖的软件包也一并装好。安装完成后,主要软件所在的目录如下:

    • docbook-xsl – /usr/share/xml/docbook/stylesheet/nwalsh/,这是Docbook的XSL转换样式表,Lenny中带的是1.73.2版本,最新版本为1.74.3。不过我觉得Lenny中的已经够用了
    • xsltproc – /usr/bin/xsltproc,这个是Docbook转换工具,用C语言写的,转换速度非常快
    • fop – /usr/bin/fop,Apache的FOP转换工具,主要用来把xsltproc输出的fo格式文件,转换成PDF文件,Lenny中带的是0.94,最新版本是0.95
  2. 设置FOP

    首先创建一个目录来存放FOP的配置信息,在这里我创设使用/etc/fop/目录。

    FOP已经能够很好的支持中文,但是如果想让FOP使用Type1类型字体以及TrueType类型字体的话,还需要为这些字体生成Metrics文件,并在FOP的配置文件中进行设置。

    在Debian Lenny中提供了一个名为/usr/bin/fop-ttfreader的脚本,它其实只是对org.apache.fop.fonts.apps.TTFReader的封装,关于org.apache.fop.fonts.apps.TTFReader程序的用法我在下篇文章里讲,你也可以参考文尾的第二篇参考文档。

    在Debian Lenny中配置中文一文中,我已经把Windows下的宋体拷贝到了Lenny中,要想FOP把这个字体嵌入到PDF文档中,需要使用/usr/bin/fop-ttfreader来生成TTF字体的Metrics文件。

    我的字体文件为/usr/local/share/fonts/msfonts/simsun.ttc,先用下面的命令看看这个字体集合中有几个字体:

    /usr/bin/fop-ttfreader /usr/local/share/fonts/msfonts/simsun.ttc /etc/fop/simsun.xml
    TTF Reader for Apache FOP 0.94
    
    Parsing font...
    Reading /usr/local/share/fonts/msfonts/simsun.ttc...
    This is a TrueType collection file with 3 fonts
    Containing the following fonts: 
    SimSun
    NSimSun
    SimSun-PUA
    Error while building XML font metrics file.
    java.lang.IllegalArgumentException: For TrueType collection you must specify which font to select (-ttcname) 

    忽略上面显示的异常,我们的目的只是看这个字体集中有几种字体,从上面的输出中可以看到有三个字体:SimSunNSimSunSimSun-PUA

    好,接下来我们为SimSun字体生成一个Metrics文件,在刚才那条命令中加上参数-ttcname SimSun参数(注意,字体名区分大小写),再执行一次,这一次输出如下:

    /usr/bin/fop-ttfreader -ttcname SimSun /usr/local/share/fonts/msfonts/simsun.ttc /etc/fop/simsun.xml
    TTF Reader for Apache FOP 0.94
    
    Parsing font...
    Reading /usr/local/share/fonts/msfonts/simsun.ttc...
    This is a TrueType collection file with 3 fonts
    Containing the following fonts: 
    SimSun <-- selected
    NSimSun
    SimSun-PUA
    Font Family: SimSun
    Creating xml font file...
    Creating CID encoded metrics...
    Writing xml font file /etc/simsun.xml...
    This font contains no embedding license restrictions.
    
    XML font metrics file successfully created.
          

    这一次执行成功了,生成的Metrics文件为/etc/fop/simsun.xml。你可以继续用这条命令为其它你想用的TTF或Type1字体生成Metrics文件。

    接下来设置FOP,我是直接把FOP 0.95自带的缺省配置文件拷贝了一份到/etc/fop/fop.xconf,然后再进行修改(我下载了一个FOP 0.95,不过只用了它的配置文件 ^_^):

    首先在文件中找到<renderer mime=”application/pdf”>这一行,然后在此标签中加入关于字体的配置。在FOP 0.94中已经支持对字体的自动检测,不过如果你的字体不在标准字体目录里,还是需要指明字体的目录。例如,我在配置文件中加入以下设置:

            
          <fonts>
            <font metrics-url="file:///etc/fop/simsun.xml" kerning="yes" embed-url="file:///usr/local/share/fonts/msfonts/simsun.ttc">
              <font-triplet name="SimSun" style="normal" weight="normal"/>
              <font-triplet name="SimSun" style="normal" weight="bold"/>
    
              <font-triplet name="SimSun" style="italic" weight="normal"/>
              <font-triplet name="SimSun" style="italic" weight="bold"/>
            </font>
    
            <font metrics-url="file:///etc/fop/simhei.xml" kerning="yes" embed-url="file:///usr/local/share/fonts/msfonts/simhei.ttf">
              <font-triplet name="SimHei" style="normal" weight="normal"/>
              <font-triplet name="SimHei" style="normal" weight="bold"/>
    
              <font-triplet name="SimHei" style="italic" weight="normal"/>
              <font-triplet name="SimHei" style="italic" weight="bold"/>
            </font>
    
            <directory recursive="true">/usr/share/fonts/</directory>
            <auto-detect/> 
          </fonts>
    
             
          

    上面的配置加入了SimSun和SimHei两种字体,并加入字体目录/usr/share/fonts//usr/local/share/fonts/,同时打开了auto-detect。FOP只在第一次运行时扫描字体,然后为之生成缓存,以后就不必再扫描了。

  3. 配置XSL转换样式表

    接下来,我们要配置XSL转换样式表,让xsltproc在转换Docbook文档时,使用我们指定的中文字体。在下面我给出了一个简单的样式表,假设存为docbook_fo.xsl:

     
    <?xml version='1.0'?>
    
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                    xmlns:exsl="http://exslt.org/common"
                    xmlns:fo="http://www.w3.org/1999/XSL/Format"
                    xmlns:ng="http://docbook.org/docbook-ng"
                    xmlns:db="http://docbook.org/ns/docbook"
                    exclude-result-prefixes="db ng exsl"
                    version='1.0'>
    
    <xsl:import href="/usr/share/xml/docbook/stylesheet/nwalsh/fo/docbook.xsl"/>
    <xsl:param name="body.font.family">SimSun</xsl:param>
    <xsl:param name="monospace.font.family">SimSun</xsl:param>
    <xsl:param name="title.font.family">SimHei</xsl:param>
    
    </xsl:stylesheet>
             

    在这个转换样式表里,首先导入了Docbook的FO样式表,然后重新设置了其中的字体参数,改成我们所要的字体名称。需要注意的是,这里的字体名字需要和/etc/fop/fop.xconf中设置的font-triplet中的名字完全一致。

    我之所以配置两天才配好FOP,就是因为在这里犯了个错误。我最初的docbook_fo.xsl中,在导入FO样式表时,使用的是<xsl:include …>,它和<xsl:import …>的区别在于,使用import导入时,先使用本文件中参数设置,当本文件中未对参数进行设置时,才使用所导入文件中的设置;但使用include导入却不是这样。所以,即使我在docbook_fo.xsl中对输出字体进行了重新设置,但实际上我的修改未生效,xsltproc输出的.fo文件中字体用的根本不是我所指定的。最终的结果就是文章中的中文,都被显示成了###。

  4. 输出PDF文件

    上面的配置完成以后,就可以输出PDF文件了。只需要使用下面两条命令即可:

    /usr/bin/xsltproc -o render_docbook_xml_to_pdf_by_apache_fop.fo docbook_fo.xsl render_docbook_xml_to_pdf_by_apache_fop.xml
    /usr/bin/fop -c /etc/fop/fop.xconf render_docbook_xml_to_pdf_by_apache_fop.fo -pdf render_docbook_xml_to_pdf_by_apache_fop.pdf

    上面两条命令会有大量的错误提示,暂时不管它,去看看输出的pdf文档吧,尽管还有诸多不满意,不过总算能输出出来了。接下来需要解决的问题还很多,比如如何分别为中英文指定字体族、如何更好的断字等,留待以后慢慢解决。

参考文档

原创文章,请阅读页脚的许可方式,转载请注明:转载自易水博客 [ http://easwy.com/blog/ ]

本文链接地址: http://easwy.com/blog/archives/render_docbook_xml_to_pdf_by_apache_fop/

文章的脚注信息由WordPress的wp-posturl插件自动生成

Linux中批量解压缩rar文件

从windows中拷贝十几个rar文件到Debian,记得以前Linux下没有rar文件工具的,今天用apt-cache搜了一下,居然发现Debian Lenny中已经包含了一个名为rar的软件。以后接受别人的rar文件也不用担心解不开了。

要解压这么多文件也挺麻烦的,不过既然在Linux下,就有好办法,只需要在shell中输入下面一条命令(bash shell):

for f in `ls --color=none`; do rar x $f; done

原创文章,请阅读页脚的许可方式,转载请注明:转载自易水博客 [ http://easwy.com/blog/ ]

本文链接地址: http://easwy.com/blog/archives/extract-multiple-rar-files-in-linux/

文章的脚注信息由WordPress的wp-posturl插件自动生成

Easwy的博客采用创作共用许可协议

以前在写文章时,基本都是允许转载,但禁止商业使用。那时对署名以及相同方式共享没有提出明确的要求,因为我觉得这两点是必然的。在创建Easwy的博客过程中,了解了创作共用许可协议,感觉其中的署名-非商业性使用-相同方式共享很适合自己,以后就按此许可协议发布自己的文章,除非在文章中另有注明。

从即日起,所有Easwy的博客上发表的文章,都将遵循署名-非商业性使用-相同方式共享的许可协议(另有注明除外),你可以在本博客每页的页尾看到这一许可声明。

对今天以前发表文章,不知道能不能采用这一许可协议,如果可以的话,也按此许可协议发布。

原创文章,请阅读页脚的许可方式,转载请注明:转载自易水博客 [ http://easwy.com/blog/ ]

本文链接地址: http://easwy.com/blog/archives/use-creative-commons-license-on-easwy-com/

文章的脚注信息由WordPress的wp-posturl插件自动生成