使用Java中iText XMLWorker为何出现奇怪错误?
解决XMLWorkerHelper解析HTML时的NumberFormatException("100%"输入字符串)
问题原因
XMLWorker(iText 5配套的HTML解析组件)对CSS属性的百分比单位支持存在缺陷,当解析类似width:100%这类样式时,会错误地尝试将带百分号的字符串直接转换为纯数字,从而抛出NumberFormatException。
解决方案
方案1:迁移至pdfHTML(官方推荐)
XMLWorker已被官方弃用,iText 7的pdfHTML组件对CSS和HTML的支持更完善,原生支持百分比单位。迁移步骤如下:
- 引入依赖(Maven示例):
<dependency> <groupId>com.itextpdf</groupId> <artifactId>html2pdf</artifactId> <version>5.0.0</version> <!-- 建议使用最新稳定版 --> </dependency>
- 重写转换函数:
byte[] convertHtmlToPdfBytes(String htmlString) throws IOException { ByteArrayOutputStream outp = new ByteArrayOutputStream(); HtmlConverter.convertToPdf(htmlString, outp); return outp.toByteArray(); }
方案2:自定义CSS解析器(兼容iText 5场景)
如果无法升级到iText 7,可以通过自定义CSS解析逻辑处理百分比:
- 实现自定义CSS解析器:
public class CustomCssResolver extends StyleAttrCSSResolver { @Override public void resolveStyles(Tag tag) { super.resolveStyles(tag); Map<String, String> styles = tag.getCSS(); // 处理width属性的百分比 if (styles.containsKey("width")) { String widthVal = styles.get("width"); if (widthVal.endsWith("%")) { // 计算对应页面宽度的具体数值(以A4默认页面为例) float pageWidth = Document.getDefaultPageSize().getWidth(); float percent = Float.parseFloat(widthVal.replace("%", "")) / 100; styles.put("width", String.valueOf(pageWidth * percent)); } } // 可按需添加其他百分比属性的处理,比如height、padding等 } }
- 修改原函数使用自定义解析器:
byte[] convertHtmlToPdfBytes(String htmlString) throws IOException, DocumentException { Document document = new Document(); ByteArrayOutputStream outp = new ByteArrayOutputStream(); PdfWriter writer = PdfWriter.getInstance(document, outp); document.open(); InputStream inp = IOUtils.toInputStream(htmlString); // 构建自定义XMLWorker处理链 CustomCssResolver cssResolver = new CustomCssResolver(); HtmlPipelineContext htmlContext = new HtmlPipelineContext(null); htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory()); PdfWriterPipeline pdfPipeline = new PdfWriterPipeline(document, writer); HtmlPipeline htmlPipeline = new HtmlPipeline(htmlContext, pdfPipeline); CssResolverPipeline cssPipeline = new CssResolverPipeline(cssResolver, htmlPipeline); XMLWorker worker = new XMLWorker(cssPipeline, true); XMLParser parser = new XMLParser(worker); parser.parse(inp); document.close(); return outp.toByteArray(); }
方案3:修改HTML中的样式写法(内容可控时使用)
如果HTML内容由你控制,可以将引发错误的百分比样式替换为XMLWorker兼容的格式,比如将width:100%替换为具体的页面宽度数值(A4页面默认宽度为595pt,即width:595pt)。
内容的提问来源于stack exchange,提问作者HNIM600
相关产品推荐
相关产品推荐

