是的,您可以使用多个 XML 数据源。在 dataSourceExpression 的帮助下,您可以将第二个(另一个)数据源传递给子报表。
我将在 Java 的帮助下展示如何做到这一点。如果使用 Java 代码,我们不需要借助报表的 queryString 在报表(主报表和子报表)中指定查询(XPath 表达式) 属性。
工作样本
主报表和子报表将使用不同的XML文件。
数据源
customers.xml 文件是主报告的数据源:
<?xml version="1.0" encoding="UTF-8"?>
<Customers>
<id>ANTON</id>
<id>AROUT</id>
<id>BERGS</id>
<id>BLAUS</id>
</Customers>
customers_details.xml 文件是子报表的数据源:
<?xml version="1.0" encoding="UTF-8"?>
<Customers>
<Customer>
<CustomerID>ANTON</CustomerID>
<CompanyName>Antonio Moreno Taquería</CompanyName>
<ContactName>Antonio Moreno</ContactName>
<ContactTitle>Owner</ContactTitle>
<City>México D.F.</City>
<Country>Mexico</Country>
</Customer>
<Customer>
<CustomerID>AROUT</CustomerID>
<CompanyName>Around the Horn</CompanyName>
<ContactName>Thomas Hardy</ContactName>
<ContactTitle>Sales Representative</ContactTitle>
<City>London</City>
<Country>UK</Country>
</Customer>
<Customer>
<CustomerID>BERGS</CustomerID>
<CompanyName>Berglunds snabbköp</CompanyName>
<ContactName>Christina Berglund</ContactName>
<ContactTitle>Order Administrator</ContactTitle>
<City>Luleå</City>
<Country>Sweden</Country>
</Customer>
<Customer>
<CustomerID>BLAUS</CustomerID>
<CompanyName>Blauer See Delikatessen</CompanyName>
<ContactName>Hanna Moos</ContactName>
<ContactTitle>Sales Representative</ContactTitle>
<City>Mannheim</City>
<Country>Germany</Country>
</Customer>
</Customers>
来自两个按 Id (Customers.id=Customers.Customer.CustomerID) 相关文件的数据。
此文件包含从与 JasperReports 库一起分发的示例 northwind.xml 文件中进行的某种编译。
主报告模板
我使用 JRXmlDataSource(String, String) 构造函数将 XML 数据源传递给子报表。子报表取决于此示例中主报表的数据。
获取子报表数据的XPath表达式为:/Customers/Customer[CustomerID=<id>],其中<id>是id节点的值,来自customers.xml.
<?xml version="1.0" encoding="UTF-8"?>
<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" name="master_with_xml" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20">
<field name="id" class="java.lang.String">
<fieldDescription><![CDATA[child::text()]]></fieldDescription>
</field>
<variable name="expression" class="java.lang.String">
<variableExpression><![CDATA["/Customers/Customer[CustomerID='" + $F{id} + "']"]]></variableExpression>
</variable>
<detail>
<band height="70" splitType="Stretch">
<textField>
<reportElement x="100" y="0" width="100" height="15"/>
<textFieldExpression><![CDATA[$F{id}]]></textFieldExpression>
</textField>
<staticText>
<reportElement x="0" y="0" width="100" height="15"/>
<text><![CDATA[Id:]]></text>
</staticText>
<subreport>
<reportElement x="54" y="15" width="380" height="45"/>
<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRXmlDataSource("customers_details.xml", $V{expression})]]></dataSourceExpression>
<subreportExpression><![CDATA["subreport_with_xml.jasper"]]></subreportExpression>
</subreport>
</band>
</detail>
</jasperReport>
子报表的模板
子报表显示来自主报表的客户 ID 数据(针对每条记录)。
<?xml version="1.0" encoding="UTF-8"?>
<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" name="subreport_with_xml" pageWidth="595" pageHeight="842" columnWidth="595" leftMargin="0" rightMargin="0" topMargin="0" bottomMargin="0">
<field name="CompanyName" class="java.lang.String">
<fieldDescription><![CDATA[CompanyName]]></fieldDescription>
</field>
<field name="ContactName" class="java.lang.String">
<fieldDescription><![CDATA[ContactName]]></fieldDescription>
</field>
<field name="ContactTitle" class="java.lang.String">
<fieldDescription><![CDATA[ContactTitle]]></fieldDescription>
</field>
<field name="City" class="java.lang.String">
<fieldDescription><![CDATA[City]]></fieldDescription>
</field>
<field name="Country" class="java.lang.String">
<fieldDescription><![CDATA[Country]]></fieldDescription>
</field>
<detail>
<band height="75" splitType="Stretch">
<staticText>
<reportElement x="0" y="0" width="100" height="15"/>
<text><![CDATA[Company name:]]></text>
</staticText>
<textField>
<reportElement x="100" y="0" width="200" height="15"/>
<textFieldExpression><![CDATA[$F{CompanyName}]]></textFieldExpression>
</textField>
<staticText>
<reportElement x="0" y="15" width="100" height="15"/>
<text><![CDATA[Contact name:]]></text>
</staticText>
<textField>
<reportElement x="100" y="15" width="200" height="15"/>
<textFieldExpression><![CDATA[$F{ContactName}]]></textFieldExpression>
</textField>
<staticText>
<reportElement x="0" y="30" width="100" height="15"/>
<text><![CDATA[Contact title:]]></text>
</staticText>
<textField>
<reportElement x="100" y="30" width="200" height="15"/>
<textFieldExpression><![CDATA[$F{ContactTitle}]]></textFieldExpression>
</textField>
<staticText>
<reportElement x="0" y="45" width="100" height="15"/>
<text><![CDATA[Country:]]></text>
</staticText>
<textField>
<reportElement x="100" y="45" width="200" height="15"/>
<textFieldExpression><![CDATA[$F{Country}]]></textFieldExpression>
</textField>
<staticText>
<reportElement x="0" y="60" width="100" height="15"/>
<text><![CDATA[City:]]></text>
</staticText>
<textField>
<reportElement x="100" y="60" width="200" height="15"/>
<textFieldExpression><![CDATA[$F{City}]]></textFieldExpression>
</textField>
</band>
</detail>
</jasperReport>
Java 代码
获取主报表数据的XPath表达式为:/Customers/*。
JasperReport jasperReport;
try (InputStream inputStream = JRLoader.getResourceInputStream("master_with_xml.jrxml")) {
jasperReport = JasperCompileManager.compileReport(JRXmlLoader.load(inputStream));
}
Map<String, Object> params = new HashMap<>();
params.put(JRParameter.REPORT_LOCALE, Locale.US);
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, params, new JRXmlDataSource("customers.xml", "/Customers/*")); // select all customers with XPath
我已将 xalan 库添加到类路径中。
输出结果
我使用 PDFExporter 来生成这个 pdf 文件:
注意事项:
- 使用 XML 数据源的绝佳示例:XML Data Source Sample。此示例的完整代码可以在 JasperReports 库 分发包的 demo/samples/xmldatasource/src 文件夹中找到。
- 可以在以下帖子中找到对某些功能的良好解释:Looking for a working example of JasperStudio xml subdatasource,JasperReports: JRDataSource.subDataSource shows undefined
- 您可以通过主报表的参数传递子报表的数据源。