最近两天做一个打印页面表单的功能,用的freemaker+itextpdf+xhtmlrenderer实现,三个异常困扰了我一天,最终全部解决,现在分享一下。
这三个组合在一起打印网页内容需要一个“模板”xhtml,在此记为temp.html。
我最开始的做法是把需要打印的jsp页面复制下来,去掉所有非html的标签(比如EL表达式,SpringMVC框架的页面标签等),反正只要是HTML的标签就留下。
最终扒下来放到浏览器一看,结构一样,再把需要的参数按照freemaker提供的语法加去,然后下面三个异常困扰了我一整天。。。。
一、RROR: 'The element type "input" must be terminated by the matching end-tag "</input>".'
是的,很简单,就是由于temp.html写的不规范。xhtmlrenderer需要的文件是要求格式十分严谨的xhtml文件,一般的html文件即使存在一些小问题,比如缺标签、缺结束标签等问题,浏览器上也显示正常。
解决办法:
1.使用JTidy将html转换为xhtml,不过这只适用于结构简单切内容较少的html。如果你的html文件错误较为严重(缺少结束标签),这个JTidy就直接将错误的去除,你就会发现你少了很多内容。另外,JTidy直接给你把非HTML标签的内容去掉,例如在模板中使用freemaker的标签<#if>,这些内容就都没了。
2.手动检验吧。。。我花了一小时手动缩进一个1000多行的html文本(Node++)。。。终于找到了一个少写的</d>
二、Error on appendChild - An attempt was made to reference a Node in a context where it does not exist
就是引用了不存在的节点。
我仔细查了半天,页面中根本没有引用节点的操作,后来才发现是css和属性导致的。我们在SpringMVC框架中,习惯将css作为静态资源放到其他路径下,在配置文件中设置静态文件的访问,可是打印pdf的过程中作为模板的temp.html直接被用了,根本没法经过框架访问css资源,真TMD坑爹!后来我把所有的静态资源全都复制过来,心想肯定都全了吧?天真!报了个格式错误的异常(就是异常一),TMD不知道是不是css格式写的有问题,一共接近2000行的样式怎么找?然后我把css全删了,结果发现还是报这个异常,然后我直接删掉所有属性,这个问题就解决了。因为这个temp.html文件不是去服务器的,这个框架组合无法识别过于复杂的模板。不过后来测试发现HTML标签属性写上没事,比如
<input type="checkbox"/>
就没问题,但是像
<input id="aa"/>
就有问题。
关于css的问题,还需要补充一下。你可以直接把css写在模板里就不会报错,或者加link标签,路径参数传进去,就像这样
在控制器中可以设置项目的根路径 /xiangmupages/ map.put("basePath","/xiangmu/"); freemarker是根据项目的根路径开始找的 href="${basePath}pages/... 运行结果: < link rel="stylesheet" type="text/css" href="/xiangmu/pages/ww/jschart/style.css" / > < script type="text/javascript" src="/xiangmu/pages/ww/jschart/amcharts.js" >< /script >
三、Content is not allowed in prolog
这个才是真正坑爹的隐藏问题,我一直猜测是因为没声明编码格式或者后缀问题,后来才发现问题出在我用记事本直接修改文件上了。
我在调试过程中直接打开部署好的temp.html文件修改,这样就不用重启服务器,结果没注意记事本打开文件和文件本身的编码格式不同,你的一点修改导致框架在读取文件时遇到了编码问题,无法打开。正确的方法是,在IDE中编辑好之后保存复制粘贴替换服务器下的temp.html文件。
四、中文不显示
最后一个坑爹玩意,这个框架不支持中文,只要出现中文就打印不出来。解决办法:
修改 flying sauser(xhtmlrenderer) 源代码,中文无障碍显示
我在做这个功能的时候,这些异常不是按照这个顺序依次出现的,是改一次就不知道下一个是什么异常,也不知道是一个异常引发其他还是怎样,总之一把辛酸泪。。。。