我想拥有适用于各种XML数据源的共享(模板).JRXML文件。
我所知道的唯一可能阻止这种情况的是,字段规格会略有不同。
对于一个XML文件,名称字段的XPATH可能是:
person/name/last
对于另一个XML文件,XPATH可能是:
contact/last_name
理想情况下,我可以将XPATH作为参数传递并使用它:
<field name="name" class="java.lang.String">
<fieldDescription> $P{NAME_XPATH} </fieldDescription>
</field>
但Jasper似乎不支持在<fieldDescription>
标签中使用参数。
我可以通过某种方式将字段规范注入我的JRXML模板吗?
答案 0 :(得分:0)
由于您的系统是基于XML的,为什么不使用XSLT?您的JRXML模板可以调整为XSL样式表,然后使用XML配置文件作为输入,XSLT处理器可以用配置内容替换字段描述。
实施例: 的 JRXML / XSL 强>
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/report-config">
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd">
...
<field name="name" class="java.lang.String">
<fieldDescription><xsl:value-of select="name"/></fieldDescription>
</field>
...
</jasperReport>
</xsl:template>
</xsl:stylesheet>
配置XML
<?xml version="1.0" encoding="ISO-8859-1"?>
<report-config>
<name>person/name/last</name>
</report-config>
答案 1 :(得分:0)
Jasper不支持在<fieldDescription>
代码中使用参数。
我下载了Jasper资源,我认为您只需实施替代XPathExecutor
即可添加此功能。原因是因为包含参数的上下文不可用于XPathExecutor工厂类。简而言之,需要添加大量的上下文传递。
你当然可以尝试添加它,但它会影响许多类文件,然后它变成Jasper可能无法接收的那种变化,并且你将永远合并你的不同来源。
我还没准备冒这个风险。另外,我认为贾斯珀迟早会加上这个。
但是,我确实提出了一个解决方案,主要涉及编写自己的自定义XPathExecutor,然后通过Threadlocal变量实现将上下文传递给它。在下面的示例代码中,Threadlocal变量为ReportGeneratorJasper.requestContext
static ThreadLocal<ReportRequest> requestContext;
以下是在我的班级ReportGeneratorJasper
中设置自定义XPathExecutor的代码:
JasperReport repResource = getJasperReport(report);
JasperPrint jp = null;
// Setup for eReports XPATH executers
//
JasperReportsContext jrc = DefaultJasperReportsContext.getInstance();
jrc.setProperty(
JRXPathExecuterUtils.PROPERTY_XPATH_EXECUTER_FACTORY,
XalanNamedParameterXPathExecutor.class.getCanonicalName());
requestContext =
new ThreadLocal<ReportRequest>() {
protected synchronized ReportRequest initialValue() {
return request;
};
};
JasperFillManager jfm = JasperFillManager.getInstance(jrc);
ReportRequest是我自己的bean,它包含定义&#34;这个&#34;的所有属性。特定的报告生成请求。
这是自定义XPathExecutor(它也提供了自己的工厂)。 :
public class XalanNamedParameterXPathExecutor
extends XalanXPathExecuter implements JRXPathExecuterFactory {
// Reference to the Threadlocal
//
private ReportRequest request;
public static final String PREFIX = "$";
public XalanNamedParameterXPathExecutor() {
this.request = ReportGeneratorJasper.requestContext.get();
}
@Override
public Object selectObject(Node arg0, String xpath) throws JRException {
String useXpath = xpath;
if (xpath.startsWith("$")) {
String value = request.getScalarParamAsString(xpath);
useXpath = (value != null ? value : xpath);
}
return super.selectObject(arg0, useXpath);
}
@Override
public JRXPathExecuter getXPathExecuter() {
return new XalanNamedParameterXPathExecutor();
}
使用Threadlocal并不是一个理想的解决方案。如果报表填充符在不同的线程中运行,则很容易破坏。但是在当前版本的Jasper中,它似乎不是一个问题。
希望Jasper能为此实现内置支持。