Chapter 19. Developing a Report Rendering Extension

This chapter describes how to develop a report rendering extension using the Eclipse PDE with sample CSV and XML report rendering extensions as the examples. Developing a BIRT report rendering extension is discussed in the following sections:

Understanding a report rendering extension

Developing a CSV report rendering extension

Developing an XML report rendering extension

Understanding a report rendering extension

BIRT Report Engine provides report rendering extensions that render a report in HTML, PDF, XLS, PostScript, Microsoft Word and PowerPoint. This chapter provides sample implementations of customized CSV and XML report rendering extensions, org.eclipse.birt.report.engine.emitter.csv and org.eclipse.birt.report.engine.emitter.xml. The sample code creates plug-ins that write the data contents of a report to a file in the specified format.

A BIRT plug-in typically loads and runs in the BIRT Report Engine environment rather than the Eclipse run-time environment. BIRT implements a separate plug-in loading framework for the BIRT Report Engine, giving the BIRT Report Engine complete control of report execution. A BIRT engine plug-in extension is functionally similar to an Eclipse plug-in extension.

A rendering extension adds an emitter to the BIRT Report Engine framework by implementing the extension point, org.eclipse.birt.report.engine.emitters.

The XML schema file, org.eclipse.birt.report.engine/schema/emitters.exsd, describes this extension point.

The extension point enables support for a new output format in the presentation engine. The BIRT plug-in registry uses this extension point to discover all supported output formats specified for the report engine environment.

This book uses the customized CSV and XML report rendering extensions in this chapter as examples of how to create a report rendering extension. The BIRT user interface also provides a built-in data extraction feature that can export data from a report document in CSV, TSV (tab-separated values), and XML formats.

You can download the source code for the CSV and XML report rendering extension examples at http://www.actuate.com/birt/contributions. For reference documentation, see the BIRT Report Engine API Javadoc in Eclipse Help for the org.eclipse.birt.report.engine.emitter and org.eclipse.birt.report.engine.content packages.

Developing a CSV report rendering extension

The CSV report rendering extension extends the functionality defined by the org.eclipse.birt.report.engine.emitter package, which is part of the org.eclipse.birt.report.engine plug-in. In developing the CSV report rendering extension, you perform the following tasks:

• Create a CSV report rendering extension project in the Eclipse PDE.

• Define the dependencies.

• Declare the emitters extension point.

• Implement the emitter interfaces.

• Test the extension in the designer and in the run-time environments.

Creating a CSV report rendering plug-in project

Create a new plug-in project for the CSV report rendering extension using the Eclipse PDE.

How to create the CSV report rendering plug-in project

1 From the Eclipse PDE menu, choose File→New→Project. New Project appears.

2 In New Project, select Plug-in Project. Choose Next. New Plug-in Project appears.

3 In Plug-in Project, modify the settings, as shown in Table 19-1.

Table 19-1 Values for CSV Emitter Plug-in Project fields

image

Plug-in Project appears as shown in Figure 19-1. Choose Next. Content appears.

Figure 19-1 Values for CSV Emitter Plug-in Project

image

4 In Content, modify the settings, as shown in Table 19-2.

Table 19-2 Values for CSV Emitter Content fields

image

Content appears as shown in Figure 19-2. Choose Finish.

Figure 19-2 Values for Plug-in Content

image

The CSV report rendering extension project appears in the Eclipse PDE workbench, as shown in Figure 19-3.

Figure 19-3 CSV report rendering extension project

image

Defining the dependencies for the CSV report rendering extension

To compile and run the CSV report rendering example, you need to specify the list of plug-ins that must be available on the classpath of the extension.

How to specify the dependencies

1 On PDE Manifest Editor, choose Overview.

2 In Plug-in Content, choose Dependencies. Required Plug-ins contains the following plug-in:

org.eclipse.core.runtime

3 In Required Plug-ins, perform the following tasks:

1 Select org.eclipse.core.runtime and choose Remove.

org.eclipse.core.runtime no longer appears in Required Plug-ins.

2 Choose Add. Plug-in Selection appears.

3 In Plug-in Selection, hold down CTRL and select the org.eclipse.birt.report.engine plug-in.

Choose OK. Dependencies appears as shown in Figure 19-4.

Figure 19-4 The Dependencies page

image

Declaring the emitters extension point

In this step, you specify the extension point required to implement the CSV report rendering extension and add the extension element details. The extension point, org.eclipse.birt.report.engine.emitters, specifies the following properties that identify the extension point:

• ID

Optional identifier of the extension instance

• Name

Optional name of the extension instance

The extension point defines an emitter that specifies the output format for the plug-in, requiring definition of the following extension element properties:

• class

Java class that implements the IContentEmitter interface

• format

Output format that the emitter supports, such as csv

• mimeType

MIME type for the supported output format, such as text/csv

• id

Optional identifier of the emitter extension

• icon

Optional icon path of the emitter extension

• pagination

Optional setting that controls page breaks. When page-break-pagination is set, the pagination is based on the page break configuration. When no-pagination is set, the report output is on one page. When paper-size-pagination is set, the pagination is based on the content size.

• supportedImageFormats

The supported format for images. The CSV emitter in this example does not support images.

• outputDisplayNone

This property controls whether the hidden content is output in the final report. For example, if the user set the display to hidden, the content will not display in the final output.

On the client side, the user has the option to invoke scripts that reset the display to block or show the hidden content. To choose not to display the output, set outputDisplayNone to true. This setting is valid only for HTML/XHTML.

• isHidden

Used to determine whether the format is shown in UI. This property is not used in the current release.

• needOutputResultSet

Represents whether the emitter needs to output the query result set in the final output. If the property is set to true, the emitter implementation can access the result set in the content object.

To specify the extension point and extension element details use the Eclipse PDE.

How to specify the extension point

1 On PDE Manifest Editor, choose Extensions.

2 In All Extensions, choose Add. New Extension—Extension Point Selection appears.

3 In Available extension points, select the following plug-in:

org.eclipse.birt.report.engine.emitters

Choose Finish. Extensions appears, as shown in Figure 19-5.

Figure 19-5 Emitter plug-in extension on the Extensions page

image

All Extensions lists the extension point, org.eclipse.birt.report.engine.emitters, and the extension element, emitter. Extension Element Details contains the element details list specified in the XML schema file, emitters.exsd.

4 In Extension Element Details, specify the properties for the CSV emitter extension element, emitter, as shown in Table 19-3.

Table 19-3 Property values for the CSV Emitter extension element

image

Extension Element Details appears as shown in Figure 19-6.

Figure 19-6 Property values for the emitter extension

image

PDE Manifest Editor automatically updates plugin.xml.

Understanding the sample CSV report rendering extension

The CSV report rendering extension described in this chapter is a simplified example that illustrates how to create a report rendering plug-in using the Eclipse PDE. The extension extends the report emitter interfaces in org.eclipse.birt.report.engine.emitters.

The CSV report rendering extension example exports only the data presented by table elements to a CSV output file. The lines of the CSV output file contain only column data separated by commas. The sample CSV report emitter does not export images, charts, or hyperlinks.

The extension example creates the CSV output file in the same folder as the exported report. The output file name is the name of the report with a .csv extension. The extension example does not support nested tables.

The following section provides a general description of the code-based extensions a developer must make to complete the development of the CSV report rendering extension after defining the plug-in framework in the Eclipse PDE.

Understanding the CSV report rendering extension package

The implementation package for the CSV report rendering extension example, org.eclipse.birt.report.engine.emitter.csv, contains the following classes:

• CSVPlugin

Defines the methods for starting, managing, and stopping a plug-in instance.

• CSVRenderOption

Integrates the plug-in with BIRT Report Engine, specifying configuration information. CSVRenderOption extends RenderOption, specifying the output format as CSV.

• CSVReportEmitter

Extends org.eclipse.birt.report.engine.emitter.ContentEmitterAdapter. CSVReportEmitter handles the start and end processing that renders the report container.

• CSVTags.java

Defines the comma and new line String settings used when writing to the CSV file.

• CSVWriter

CSVWriter writes the data and label contents of the report to the CSV file, using a call to java.io.PrintWriter.print( ). CSVWriter also uses org.eclipse.birt.report.engine.emitter.XMLWriter with java.util.logging.Logger to write log messages at specified levels.

The following sections contain specific information about implementation details for the classes in the CSV report rendering extension package.

Understanding CSVReportEmitter

CSVReportEmitter is the class that extends ContentEmitterAdapter to output the text content of the report items to a CSV file. CSVReportEmitter instantiates the writer and emitter objects.

CSVReportEmitter implements the following methods:

• CSVReportEmitter( ) instantiates the CSV report emitter class as an org.eclipse.birt.report.engine.presentation.ContentEmitterVisitor object, to perform emitter operations, as shown in Listing 19-1.

Listing 19-1 The CSVReportEmitter( ) constructor


public CSVReportEmitter( )
{
   contentVisitor = new ContentEmitterVisitor( this );
}

• initialize( ) performs the following operations required to create an output stream that writes the text contents of the report to the CSV file:

• Obtains a reference to the IEmitterServices interface. Instantiates the file and output stream objects, using the specified settings.

• Instantiates the CSV writer object.

Listing 19-2 shows the initialize( ) method.

Listing 19-2 The initialize( ) method


public void initialize( IEmitterServices services )
{
   this.services = services;
   Object fd = services.getOption
      ( RenderOptionBase.OUTPUT_FILE_NAME );
   File file = null;
   try
   {
      if ( fd != null )
      {
         file = new File( fd.toString( ) );
         File parent = file.getParentFile( );
         if ( parent != null && !parent.exists( ) )
         {
            parent.mkdirs( );
         }
         out = new BufferedOutputStream( new
            FileOutputStream( file ) );
      }
   }
   catch ( FileNotFoundException e )
   {
      logger.log( Level.WARNING, e.getMessage( ), e );
   }
   if ( out == null )
   {
      Object value = services.getOption
         ( RenderOptionBase.OUTPUT_STREAM );
      if ( value != null && value instanceof OutputStream )
      {
         out = (OutputStream) value;
      } else
      {
         try
         {
            file = new File( REPORT_FILE );
            out =
               new BufferedOutputStream
                  ( new FileOutputStream( file ) );
         }
         catch ( FileNotFoundException e )
         {
            logger.log( Level.SEVERE, e.getMessage( ), e );
         }
      }
   }
   writer = new CSVWriter( );
}

• start( ) performs the following operations:

• Obtains a reference to the IReportContent interface.

• Sets the start emitter logging level and writes to the log file.

• Opens the output file and specifies the encoding scheme as UTF-8.

• Starts the CSV writer

Listing 19-3 shows the start( ) method.

Listing 19-3 The start( ) method


public void start( IReportContent report )
{
   logger.log( Level.FINE,
      "[CSVReportEmitter] Start emitter." );
   this.report = report;
   writer.open( out, "UTF-8" );
   writer.startWriter( );
}

• end( ) performs the following operations:

• Sets the end report logging level and writes to the log file.

• Ends the write process and closes the CSV writer.

• Closes the output file.

Listing 19-4 shows the end( ) method.

Listing 19-4 The end( ) method


public void end( IReportContent report )
{
   logger.log( Level.FINE,
      "[CSVReportEmitter] End report." );
   writer.endWriter( );
   writer.close( );
   if( out != null )
   {
      try
      {
         out.close( );
      }
      catch ( IOException e )
      {
         logger.log( Level.WARNING, e.getMessage( ), e );
      }
   }
}

Understanding the other CSVReportEmitter methods

The CSVReportEmitter class defines the following additional methods, called at different phases of the report generation process, that provide access to emitters, render options, and style information to facilitate BIRT Report Engine processing:

• startTable( )

When writing to the CSV file, the CSV rendering extension must consider the cell position in the row because a comma appears as the last character in all the cells except the last cell in the row.

The startTable( ) method uses ITableContent.getColumnCount( ) to get information about table column numbers and to initialize the protected columnNumbers variable, as shown in Listing 19-5.

Listing 19-5 The startTable( ) method


public void startTable( ITableContent table )
{
   assert table != null;
   tableDepth++;
   columnNumbers = table.getColumnCount( );
...
}

• startRow( )

At the start of each row, startRow( ) performs the following operations:

• Calls isRowInFooterBand( ) to determine if the row is in the header or footer band of a table or group

• Sets exportElement to false if the current table element belongs to a table header, footer, or is an image, since this extension exports only label and data elements to the CSV file

• Sets the currentColumn indicator to 0

Listing 19-6 shows the startRow( ) code.

Listing 19-6 The startRow( ) method


public void startRow( IRowContent row )
{
   assert row != null;
   if ( tableDepth > 1) {
      logger.log( Level.FINE,
      "[CSVTableEmitter] Nested tables are not supported." );
      return;
   }
   if ( isRowInFooterBand( row ) )
      exportElement = false;
   currentColumn = 0;
}

• isRowInFooterBand( )

If the row is an instance of band content, isRowInFooterBand( ) checks the band type. If the band type is a footer, the method returns true, as shown in Listing 19-7.

Listing 19-7 The isRowInFooterBand( ) method


boolean isRowInFooterBand( IRowContent row )
{
   IElement parent = row.getParent( );
   if ( !( parent instanceof IBandContent ) )
   {
      return false;
   }
   IBandContent band = ( IBandContent )parent;
   if ( band.getBandType( ) == IBandContent.BAND_FOOTER )
   {
      return true;
   }
   return false;
}

• startText( )

If the element is exportable, startText( ) writes the text value to the CSV output file, as shown in Listing 19-8.

Listing 19-8 The startText( ) method


public void startText( ITextContent text )
{
   if ( tableDepth > 1) {
      logger.log( Level.FINE,
         "[CSVTableEmitter] Nested tables are not supported."
         );
      return;
   }
   String textValue = text.getText( );
   if (exportElement)
   {
      writer.text( textValue );
   }
}

• endCell( )

If the current cell is not the last column in the row and the element is exportable, endCell( ) writes a comma to the CSV output file, as shown in Listing 19-9.

Listing 19-9 The endCell( ) method


public void endCell( ICellContent cell )
{
   if ( ( currentColumn < columnNumbers )
      && exportElement )
   {
      writer.closeTag( CSVTags.TAG_COMMA );
   }
}

• endRow( )

At the end of each row, if the element is exportable, endRow( ) writes a new line or carriage return to the CSV output file, as shown in Listing 19-10.

Listing 19-10 The endRow( ) method


public void endRow( IRowContent row )
   if ( exportTableElement )
      writer.closeTag( CSVTags.TAG_CR );
   exportElement = true;
}

Understanding CSVTags

The CSVTags class defines the contents of the comma and new line tags, as shown in Listing 19-11.

Listing 19-11 The CSVTags class


public class CSVTags
{
   public static final String TAG_COMMA = "," ;
   public static final String TAG_CR = " " ;
}

Understanding CSVWriter

The CSVWriter class writes the closing tags defined in CSVTags, as shown in Listing 19-12.

Listing 19-12 The closeTag( ) method


public void closeTag( String tagName )
{
   printWriter.print( tagName );
}

Understanding CSVRenderOption

The org.eclipse.birt.report.engine.emitter.csv.CSVRenderOption class extends org.eclipse.birt.report.engine.api.RenderOption to add the CSV rendering option to the BIRT Report Engine run time, as shown in Listing 19-13.

Listing 19-13 The CSVRenderOption class


public class CSVRenderOption extends RenderOption {
   public static final String CSV = "CSV";
      public CSVRenderOption( ) {
   }
}

Testing the CSV report rendering plug-in

You can use the new CSV emitter directly in the BIRT Report Designer or programmatically when you run and render reports using the BIRT Report Engine API. This section provides instructions on how to test the CSV emitter in both scenarios.

How to launch the CSV report rendering plug-in

1 From the Eclipse PDE menu, choose Run—Run Configurations. On Run Configurations, right-click Eclipse Application. Choose New.

2 Create a configuration to launch an Eclipse application by performing the following tasks:

1 In Name, type:

CSVEmitter

2 On Main, in Location, type:

C:TestCSVEmitter

Run Configurations appears as shown in Figure 19-7.

Figure 19-7 Creating the CSVEmitter run configuration

image

3 Choose the Plug-ins tab to select the list of plug-ins that you want to launch with the Run configuration.

4 In Launch with, choose

plug-ins selected below only

from the drop-down list, as shown in Figure 19-8.

Figure 19-8 Adding the csv emitter plug-in to the launch configuration

image

5 In Plug-ins, select Workspace and Target Platform.

6 Choose Run to launch the run-time Eclipse workbench. A new instance of Eclipse opens up.

How to preview a BIRT report in CSV format in BIRT Report Designer

The BIRT Report Designer discovers the new CSV custom emitter and displays the new rendering format in the Run→ViewReport menu.

To preview a BIRT report in CSV format, perform the following tasks:

1 In the new Eclipse workbench, switch to BIRT Report Design perspective.

2 In BIRT Report Designer perspective, open the BIRT report, you want to render in CSV format.

3 Choose Run→ViewReport→As CSV from the main menu, as shown in Figure 19-9.

Figure 19-9 Preview a report in CSV format

image

4 A new browser window opens and a file download message appears, as shown in Figure 19-10.

Figure 19-10 File Download message

image

5 Choose Save and select the location to save the CSV report.

6 Open the report using any editor or Excel to validate the CSV output.

How to render a BIRT report in CSV format programmatically

To test the CSV report rendering example, you create a Java application that runs a report design in an installation of the BIRT run-time engine. BIRT provides a run-time engine that runs in a stand-alone Java EE application server environment and a preview engine that runs in the BIRT Report Designer.

To test the CSV report rendering plug-in, you perform the following tasks:

• Build the org.eclipse.birt.report.engine.emitter.csv plug-in.

• Deploy the plug-in to the BIRT run-time engine directory.

• Create a report design containing a table that maps to a data source and data set.

• Create a Java application that runs the report design and writes the table data to a CSV file.

• Run the application and examine the output in the CSV file.

The test environment must include the BIRT run-time engine.

The following sections describe the steps required to build and export the plug-ins, create the Java application and report design, and test the plug-in example.

How to build and export the org.eclipse.birt.report.engine.emitter.csv plug-in

On PDE Manifest Editor, perform the following tasks:

1 Choose the Build tab, and specify the binary build configuration for the plug-in to include the following items:

• META-INFMANIFEST.MF

• binorg.eclipse.birt.report.engine.emitter.csv

• plugin.xml

2 On Overview, in Exporting, choose the Export Wizard and perform the following tasks:

1 In Options, choose Package plug-ins as individual JAR archives and Allow for binary cycles in target platform, as shown in Figure 19-11.

Figure 19-11 Exporting a plug-in option

image

2 In Destination, choose the directory, $INSTALL_DIRirt-runtime-2_6_0ReportEngine, as shown in Figure 19-12. Choose Finish.

Figure 19-12 Exporting a plug-in to BIRT run-time engine

image

The org.eclipse.birt.report.engine.emitter.csv JAR file deploys to the $INSTALL_DIRirt-runtime-2_6_0ReportEngineplugins directory.

How to create the report execution Java project

1 In Eclipse workbench, choose File→New→Project. New Project appears.

2 In New Project—Select a wizard, perform the following tasks:

1 In Wizards, choose Java Project. Choose Next. Create a Java Project appears.

2 In Create a Java Project, perform the following tasks:

1 In Project name, type:

ExecuteCSVReport

2 Choose Next. Java Settings—Source appears.

3 In Java Settings, choose Libraries. Java Settings—Libraries appears.

4 In Libraries, perform the following tasks:

1 Choose Add External JARS. JAR Selection opens.

2 On JAR Selection, in Look in, navigate to $INSTALL_DIRirt-runtime-2_6_0ReportEnginelib and, holding down CTRL, select the following libraries:

• chartengineapi.jar

• com.ibm.icu_4.2.1.<version>.jar

• commons-cli-1.0.jar

• coreapi.jar

• crosstabcoreapi.jar

• dataadapterapi.jar

• dataaggregationapi.jar

• dataextraction.jar

• dteapi.jar

• emitterconfig.jar

• engineapi.jar

• flute.jar

• js.jar

• modelapi.jar

• modelodaapi.jar

• odadesignapi.jar

• org.apache.commons.codec_1.3.0.jar

• org.eclipse.emf.common_2.6.0.<version>.jar

• org.eclipse.emf.ecore_2.6.0.<version>.jar

• org.eclipse.emf.ecore.xmi_2.5.0.<version>.jar

• org.w3c.css.sac_1.3.0.<version>.jar

• scriptapi.jar

Choose Open.

3 On JAR Selection, in Look in, navigate to $INSTALL_DIRirt-runtime-2_6_0ReportEngineplugins and select org.eclipse.birt.report.engine.emitter.csv.jar. Choose Open.

Choose Finish. In Package Explorer, the ExecuteCSVReport project appears.

How to create the Java report execution class

1 In Eclipse workbench, choose File→New→Class. New Java Class appears.

2 On New Java Class, perform the following tasks:

1 In Source folder, type:

ExecuteCSVReport/src

2 In Name, type:

ExecuteCSVReport

3 In Which method stubs would you like to create?, perform the following tasks:

1 Select Public static void main(Strings[ ] args).

2 Deselect Constructors from superclass.

3 Deselect Inherited abstract methods.

Choose Finish.

In Package Explorer, ExecuteCSVReport.java appears in the ExecuteCSVReport project.

3 Open ExecuteCSVReport.java in Java Editor, and add the required code. The ExecuteCSVReport code is discussed later in this chapter.

4 In Eclipse workbench, compile the project by choosing Project→Build Project.

How to run the CSV report rendering extension

To run the CSV report rendering extension, using the ExecuteCSVReport application, perform the following tasks:

1 In Eclipse workbench, right-click ExecuteCSVReport, and choose Run As→Run Configurations. Run Configurations appears.

2 In Run Configurations, perform the following tasks:

1 In Run Configurations, right-click JavaApplication. Choose New.

2 A New Configuration appears as shown in Figure 19-13. Keep the values set by default.

Figure 19-13 Creating the ExecuteCSVReport Run Configuration

image

3 Choose Apply.

3 To run the Java application using the launch configuration, choose Run.

How to view the CSV report rendering extension file output

1 In Eclipse, navigate to the directory containing the CSV output file. The output CSV file is saved to the following location:

C:TestCSVEmitterExecuteCSVReport eports

2 Using a text editor or other tool, open the file, and view its contents.

Figure 19-14 shows the CSV output.

Figure 19-14 CSV output

image

The XML source code for the report design used in this example is discussed later in this chapter.

About ExecuteCSVReport class

The ExecuteCSVReport class uses BIRT Engine API to run a BIRT report and render the output in CSV format. The custom CSV emitter writes the text-based elements of the report to a file. The ExecuteCSVReport class performs the following operations:

• Configures the report engine

• Sets the log configuration and logging level

• Starts the platform and loads the plug-ins

• Gets the report engine factory object from the platform and creates the report engine

• Opens the report design

• Creates a task to run and render the report

• Set the rendering options, such as the output file and format

• Runs the report and destroys the engine

• Shuts down the engine

Listing 19-14 shows the code for the ExecuteCSVReport class in the CSV report rendering extension example.

Listing 19-14 The ExecuteCSVReport class code


import java.util.logging.Level;
import org.eclipse.birt.core.framework.Platform;
import org.eclipse.birt.report.engine.api.EngineConfig;
import org.eclipse.birt.report.engine.api.CSVRenderOption;
import org.eclipse.birt.report.engine.api.IReportEngine;
import
   org.eclipse.birt.report.engine.api.IReportEngineFactory;
import org.eclipse.birt.report.engine.api.IReportRunnable;
import org.eclipse.birt.report.engine.api.IRunAndRenderTask;

public class ExecuteCSVReport {

   static void executeCSVReport( ) throws Exception
   {
      IReportEngine engine=null;
      EngineConfig config = null;
      config = new EngineConfig( );
      config.setEngineHome
         ( "C:/birt-runtime-2_6_0/ReportEngine" );
      config.setLogConfig( "c:/birt/logs", Level.FINE );
      Platform.startup( config );
      IReportEngineFactory factory =
         ( IReportEngineFactory ) Platform.createFactoryObject
         ( IReportEngineFactory
            .EXTENSION_REPORT_ENGINE_FACTORY );
      engine = factory.createReportEngine( config );
      engine.changeLogLevel( Level.FINEST );

      IReportRunnable design =
         engine.openReportDesign
            ( "reports/csvTest.rptdesign" );
      IRunAndRenderTask task =
         engine.createRunAndRenderTask( design );
      String format = "CSV";
      CSVRenderOption csvOptions = new CSVRenderOption( );
      csvOptions.setOutputFormat( format );
      csvOptions.setOutputFileName( "reports/csvTest.csv" );
      task.setRenderOption( csvOptions );
      task.run( );

      task.close( );
      engine.destroy( );
      Platform.shutdown( );
      System.out.println("We are done!!!");
   }
   public static void main(String[] args) {
      try
      {
         executeCSVReport( );
      }
      catch ( Exception e )
      {
         e.printStackTrace();
      }
   }
}

About the report design XML code

The XML file for the report design, csvTest.reportdesign, contains the following source code settings, as specified in the report design:

• Data sources, including the ODA plug-in extension ID, driver class, URL, and user

• Data sets, including the ODA JDBC plug-in extension ID, result set properties, and query text

• Page setup, including the page footer

• Body, containing the table structure and properties for the bound data columns, including the header, footer, and detail rows

The report design example specifies a data source that connects to org.eclipse.birt.report.data.oda.sampledb, the BIRT Classic Models sample database. Listing 19-15 shows the XML source code for the report design used to test the CSV rendering example. The sample application runs the report from the reports subfolder in the ExecuteCSVReport project.

Listing 19-15 The report design XML code


<?xml version="1.0" encoding="UTF-8"?>
<report xmlns="http://www.eclipse.org/birt/2005/design"
   version="3.2.21" id="1">
   <property name="createdBy">
   Eclipse BIRT Designer Version 2.6.0.v20100531 Build &lt;2.6
   .0.v20100609-1613> </property>
   <property name="units">in</property>
      <data-sources>
         <oda-data-source
            extensionID=
               "org.eclipse.birt.report.data.oda.jdbc"
               name="Data Source" id="2">
               <list-property name="privateDriverProperties">
                  <ex-property>
                     <name>contentBidiFormatStr</name>
                     <value>ILYNN</value>
                  </ex-property>
                  <ex-property>
                     <name>metadataBidiFormatStr</name>
                     <value>ILYNN</value>
                  </ex-property>
               </list-property>
            <property
               name="odaDriverClass">
               org.eclipse.birt.report.data.oda.sampledb.Driver
            </property>
            <property
               name="odaURL">jdbc:classicmodels:sampledb
            </property>
            <property name="odaUser">ClassicModels</property>
         </oda-data-source>
      </data-sources>
      <data-sets>
         <oda-data-set
            extensionID=
               "org.eclipse.birt.report.data.oda.jdbc
                  .JdbcSelectDataSet" name="Data Set" id="3">
            <list-property name="columnHints">
               <structure>
                  <property name=
                        "columnName">PRODUCTNAME</property>
                  <text-property name=
                     "displayName">PRODUCTNAME</text-property>
                  <text-property name=
                        "displayName">PRODUCTNAME</text-property>
               </structure>
               <structure>
                  <property name=
                        "columnName">QUANTITYINSTOCK</property>
                  <text-property name=
                        "displayName">QUANTITYINSTOCK</text-property>
               </structure>
               <structure>
                  <property name="columnName">MSRP</property>
                  <text-property name=
                     "displayName">MSRP</text-property>
               </structure>
            </list-property>
      <structure name="cachedMetaData">
            <list-property name="resultSet">
               <structure>
                  <property name="position">1</property>
                  <property name=
                     "name">PRODUCTNAME
                  </property>
                  <property
                     name="dataType">string
                  </property>
               </structure>
               <structure>
                  <property name="position">2</property>
                  <property
                     name="name">QUANTITYINSTOCK
                  </property>
                  <property
                     name="dataType">integer
                  </property>
               </structure>
               <structure>
                  <property name="position">3</property>
                  <property name="name">MSRP</property>
                  <property name="dataType">float</property>
               </structure>
            </list-property>
         </structure>
         <property name="dataSource">Data Source</property>
            <list-property name="resultSet">
                  <structure>
                        <property name="position">1</property>
                        <property name="name">PRODUCTNAME
                        </property>
                        <property name=
                              "nativeName">PRODUCTNAME</property>
                        <property name="dataType">string
                        </property>
                        <property name=
                              "nativeDataType">12</property>
                  </structure>
                  <structure>
                        <property name="position">2</property>
                        <property name="name">QUANTITYINSTOCK
                        </property>
                        <property name=
                              "nativeName">QUANTITYINSTOCK
                              </property>
                        <property name="dataType">integer
                        </property>
                        <property name="nativeDataType">4
                        </property>
                  </structure>
                  <structure>
                        <property name="position">3</property>
                        <property name="name">MSRP</property>
                        <property name="nativeName">MSRP
                        </property>
                        <property name="dataType">float
                        </property>
                        <property name="nativeDataType">8
                        </property>
                  </structure>
            </list-property>
         <property name="queryText"><![CDATA [
            select CLASSICMODELS.PRODUCTS.PRODUCTNAME,
                     CLASSICMODELS.PRODUCTS.QUANTITYINSTOCK,
                     CLASSICMODELS.PRODUCTS.MSRP
            from CLASSICMODELS.PRODUCTS]]</xml-property>
      </oda-data-set>
   </data-sets>
   <page-setup>
      <simple-master-page name="Simple MasterPage" id="4">
         <property name="topMargin">1in</property>
         <property name="leftMargin">1.25in</property>
         <property name="bottomMargin">1in</property>
         <property name="rightMargin">1.25in</property>
         <page-footer>
            <text id="5">
               <property name="contentType">html</property>
               <text-property name="content">
                  <![CDATA[<value-of>new Date()</value-of>]]>
               </text-property>
            </text>
         </page-footer>
      </simple-master-page>
   </page-setup>
   <body>
      <table id="6">
         <property name="width">100%</property>
         <property name="dataSet">Data Set</property>
         <list-property name="boundDataColumns">
            <structure>
               <property name="name">PRODUCTNAME</property>
               <expression
                  name="expression">dataSetRow["PRODUCTNAME"]
               </expression>
            </structure>
            <structure>
               <property
                  name="name">QUANTITYINSTOCK
               </property>
               <expression
                  name="expression">
                  dataSetRow["QUANTITYINSTOCK"]
               </expression>
            </structure>
            <structure>
               <property name="name">MSRP</property>
               <expression
                  name="expression">dataSetRow["MSRP"]
               </expression>
            </structure>
         </list-property>
         <column id="28"/>
         <column id="29"/>
         <column id="30"/>
         <header>
            <row id="7">
               <cell id="8">
                  <property name="colSpan">3</property>
                  <property name="rowSpan">1</property>
                  <property name="textAlign">center</property>
                  <label id="9">
                        <property
                           name="fontSize">x-large
                        </property>
                        <property
                           name="fontWeight">bold
                        </property>
                        <property
                           name="textAlign">center
                        </property>
                        <list-property name="visibility">
                              <structure>
                                    <property name=
                                       "format">all</property>
                                    <expression name=
                                          "valueExpr">true
                                    </expression>
                              </structure>
                        </list-property>
                        <text-property
                        name="text">Report
                        </text-property>
                     </label>
               </cell>
            </row>
            <row id="10">
               <cell id="11">
                  <label id="12">
                     <text-property
                        name="text">PRODUCTNAME
                     </text-property>
                  </label>
               </cell>
               <cell id="13">
                  <label id="14">
                     <text-property
                        name="text">QUANTITYINSTOCK
                     </text-property>
                  </label>
               </cell>
               <cell id="15">
                  <label id="16">
                     <text-property
                        name="text">MSRP
                     </text-property>
                  </label>
               </cell>
            </row>
         </header>
         <detail>
            <row id="17">
               <cell id="18">
                  <data id="19">
                     <property
                        name="resultSetColumn">PRODUCTNAME
                     </property>
                  </data>
               </cell>
               <cell id="20">
                  <data id="21">
                     <property
                        name="resultSetColumn">QUANTITYINSTOCK
                     </property>
                  </data>
               </cell>
               <cell id="22">
                  <data id="23">
                     <property
                        name="resultSetColumn">MSRP
                     </property>
                  </data>
               </cell>
            </row>
         </detail>
         <footer>
            <row id="24">
               <cell id="25"/>
               <cell id="26"/>
               <cell id="27"/>
            </row>
         </footer>
      </table>
   </body>
</report>

BIRT Report Engine can render a report design for output using a standard emitter extension or a customized emitter extension, such as this CSV rendering example.

Developing an XML report rendering extension

The sample XML report rendering extension is a plug-in that can export BIRT report data in XML format. Typically, report developers render BIRT report data to XML to enable sharing data with another application.

For example, business-to-business (B2B) systems must transmit data to customers and trading partners in a consistent way that supports interoperability according to Electronic Data Interchange (EDI) standards. These systems use specialized forms of XML such as Electronic Business eXtensible Markup Language (ebXML). A custom XML report rendering extension can render BIRT report data in a format that is consistent with this established standard.

The sample XML report rendering extension provides the following capabilities:

• Exports BIRT report data in XML format The XML report rendering plug-in renders each report element and writes to the output file, <report_name>.xml.

• Defines a public API for rendering BIRT reports in XML format The plug-in extends the functionality defined by the org.eclipse.birt.report.engine.emitter extension point defined in the org.eclipse.birt.report.engine plug-in.

• Supports the user specifying an XML schema for formatting output During the rendering process, the sample plug-in processes all the elements in the report design, exporting XML properties and related data to the output file. Optionally, the plug-in supports mapping the report elements to an XML schema to provide additional formatting for output.

The plug-in defines these mappings in the property file, <report_name>.xmlemitter. The plug-in reads the property file at run time and loads the custom tags.

Creating an XML report rendering plug-in project

Create a new plug-in project for the XML report rendering extension using the Eclipse PDE.

How to create the XML report rendering plug-in project

1 From the Eclipse PDE menu, choose File→New→Project. New Project appears.

2 On New Project, select Plug-in Project. Choose Next. New Plug-in Project appears.

3 In Plug-in Project, modify the settings, as shown in Table 19-4.

Table 19-4 Values for XML Emitter Plug-in Project fields

image

Choose Next. Plug-in Content appears.

4 In Plug-in Content, modify the settings, as shown in Table 19-5.

Table 19-5 Values for XML Emitter Plug-in Content fields

image

Choose Finish.

The XML report rendering extension project appears in the Eclipse PDE workbench, as shown in Figure 19-15.

Figure 19-15 XML report rendering extension project

image

Defining the dependencies for the XML report rendering extension

To compile and run the XML report rendering example, specify the org.eclipse.birt.report.engine plug-in, which must be available on the classpath for the XML rendering extension.

Declaring the emitters extension point

To implement the XML report rendering extension, specify the org.eclipse.birt.report.engine.emitters extension point and add the extension element details.

How to specify the extension point

1 On PDE Manifest Editor, choose Extensions.

2 In All Extensions, choose Add. New Extension—Extension Point Selection appears.

3 In Available extension points, select the following plug-in:

org.eclipse.birt.report.engine.emitters

Choose Finish.

4 In All Extensions, right-click the extension point, org.eclipse.birt.report.engine.emitters, and choose the extension element, emitter.

5 In Extension Element Details, specify the properties for the XML emitter extension element, emitter, as shown in Table 19-6.

Table 19-6 Property values for the XML Emitter extension element

image

Understanding the sample XML report rendering extension

The XML report rendering extension extends the report emitter interfaces and XML writer in org.eclipse.birt.report.engine.emitter. The extension example provides access to the report container, pages, tables, rows, cells text, labels, data, images, hyperlinks, and other contents at different phases of the report generation process.

The example writes the contents of the report to an XML output file. The example creates the XML file in the same folder as the exported report. The output file name is the name of the report with a .xml extension. The example provides only limited error checking.

The following section provides a general description of the code-based extensions a developer must make to develop an XML report rendering extension after defining the plug-in framework in the Eclipse PDE.

Understanding the XML report rendering extension package

The implementation package for the XML report rendering extension example, org.eclipse.birt.report.engine.emitter.xml, contains the following classes:

• XMLPlugin

The plug-in run-time class for the report item extension example.

• XMLReportEmitter

Handles the start and end processing that renders the report container.

• XMLRenderOption

Integrates the plug-in with BIRT Report Engine, specifying configuration information, including the output format as XML.

• XMLTags.java

Defines the controls and associated property lists used when writing to the XML file.

• XMLFileWriter

Writes the XML version, text, image, data, label, and report tag content of the report to the XML output file.

• LoadExportSchema

Loads the XML schema file, if one exists, to replace the default values specified for the XML version, data, image, label, report tags, and text. An accessor method for each tag returns the value to XMLReportEmitter for output to the export file.

The following section contains more specific information about the implementation details for the classes in the XML report rendering extension package.

Understanding XMLReportEmitter

XMLReportEmitter writes the contents of the report to an XML file. XMLReportEmitter instantiates the writer and emitter objects and handles the start and end processing that renders the report container. XMLReportEmitter exports the XML version, data, image, label, report tag content, and text of the report to the XML output file.

XMLReportEmitter implements the following methods:

• XMLReportEmitter( ) instantiates the XML report emitter class as an org.eclipse.birt.report.engine.presentation.ContentEmitterVisitor object to perform emitter operations.

• initialize( ) performs the following operations required to create an output stream that writes the report contents to the XML file, similar to the CSV report rendering extension:

• Obtains a reference to the IEmitterServices interface

• Instantiates the file and output stream objects, using the specified settings

• Instantiates the XML file writer object

• start( ) performs the following operations:

• Obtains a reference to the IReportContent interface, containing accessor methods that get the interfaces to the report content emitters

• Sets the start emitter logging level and writes to the log file

• If an optional XML schema file exists, start( )

• locates the XML schema file for the report and

• instantiates a LoadExportSchema object to read the XML schema file

• Opens the output file, specifying the encoding scheme as UTF-8

• Starts the XML writer

• Writes the start tag, which specifies the <xml> tag, including the version and encoding schema, to the output file

• Writes the <report> tag, which specifies the report name and other properties in the report property list to the output file

Listing 19-16 shows the start( ) method.

Listing 19-16 The start( ) method


public void start( IReportContent report )
{
logger.log( Level.FINE,
   "[XMLReportEmitter] Start emitter." );
String fileName =
   report.getDesign( ).getReportDesign( ).getFileName( );
   int pos = fileName.indexOf("/");
   String fn = fileName.substring(pos+1,fileName.length( ));
   fileName = fn;
   if (fileName.length( ) > 0) {
      pos = fileName.lastIndexOf(".");
      if ( pos > 0 )
         fileName = fileName.substring(0, pos);

         fileName = fileName + ".xmlemitter";
         pos = fileName.lastIndexOf("/");
         String propFileName =
            fileName.substring( pos+1 , fileName.length( ) );
         String resourceFolder =
            report.getDesign().getReportDesign( )
                  .getResourceFolder( );
         if ( fileExists(resourceFolder + "/"
            + propFileName))
            exportSchema = new LoadExportSchema(
                  resourceFolder + "/" + propFileName );
         else
            if ( fileExists(fileName))
                  exportSchema =
                        new LoadExportSchema( fileName );
            else exportSchema = new LoadExportSchema( "" );
   }
   this.report = report;
   writer.open( out, "UTF-8" );
   writer.startWriter( );

   writer.closeTag( exportSchema.getExportStartTag( ));
   writer.closeTag( XMLTags.TAG_CR );

   String rp = exportSchema.getExportReportTag( );
   for (int i = 0;i < XMLTags.rPropList.length;i++)
   {
      if (exportSchema.isPropertyRequired(
            XMLTags.rPropList[i], rp))
      {
         String propValue = getReportPropValue(i,report);
         rp = replaceTag( rp, "??"
                       +XMLTags.rPropList[i], propValue );
      }
   }
   writer.writeCode( rp );
   writer.closeTag( XMLTags.TAG_CR );
}

• end( ) performs the following operations, similar to the CSV rendering extension:

• Sets the end report logging level and writes to the log file

• Ends the write process and closes the XML writer

• Closes the output file

Understanding the other XMLReportEmitter methods

The XMLReportEmitter class defines the following additional methods, called at different phases of the report generation process, that provide access to the report container, pages, tables, rows, cells text, labels, data, images, hyperlinks, and other contents. The following examples show the processing for a label:

• startLabel( ) performs the following operations:

• Calls LoadExportSchema.getExportLabelTag( ) to get the pattern for the <label> tag specified in the <report_name>.xmlemitter property file. If the property file does not exist, the plug-in uses the following default pattern specified in the LoadExportSchema class:

<label>??value</label>

• Iterates through the following label properties list defined in XMLTags to determine the properties required by the report:

static String[ ] lPropList =
   {"Bookmark","Height","Hyperlink","InlineStyle",
      "Name","TOC","Width","X","Y" };

• Calls getLabelPropValue( ) to obtain each required property value and substitute the value in the <label> tag expression.

• Calls startText( ) and XMLFileWriter.closeTag( ) to write the <label> tag to the output file.

Listing 19-17 shows the startLabel( ) method code.

Listing 19-17 The startLabel( ) method


public void startLabel( ILabelContent label )
{
   String lbl = exportSchema.getExportLabelTag( );
   int len = XMLTags.lPropList.length;
   for (int i = 0;i < XMLTags.lPropList.length;i++)
   {
      if (exportSchema.isPropertyRequired(
         XMLTags.lPropList[i], lbl))
      {
         String propValue = getLabelPropValue(i,label);
         lbl = replaceTag( lbl, "??"+XMLTags.lPropList[i],
            propValue );
      }
   }
   startText( label, lbl );
   writer.closeTag( XMLTags.TAG_CR );
}

• startText( ) performs the following operations:

• Sets the start text logging level and writes to the log file

• Uses getLabelPropValue( ) iteratively to get the label text value

• Writes the <label> tag to the output file

Listing 19-18 shows the startText( ) method code.

Listing 19-18 The startText( ) method


public void startText( ITextContent text, String exportTag )
{
   logger.log( Level.FINE,
      "[XMLReportEmitter] Start text" );
   String txt = exportSchema.getExportLabelTag();
   int len = XMLTags.lPropList.length;
   for (int i = 0;i < XMLTags.lPropList.length;i++)
   {
      if (exportSchema.isPropertyRequired(
            XMLTags.lPropList[i], lbl))
      {
         String propValue = getLabelPropValue(i,label);
         lbl = replaceTag( lbl, "??"
                 +XMLTags.lPropList[i], propValue );
      }
   }
   String textValue = text.getText( );
   writer.writeCode( replaceTag( exportTag, XMLTags.valueTag,
textValue ) );
}

• getLabelPropValue( ) performs the following operations:

• Calls the appropriate IContent accessor method to obtain the property value

• Returns the value to startLabel( ) for substitution in the <label> tag and writing the tag to the XML output file

Listing 19-19 shows the getLabelPropValue( ) method code.

Listing 19-19 The getLabelPropValue( ) method


private String getLabelPropValue( int property, ILabelContent
label)
{
   String propValue;

   switch (property) {
      case 0: // "Bookmark":
         propValue = label.getBookmark( );
         break;
      case 1: // "Height":
         if ( label.getHeight( ) != null )
            propValue = label.getHeight().toString( );
         else
               propValue = "";
         break;
      case 2: //"Hyperlink":
         if ( label.getHyperlinkAction( ) != null )
            propValue =
                  label.getHyperlinkAction( ).getHyperlink( );
            else propValue = "";
            break;
         ...
         case 8: //"Y":
            if ( label.getY( ) != null )
               propValue = label.getY( ).toString( );
            else
               propValue = "";
            break;
         default: propValue = "";
            break;
   }
      if ( propValue == null )
         propValue = "";
         return propValue;
   }

Understanding XMLTags

The XMLTags class defines the controls and associated property lists used in analyzing the report contents, as shown in Listing 19-20.

Listing 19-20 The XMLTags class


public class XMLTags
{
   public static final String TAG_CR = " " ;
   static String valueTag = "??value";
   static String labelControl = "label";
   static String textControl = "text";
   static String imageControl = "image";
   static String dataControl = "data";
   static String reportControl = "report";
   static String startControl = "start";
   static String endControl = "end";

   static String[ ] iPropList =
      {"Bookmark","Height","Hyperlink","ImageMap",
         "InlineStyle","MIMEType","Name","Style","TOC","URI",
         "Width","X","Y"};
   static String[ ] dPropList =
         {"Bookmark","Height","Hyperlink","InlineStyle","Name",
            "Style","TOC","Width","X","Y"};
   static String[ ] lPropList =
      {"Bookmark","Height","Hyperlink","InlineStyle","Name",
         "TOC","Width","X","Y" };
   static String[ ] tPropList =
         {"Bookmark","Height","Hyperlink","InlineStyle","Name",
            "Style","Text","TOC","Width","X","Y"}
   static String[ ] rPropList =
         {"TotalPages", "TOCTree", "Name"};
}

Understanding XMLFileWriter

The XMLFileWriter class writes the closing tag similar to the CSV report rendering extension.

Understanding XMLRenderOption

The org.eclipse.birt.report.engine.emitter.xml.XMLRenderOption class adds the XML rendering option to the BIRT Report Engine run time, as shown in Listing 19-21.

Listing 19-21 The XMLRenderOption class


package org.eclipse.birt.report.engine.emitter.xml;
import org.eclipse.birt.report.engine.api.RenderOption;

public class XMLRenderOption extends RenderOption{
   public static final String XML = "XML";
   public XMLRenderOption( ) {
}

Understanding LoadExportSchema

The org.eclipse.birt.report.engine.emitter.xml.LoadExportSchema class optionally loads an XML schema by performing the following operations:

• Specifies the default substitution patterns for the XML tags

• Calls the readSchemaFile( ) method

• Specifies an accessor method for each tag that returns a value to XMLReportEmitter for output to the export file

Listing 19-22 shows the specification of the default substitution patterns for the XML tags and the constructor, which calls the readSchemaFile( ) method.

Listing 19-22 The LoadExportSchema class


package org.eclipse.birt.report.engine.emitter.xml;
...
public class LoadExportSchema{
   protected String fileName = "";
   protected String startTag =
      "<?xml version="1.0" encoding="UTF-8"?>";
   protected String textTag = "<text>??value</text>";
   protected String imageTag = "<image>??value</image>";
   protected String dataTag = "<data>??value</data>";
   protected String labelTag = "<label>??value</label>";
   protected String endTag = "</report>";
   protected String reportTag = "<report:??name>";

   public LoadExportSchema(String fileName)
   {
      if ( fileName.length( ) > 0 )
      {
         this.fileName = fileName;
         readSchemaFile( );
      }
   }
   ...

The readSchemaFile( ) method reads the XML Schema file, one line at a time, replacing the default values for the patterns of the XML version, data, image, label, report tags, and text with the values specified in the XML Schema file.

Listing 19-23 shows the code for the readSchemaFile( ) method.

Listing 19-23 The readSchemaFile( ) method


private void readSchemaFile( )
{
   BufferedReader input = null;
   try
   {
      input = new BufferedReader(
            new FileReader(fileName) );
      String line = null; //not declared within while loop
      while (( line = input.readLine( )) != null){
         int pos = line.indexOf("=");
         if ( pos > 0 )
         {
            String index = line.substring(0, pos );
            String indexTag = line.substring(pos + 1,
               line.length( ));
            if ( index.equalsIgnoreCase(
               XMLTags.labelControl ) )
            {
               labelTag = indexTag;
         }
         if ( index.equalsIgnoreCase( XMLTags.imageControl ) )
         {
            imageTag = indexTag;
         }
         if ( index.equalsIgnoreCase( XMLTags.dataControl ) )
         {
            dataTag = indexTag;
         }
         if ( index.equalsIgnoreCase( XMLTags.startControl ) )
         {
            startTag = indexTag;
         }
         if ( index.equalsIgnoreCase( XMLTags.endControl ) )
         {
            endTag = indexTag;
         }
         if ( index.equalsIgnoreCase( XMLTags.reportControl ) )
         {
            reportTag = indexTag;
         }
      }
      catch (FileNotFoundException ex)
      {
         ex.printStackTrace( );
      }
      catch (IOException ex)
      {
         ex.printStackTrace( );
      }
      finally
      {
         try
         {
            if (input!= null)
            {
               input.close( );
            }
         }
         catch (IOException ex)
         {
            ex.printStackTrace( );
         }
      }
   }

Listing 19-24 shows the values of the patterns for the XML version, data tags, image, label, report, and text specified in the XML Schema file, xmlReport.xmlemitter.

Listing 19-24 The XML Schema file


start=<?xml version="1.0" encoding="UTF-8"?>
report=<report name=??name>
label=<label name=??name hyperlink=??hyperlink>??value</label>
text=<text name=??name>??value</text>
image=<image name=??name>??value</image>
data=<data>??value</data>
end=</report>

Testing the XML report rendering plug-in

To test the XML report rendering example, create a Java application that runs a report design in an installation of the BIRT run-time engine, similar to the application created to run the CSV report rendering example.

To test the XML report rendering plug-in, perform the following tasks:

• Build the org.eclipse.birt.report.engine.emitter.xml plug-in.

• Deploy the plug-in to the BIRT run-time engine directory.

• Launch a run-time instance of the Eclipse PDE or open an Eclipse workbench.

• Create a Java application that runs the report design and writes the report’s data to an XML file.

• Create a report design containing a table that maps to a data source and data set.

• Run the application and examine the XML in the output file.

Figure 19-16 shows the report design used in the XML report rendering example.

Figure 19-16 Report design for the XML report rendering example

image

Listing 19-25 shows the contents of the XML output file, containing XML version, report, image, label, and data tags for an executed report.

Listing 19-25 The XML output file


<?xml version="1.0" encoding="UTF-8"?>
<report name=
   C:/Test/XMLEmitter/ExecuteXMLReport/reports/
   xmlReport.rptdesign>
   <image name=>
      /9j/4AAQSkZJRgABAgEBLAEsAAD
      /4RVaRXhpZgAATU0AKgAAAAgABwESAAMAAAABAAEAAAEaAAUA
      ...
      7PMv9I9nVo5cj8b7MV9zB/gh8cf/2Q==
   </image>
   <label
      name= hyperlink=http://www.actuate.com>Company Name
   </label>
   <label name= hyperlink=>Report</label>
   <label name= hyperlink=>PRODUCTNAME</label>
   <label name= hyperlink=>QUANTITYINSTOCK</label>
   <label name= hyperlink=>MSRP</label>
   <data>1969 Harley Davidson Ultimate Chopper</data>
   <data>7933</data>
   <data>95.7</data>
   <data>1952 Alpine Renault 1300</data>
   <data>7305</data>
   <data>214.3</data>
   <data>1996 Moto Guzzi 1100i</data>
   <data>6625</data>
   <data>118.94</data>
   <data>2003 Harley-Davidson Eagle Drag Bike</data>
   <data>5582</data>
   <data>193.66</data>
   ...
   <data>American Airlines: MD-11S</data>
   <data>8820</data>
   <data>74.03</data>
   <data>Boeing X-32A JSF</data>
   <data>4857</data>
   <data>49.66</data>
   <data>Pont Yacht</data>
   <data>414</data>
   <data>54.6</data>
   ...
</report>

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset