How to fetch data by id from parent's sibling

2019-07-25 13:03发布

问题:

I want to create a list of order items; for each item, I want to display an "Item ID" and "Address Line" field; the data of the former field comes from a child element on the item, but the data from the latter must be fetched from a sibling of the item's parent using an unique id that is referenced in the item.

I've created a simplified xml data source and report in in order to illustrate the problem. The xml data is defined as follows:

<data>
<productorder>
    <item>
        <id>10001</id>
        <installationAddressId>1</installationAddressId>
    </item>
    <item>
        <id>10002</id>
        <installationAddressId>3</installationAddressId>
    </item>
</productorder>
<address>
    <id>1</id>
    <addressLine>Street 1, 12345 Berlin Germany</addressLine>
</address>
<address>
    <id>2</id>
    <addressLine>Street 2, 12345 Berlin Germany</addressLine>
</address>
<address>
    <id>3</id>
    <addressLine>Street 3, 12345 Berlin Germany</addressLine>
</address>
</data>

The simple (incorrect) report is:

<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="SimpleOrderItemReport" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="0d316a3a-9d1c-4483-bf7d-d1bd9165e0cb">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="SimpleOrderItemReportDataAdapter"/>
<subDataset name="OrderItemList" uuid="c1a7dc7b-2bc3-4f1f-bab9-ae6e3b207739">
    <property name="com.jaspersoft.studio.data.defaultdataadapter" value="SimpleOrderItemReportDataAdapter"/>
    <queryString language="xPath">
        <![CDATA[/data/productorder/item]]>
    </queryString>
    <field name="id_1" class="java.lang.String">
        <fieldDescription><![CDATA[id]]></fieldDescription>
    </field>
    <field name="installationAddressId_1" class="java.lang.String">
        <fieldDescription><![CDATA[installationAddressId]]></fieldDescription>
    </field>
    <field name="addressLine" class="java.lang.String">
        <fieldDescription><![CDATA[../../address/addressLine]]></fieldDescription>
    </field>
</subDataset>
<queryString language="xPath">
    <![CDATA[/data]]>
</queryString>
<detail>
    <band height="125" splitType="Stretch">
        <componentElement>
            <reportElement x="124" y="19" width="390" height="30" uuid="84a1e8b2-13df-4391-9cdd-39a9d4d79434"/>
            <jr:list xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd">
                <datasetRun subDataset="OrderItemList" uuid="0d232993-a132-45ff-813c-d00d8a685d9e">
                    <dataSourceExpression><![CDATA[((net.sf.jasperreports.engine.data.JRXmlDataSource)$P{REPORT_DATA_SOURCE}).subDataSource("/data/productorder/item")]]></dataSourceExpression>
                </datasetRun>
                <jr:listContents height="30" width="390">
                    <textField>
                        <reportElement x="40" y="0" width="40" height="30" uuid="2b9a8530-32e3-4ecb-8dc4-3d8d9d30b191"/>
                        <textElement textAlignment="Left" verticalAlignment="Top"/>
                        <textFieldExpression><![CDATA[$F{id_1}]]></textFieldExpression>
                    </textField>
                    <textField>
                        <reportElement x="190" y="0" width="200" height="30" uuid="d570993d-201b-4a43-9147-73036dd0cf11"/>
                        <textElement textAlignment="Left" verticalAlignment="Top"/>
                        <textFieldExpression><![CDATA[$F{addressLine}]]></textFieldExpression>
                    </textField>
                    <staticText>
                        <reportElement x="0" y="0" width="40" height="30" uuid="b96b0be3-fa58-42f1-8270-004a08a7c3df"/>
                        <textElement verticalAlignment="Top"/>
                        <text><![CDATA[Item ID:]]></text>
                    </staticText>
                    <staticText>
                        <reportElement x="90" y="0" width="100" height="30" uuid="f85e298c-e3e0-42e3-bd0d-fc7c7808c2f1"/>
                        <textElement verticalAlignment="Top"/>
                        <text><![CDATA[Address Line:]]></text>
                    </staticText>
                </jr:listContents>
            </jr:list>
        </componentElement>
    </band>
</detail>
</jasperReport>

For the xml data that was provided above, I want to see the following two rows in the report:

  1. Item ID: 10001 Address Line: Street 1, 12345 Berlin Germany
  2. Item ID: 10002 Address Line: Street 3, 12345 Berlin Germany

I can't seem to find a field description or xpath query that would achieve this goal. Does anyone know how to do get my desired result?

回答1:

If you use JasperReports with Xalan as XPath executer (and that's the default configuration, see net.sf.jasperreports.xpath.executer.factory), you can use the XSLT current function to refer to the current node.

In your case, the field should look like this:

<field name="addressLine" class="java.lang.String">
    <fieldDescription><![CDATA[../../address[id = current()/installationAddressId]/addressLine]]></fieldDescription>
</field>