如何解决[org.xml.sax.SAXParseException]及基于XSL模板与XML参数生成PDF
我来帮你一步步解决这两个问题:
问题1:搞定
org.xml.sax.SAXParseException; lineNumber: 2; columnNumber: 1; Content is not allowed in prolog.异常 这个错误本质是XML解析器在文件开头(prolog部分,也就是XML声明之前)发现了不该有的内容,常见原因和解决方法如下:
- 字节顺序标记(BOM)搞的鬼:如果你的XML或XSL文件是UTF-8编码但带了BOM,解析器会把这个隐藏的标记当成内容。解决办法很简单:用Notepad++这类编辑器打开文件,选择「编码」→「UTF-8无BOM格式」重新保存就行。
- 开头有空白字符:检查你的XML/XSL文件第一行,必须是
<?xml version="1.0" encoding="UTF-8"?>,前面不能有空格、换行或者其他任何字符。很多时候复制粘贴会不小心带进来空格,删掉就好。 - 编码不匹配:确认文件实际编码和声明里的
encoding="UTF-8"一致。比如文件其实是GBK编码,但声明写了UTF-8,解析器就会乱读。要么把文件转成UTF-8,要么修改声明里的编码值。 - 动态生成时的输出问题:如果是程序生成XML,比如Java或Python代码,要确保输出流没有先写日志、空格之类的内容再输出XML。比如Java里要清空输出缓冲区,保证XML是第一个被写入的内容。
问题2:基于给定XSL模板和XML生成PDF
生成PDF的核心流程是:XML → XSLT转换为XSL-FO → FO处理器转PDF,具体步骤如下:
1. 完善你的XSL模板
你给出的开头已经引入了XSL-FO的命名空间,接下来需要编写FO的布局规则来渲染GenerationReport里的内容。这里给你一个基础示例,你可以根据实际XML结构扩展:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:fo="http://www.w3.org/1999/XSL/Format" > <xsl:output method="xml" version="1.0" omit-xml-declaration="no" indent="yes" encoding="UTF-8" /> <xsl:template match="/"> <fo:root> <!-- 定义A4页面模板,设置边距 --> <fo:layout-master-set> <fo:simple-page-master master-name="A4-page" page-width="210mm" page-height="297mm" margin-top="20mm" margin-bottom="20mm" margin-left="25mm" margin-right="25mm"> <fo:region-body /> <fo:region-before extent="15mm" /> <!-- 页眉区域 --> <fo:region-after extent="10mm" /> <!-- 页脚区域 --> </fo:simple-page-master> </fo:layout-master-set> <fo:page-sequence master-reference="A4-page"> <!-- 页眉内容 --> <fo:static-content flow-name="xsl-region-before"> <fo:block font-size="14pt" font-weight="bold" text-align="center">生成报告</fo:block> </fo:static-content> <!-- 正文内容,这里需要匹配你的XML元素路径 --> <fo:flow flow-name="xsl-region-body"> <fo:block font-size="12pt" margin-top="10mm"> <xsl:value-of select="GenerationReport/YourElementName" /> <!-- 替换成你实际的XML元素路径,比如Va开头的元素 --> </fo:block> <!-- 继续添加更多fo:block来渲染所有XML内容,比如表格、列表等 --> </fo:flow> </fo:page-sequence> </fo:root> </xsl:template> </xsl:stylesheet>
2. 执行XSLT转换得到XSL-FO文件
你可以用命令行工具(比如Saxon)或者编程语言来完成转换:
命令行示例(Saxon)
java -jar saxon-he-12.4.jar -s:你的XML文件.xml -xsl:你的XSL模板.xsl -o:输出的FO文件.fo
Java代码示例
import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; import java.io.File; public class XsltToFo { public static void main(String[] args) throws Exception { TransformerFactory factory = TransformerFactory.newInstance(); // 加载XSL模板 Transformer transformer = factory.newTransformer(new StreamSource(new File("your-template.xsl"))); // 转换XML为FO transformer.transform(new StreamSource(new File("input.xml")), new StreamResult(new File("output.fo"))); } }
3. 将XSL-FO转换为PDF
推荐用Apache FOP这个工具来处理FO文件,支持命令行和代码调用:
命令行示例
直接一步到位从XML+XSL生成PDF:
fop -xml input.xml -xsl your-template.xsl -pdf output.pdf
或者先转FO再转PDF:
fop output.fo output.pdf
Java代码示例
import org.apache.fop.apps.Fop; import org.apache.fop.apps.FopFactory; import org.apache.fop.apps.MimeConstants; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.sax.SAXResult; import javax.xml.transform.stream.StreamSource; import java.io.FileOutputStream; import java.io.OutputStream; public class FoToPdf { public static void main(String[] args) throws Exception { // 初始化FOP工厂 FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI()); // 输出PDF文件流 OutputStream out = new FileOutputStream(new File("output.pdf")); try { // 创建FOP实例,指定输出格式为PDF Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, out); // 加载XSL模板并执行转换 TransformerFactory factory = TransformerFactory.newInstance(); Transformer transformer = factory.newTransformer(new StreamSource(new File("your-template.xsl"))); transformer.transform(new StreamSource(new File("input.xml")), new SAXResult(fop.getDefaultHandler())); } finally { out.close(); } } }
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

