The XML report rendering extension package
The implementation package for the XML report rendering extension example, org.eclipse.birt.report.engine.emitter.xml, is in the Third Edition (published 2011):
http://www.actuate.com/birt/contributions
It 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.
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
*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 24‑16 shows the start( ) method.
Listing 24‑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 24‑17 shows the startLabel( ) method code.
Listing 24‑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 24‑18 shows the startText( ) method code.
Listing 24‑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 24‑19 shows the getLabelPropValue( ) method code.
Listing 24‑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;
}
XMLTags class
The XMLTags class defines the controls and associated property lists used in analyzing the report contents, as shown in Listing 24‑20.
Listing 24‑20 The XMLTags class
public class XMLTags
{
public static final String TAG_CR = "\n";
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" };
}
XMLFileWriter class
The XMLFileWriter class writes the closing tag similar to the CSVWriter class in the CSV report rendering extension.
XMLRenderOption class
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 24‑21.
Listing 24‑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( ) {
}
LoadExportSchema class
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 24‑22 shows the specification of the default substitution patterns for the XML tags and the constructor, which calls the readSchemaFile( ) method.
Listing 24‑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 24‑23 shows the code for the readSchemaFile( ) method.
Listing 24‑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 24‑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 24‑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>