XML文件如何转换为PDF报表 使用JasperReports导出XML数据

8次阅读

jasperreports需用jrxmldatasource包装xml数据源,要求xml有唯一根节点且记录为直接子节点,支持xpath定位字段、命名空间及sax流式解析,pdf中文需配置字体,大文件须启用流模式防oom。

XML文件如何转换为PDF报表 使用JasperReports导出XML数据

XML数据源怎么配给JasperReports

JasperReports 本身不直接解析任意 XML 文件,必须先用 JRXmlDataSource 包装。它要求 XML 符合特定结构:根节点下是重复的记录节点(比如 <orders><order>...</order><order>...</order></orders>),否则会报 net.sf.jasperreports.engine.JRException: Could not load XML data 或静默跳过数据。

  • 确保 XML 有且仅有一个顶层容器节点,所有数据行是它的直接子节点(不能嵌套两层才到记录)
  • new JRXmlDataSource(xmlInputStream, "/root/record") 显式指定 XPath 路径,别依赖默认行为
  • 如果 XML 含命名空间,JRXmlDataSource 默认不处理,要么预处理去掉 Namespace,要么改用 JRXmlDataSource(InputStream, String, Boolean) 构造函数并传 true 启用 namespace 支持(JasperReports ≥ 6.12)

报表模板里怎么引用XML字段

字段名不是 XML 标签名,而是 XPath 表达式相对记录节点的路径。比如每条 <order></order> 下有 <customer><name>Alice</name></customer>,那字段表达式得写 customer/name,不是 name/order/customer/name

  • 字段类型在模板中声明为 java.lang.String 即可,JasperReports 会自动转换文本内容
  • 遇到属性值(如 <item id="101"></item>),用 @id 引用,注意 @ 符号不能漏
  • 子节点含多个同名项(如多个 <tag></tag>)时,tags/tag 只取第一个;要全量需用 $F{tags/tag}.size() 配合 list 组件,但得提前确认字段类型是 java.util.List

导出PDF时中文乱码或字体缺失

XML 数据里的中文能正常读取,但 PDF 导出后显示方块或空格,问题几乎都在字体配置,和 XML 解析无关。

  • 必须在 jrxml 模板里每个文本字段设置 pdfFontNamepdfEncoding,例如 pdfFontName="STSong-Light" pdfEncoding="UniGB-UCS2-H"
  • 使用 iText 5 时,中文字体文件(如 simhei.ttf)要通过 JRFontExtensionsRegistry 注册,或把字体打包进 classpath 并在 jasperreports_extension.properties 中声明
  • 若用 JasperReports Server,字体配置在服务端,本地开发测试用的字体路径对服务器无效,容易误判为代码问题

内存溢出或生成超慢的常见原因

大 XML(>10MB)直接喂给 JRXmlDataSource 会全部加载进内存构建 dom 树,不是流式解析。即使数据只用一次,也极易 OOM。

  • 超过 5 万条记录建议改用 JRXmlDataSource 的流式构造函数:new JRXmlDataSource(xmlInputStream, "/root/record", true)(第三个参数启用 SAX 模式)
  • 避免在模板表达式里写复杂 XPath,如 ../../../parent/name,每次渲染都重新遍历,性能断崖式下降
  • 不要在 textFieldexpression 中调用 System.getProperty() 或其他 IO 操作——XML 数据源本身无状态,但表达式会在每行重复执行

真正卡住的地方往往不在“怎么转”,而在 XML 结构是否适配 JRXmlDataSource 的 XPath 定位逻辑,以及字体和内存这两关没提前压测过真实数据量。

text=ZqhQzanResources