The sample XML data extraction extension
The sample XML data extraction extension example described in this section illustrates how to create a plug-in extension that converts all or part of report data to XML format. The XML data extraction extension example exports only the data selected in the export data menu to an output file. The export data feature is available in the BIRT Web Viewer.
This extension example creates the XML output stream and sends the stream to the browser. Most browsers show the formatted XML directly. Some show a download message that prompts the user to view or save the XML output. This behavior depends on the browser and how it is configured to work with XML MIME type files. If the user changes the MIME type in the plug-in’s extension properties to text/plain, the browser displays the XML file instead of displaying a download message.
Implementing the data extraction interfaces
This section provides a general description of the code a developer must write to complete the development of an XML data extraction extension. The org.eclipse.birt.report.engine.api and org.eclipse.birt.report.engine
.dataextraction plug-ins define the data extraction interfaces used to extract and format data to a specified format. The XML data extraction extension implements the following interfaces and classes:
*org.eclipse.birt.report.engine.extension.IDataExtractionExtension
Defines three methods to initialize the resources, output extracted data, and release allocated resources during the data extraction process. The purpose of the output method is to process the metadata in the result set and format the output in the desired format. Extending the implementation class of the interface DataExtractionExtensionBase instead of the interface itself is a recommended best practice.
*org.eclipse.birt.report.engine.api.IExtractionResults
Provides the API for retrieving metadata for the result set.
*org.eclipse.birt.report.engine.api.IDataExtractionOption
Defines the basic properties of the data extraction and related get and set methods. Basic properties include elements such as output format, output file, and output stream.
*org.eclipse.birt.report.engine.dataextraction.ICommonDataExtractionOption
Extends the IDataExtractionOption interface to define the basic properties and related get and set methods for a common data extraction plug-in. The XML data extraction extension uses this interface, since most of the properties defined for the common data extraction apply to the XML extraction as well.
The implementation class for this interface is org.eclipse.birt.report.engine
.dataextraction.impl.CommonDataExtractionImpl. The class provides utility methods that are initialized according to the data extraction options. The basic properties for the data extraction option are:
*Output locale
*Output time zone
*Output encoding, such as UTF-8, UTF-16LE, or ISO-8859-1
*Output date format
*Selected columns for export
*Indicator of whether to export the columns data type
*Indicator of whether to export the locale neutral format value
*User-defined parameters
XML document format
The implementation package for the XML data extraction extension, org.eclipse.birt.report.engine.dataextraction.xml, contains only the class XMLDataExtractionImpl.java.
The XMLDataExtractionImpl extends org.eclipse.birt.report.engine
.dataextraction.impl.CommonDataExtractionImpl class and implements private methods that create an XML document.
The XML document schema contains the following elements:
*<Report>
<Report> encloses the other elements of the XML document.
*<Properties>
Contents include information about the following report properties:
*<ReportName>
Full path and the report name.
*<Locale>
Report locale for display. If the locale is null, the default is locale en_US, displaying American English.
*<Encoding>
Specifies an option in the Export Data user interface allowing users to select the encoding for exported report data. By default, the encoding is set to UTF-8. The text content of <Encoding> displays the selected encoding.
*<Parameters>
This tag includes all parameters passed in the URL used to run the report in the Web Viewer. These parameters are referred as user parameters, which are different from report parameters. These items appear in a comma-separated list.
The exact number and values of the parameters depend on the report design and the environments in which the report runs. The user parameter names are self-documenting.
The following list displays the commonest user parameters:
*__asattachment
*__resourceFolder
*__cubememsize
*__resultsetname
*__dpi
*__rtl
*__exportdatatype
*__selectedcolumn0
*__exportencoding
*__selectedcolumn1
*__extractextension
*__selectedcolumn2
*__format
*__selectedcolumnnumber
*__locale
*__sep=0
*__localeneutral
*__sessionId
*__masterpage
*__svg
*__report
*__timezone
*<isLocaleNeutral>
Users have the option to export data in a locale neutral format. Numbers are exported as neutral string values. Date format columns are exported in ISO8601 format, such as YYYY-MM-DD or YYYYMMDD, for example.
*<Columns>
Lists the columns in the data row. Column type is an attribute of <Column>. This attribute is optional and appears in an XML document only if the user selects to export the data types in the Data Export dialog.
*<Row>
Contains the data for a single data row. Column names appear in tags around each column value.
Listing 26‑1 shows an example of an exported XML document.
Listing 26‑1 An exported XML document
<?xml version="1.0" encoding="UTF-8"?>
<Report>
<!--Extract report data in XML format-->
<!--Lists the report properties, such as name, locale, encoding, user parameters-->
<Properties>
<ReportName>C:\Test\XMLDataExtraction\XMLTest\new report.rptdesign</ReportName>
<Locale>English</Locale>
<Encoding>UTF-8</Encoding>
<Parameters> exportencoding=UTF-8, svg=false,_selectedcolumn1=
CONTACTFIRSTNAME,_selectedcolumn2=PHONE,_rtl=false, extractextension=org.eclipse.birt.report.engine
.dataextraction.xml, report=C:\Test\XMLDataExtraction
\XMLTest\new_report.rptdesign, masterpage=true, sessionId=20131212_074641_765,1090400155=, format=html, asattachment=true, selectedcolumnnumber=3, localeneutral=false, sep=0, timezone=US/Pacific-New, locale=en_US, carriagereturn=false, cubememsize=10, exportdatatype=false, resultsetname=ELEMENT_9, selectedcolumn0=CUSTOMERNAME, dpi=96, resourceFolder=
C:\Test\XMLDataExtraction\XMLTest</Parameters>
</Properties>
<Row>
<CUSTOMERNAME>Atelier graphique</CUSTOMERNAME>
<CONTACTFIRSTNAME>Carine </CONTACTFIRSTNAME>
<PHONE>40.32.2555</PHONE>
</Row>
<Row>
<CUSTOMERNAME>Signal Gift Stores</CUSTOMERNAME>
<CONTACTFIRSTNAME>Jean</CONTACTFIRSTNAME>
<PHONE>7025551838</PHONE>
</Row>
<Row>
<CUSTOMERNAME>Australian Collectors, Co.</CUSTOMERNAME>
<CONTACTFIRSTNAME>Peter</CONTACTFIRSTNAME>
<PHONE>03 9520 4555</PHONE>
</Row>
</Report>
XMLDataExtractionImpl class
XMLDataExtractionImpl extends CommonDataExtractionImpl. The class uses private variables to store the output XML document, the output stream where the document streams as a string, and the properties of the report. These properties are exported in the <properties> tag of the output XML file.
The variable declarations are shown in Listing 26‑2.
Listing 26‑2 XML data extraction option variables
public class XMLDataExtractionImpl extends CommonDataExtractionImpl
{
public static final String PLUGIN_ID =
"org.eclipse.birt.report.engine.dataextraction.xml";
public static final String DEFAULT_ENCODING =
Charset.defaultCharset( ).name( );
private Document outDocument;
private OutputStream outputStream;
private String encoding;
private String selectedColumnNames;
private boolean isExportDataType;
private boolean isLocaleNeutral;
private Locale locale;
private String reportName;
private String userParameters;
The XMLDataExtractionImpl class uses the Java API defined in the org.w3c.dom package for XML processing. Table 26-4 describes the exported properties variables.
Table 26-4 Report properties variables 
Property
Variable
Description
Report name
reportName
Name of BIRT report.
Locale
locale
Locale in which the report runs.
Encoding
encoding
Encoding used in report. User selects the value in the Export Data menu.
Selected column names
selectedColumnNames
The columns selected for export.
User parameters
pUserParameters
Parameters passed in the Web Viewer URL by the report engine.
Export the data types
isExportDataType
Variable that defines whether to export the data type of the columns to the output XML document. User selects the value in the Export Data menu.
Neutral locale
isLocaleNeutral
Variable that defines whether to use a neutral locale format for the data types columns. User defines the value in the Export Data menu.
The following XMLDataExtractionImpl methods set up and implement the data extraction:
*initialize( )
Defined by the org.eclipse.birt.report.engine.extension
.IDataExtractionExtension interface class. Initializes context and options objects and calls the private initXMLOptions( ) method to initialize local variables. Listing 26‑3 shows the initialize( ) method.
Listing 26‑3 initialize( ) method
public void initialize( IReportContext context,
IDataExtractionOption options ) throws BirtException
{
super.initialize( context, options );
initXMLOptions( options );
}
*initXMLOptions( )
Called at the beginning of each data extraction to perform the following operations. Listing 26‑4 shows the initXMLOptions( ) method.
*Creates the output stream that writes the text contents of the report to the XML file.
*Obtains a reference to the CommonDataExtractionOption object xmlOption, containing accessor methods that get the IDataExtractionOption interface options for the plug-in.
*Uses the data extraction API methods to initialize report property values, such as encoding, locale, iLocaleNeutral, selected columns, isExportDataType, user parameters, and report name.
Listing 26‑4 initXMLOptions( ) method
private void initXMLOptions( IDataExtractionOption options )
{
outputStream = options.getOutputStream( );
CommonDataExtractionOption xmlOption;
if ( options instanceof CommonDataExtractionOption )
{
xmlOption = ( CommonDataExtractionOption )options;
}
else
{
xmlOption = ( CommonDataExtractionOption ) new CommonDataExtractionOption( options.getOptions( ));
}
encoding = xmlOption.getEncoding( );
if ( encoding == null || "".equals( encoding.trim( )))
{
encoding = null;
}
else
{
encoding = encoding.trim( );
}
if ( encoding == null )
{
encoding = DEFAULT_ENCODING;
}
isLocaleNeutral = xmlOption.isLocaleNeutralFormat( );
locale = (Locale) xmlOption.getLocale( );
if ( locale == null )
{
locale = Locale.getDefault( );
}
selectedColumnNames = xmlOption.getSelectedColumns( );
isExportDataType = xmlOption.isExportDataType( );
Map pUserParameters = xmlOption.getUserParameters( );
userParameters = getUserParameters(pUserParameters);
getReportName( pUserParameters );
}
*getReportName( )
Called by the initXMLOptions( ) method to extract the report name and path from the user parameters. Listing 26‑5 shows the getReportName( ) method.
Listing 26‑5 getReportName( ) method
private void getReportName( Map pUserParameters )
{
Map uParameters = pUserParameters;
\\ Iterate over the keys, values in the map
if ( uParameters != null )
{
java.util.Iterator it = null;
for ( it = (java.util.Iterator) uParameters.keySet( ).iterator( );
((java.util.Iterator) it).hasNext( ); )
{
Object key = it.next( );
Object value = uParameters.get(key);
if (key.toString( ).equalsIgnoreCase("__report"))
{
reportName = value.toString( );
}
}
}
}
*output( )
Interface method called to format the output stream for the data extraction. Uses the Document Object Model (DOM) component API to create the output XML document.
The data set result set is passed to the output( ) method through the IExtractionResults results input parameter. The code iterates through the result set to extract the data for only the selected columns. At the end the code converts the XML document to a string and writes the string to the output stream. Listing 26‑6 shows the output( ) method.
Listing 26‑6 output( ) method
public void output( IExtractionResults results )
throws BirtException
{
String[ ] columnNames = (String[ ]) selectedColumnNames;
try {
outDocument = createNewDocument ( );
} catch (Exception e) {
e.printStackTrace();
}
// Create root element of output XML document
Element rootElement = outDocument.createElement( "Report" );
rootElement.appendChild( outDocument.createComment( "Extract report data in XML format" ));
outDocument.appendChild( rootElement );
 
Element pRow = outDocument.createElement( "Properties" );
rootElement.appendChild( outDocument.createComment(
"Lists the report properties, such as name, locale,
encoding, user parameters" ));
rootElement.appendChild( pRow );
 
Element nodeReportName = outDocument.createElement(
"ReportName" );
nodeReportName.appendChild( outDocument.createTextNode(
reportName ));
pRow.appendChild( nodeReportName );
 
Element nodeLocale = outDocument.createElement( "Locale" );
nodeLocale.appendChild(outDocument.createTextNode(
locale.getDisplayLanguage( ) ));
pRow.appendChild( nodeLocale );
 
Element nodeEncoding =
outDocument.createElement( "Encoding" );
nodeEncoding.appendChild( outDocument.createTextNode(
encoding ));
pRow.appendChild( nodeEncoding );
 
Element nodeParameters = outDocument.createElement(
"Parameters" );
nodeParameters.appendChild( outDocument.createTextNode(
userParameters ));
pRow.appendChild(nodeParameters);
 
try {
// If selected columns are null or empty,
// returns all columns
if ( columnNames == null || columnNames.length <= 0 )
{
int count =
results.getResultMetaData( ).getColumnCount( );
columnNames = new String[ count ];
for ( int i = 0; i < count; i++ )
{
String colName =
results.getResultMetaData( ).getColumnName(i);
columnNames[i] = colName;
}
}
IDataIterator iData = null;
if ( results != null )
{
iData = results.nextResultIterator( );
if ( iData != null && columnNames.length > 0 )
{
String[ ] values = new String[ columnNames.length ];
while ( iData.next( ) )
{
Element row = outDocument.createElement( "Row" );
rootElement.appendChild( row );
for (int i = 0; i < columnNames.length; i++)
{
String columnName = results
.getResultMetaData( ).getColumnName( i );
values[i] = getStringValue( iData.getValue(
columnNames[i] ), isLocaleNeutral, locale );
Element node = outDocument.createElement(
columnName );
node.appendChild(
outDocument.createTextNode( values[i] ));
row.appendChild( node );
}
}
}
}
if ( encoding != null && encoding.trim( ).length( ) > 0 )
{
outputStream.write( serialize( outDocument )
.getBytes( encoding.trim( )));
}
else
{
outputStream.write( serialize( outDocument )
.getBytes( ));
}
}
catch ( Exception e ) {
}
}
*createNewDocument( )
Creates the new document. Listing 26‑7 shows the createNewDocument( ) method.
Listing 26‑7 createNewDocument( ) method
private Document createNewDocument( ) throws Exception
{
try {
DocumentBuilderFactory documentBuilderFactory =
DocumentBuilderFactory.newInstance( );
DocumentBuilder documentBuilder =
documentBuilderFactory.newDocumentBuilder( );
Document document = documentBuilder.newDocument( );
return document;
}
catch (Exception e) {
System.out.println( "error in createNewDocument" );
throw e;
}
}
*serialize( )
Uses org.w3c.dom classes to serialize the document as a string. Listing 26‑8 shows the serialize( ) method.
Listing 26‑8 serialize( ) method
public static String serialize(Document doc) throws IOException
{
String str = null;
try {
DOMImplementationRegistry registry =
DOMImplementationRegistry.newInstance();
DOMImplementationLS impl = ( DOMImplementationLS )
registry.getDOMImplementation("LS");
LSSerializer writer = impl.createLSSerializer();
str = writer.writeToString(doc);
}
catch (Exception e) {
e.printStackTrace();
}
return str;
}