XSL-FO Designer for Apache FOP

bcl_716964462.htm

18. Advanced functionalities

This section will describe how the designer generates the XSL-FO code and how you can add your own code. Note this section requires some basic knowledge of XSLT and XPATH.

Understanding the generated code for areas

Each detail area (see 1 in the screenshot) in the designer will be printed as a table:
  • The table has a header (see 2) which will contain the area‘s header content.
  • And a body which contains the detail area content.
  • The body can contain many rows which are the repetitions of the detail area. For these many rows to happen the designer creates a XSLT loop using the for-each expression based on the XML Node that has been selected for the area (see 3)

In the order.xre example we can see the described structure for the order lines:
  • There is a table being created if any node /Order/OrderDetail/ListOfItemDetail/ItemDetail exists. That is what you see right below the blue comment line (xsl:if expression).
  • There is a table header which contains the „Detail Columns Header“ fields.

  • There is a table body
  • And there is a loop. This is the expression

    <xsl:for-each select="OrderDetail/ListOfItemDetail/ItemDetail">



    After the loop there is the definition of the tables rows <fo:table-row , therefore a new table row will be created of each repetition  of the loop, that is for each ItemDetail in the input XML. In each row the fields of the area will be printed.
  • Further down in the code there is the end of the loop and the table to finish the area printing

The result is:
  • One table header (the grey area below)
  • One table body with 2 rows (for 2 items in the order, since we used an input XML file with 2 items only)

Note the code generated for the report header is similar but slightly different in the locations.

Introduction to Variables and Keys


This section will introduce the use of XSLT Variables and Key in the designer.

Variables can be defined like this:

<xsl:variable name="Variablename" select="value"/>

Some examples are:
  • <xsl:variable name="color" select=“'blue'“/> : this creates a variable named color and sets the value to 'blue'
  • <xsl:variable name="color" select=“/MYDOCUMENT/COLOR“/> :  this creates a variable named color and sets the content of the XML node /MYDOCUMENT/COLOR.
  • <xsl:variable name="color" /> : this creates the variable and the value will be an empty string.

The variable can later on be read using the syntax $variable name. For example:
  • You can use $color as value in the Xpath of a field name
  • Or you can type in this expression in a free code field:

    <xsl:value-of select="$color"/>

Keys are similar to database lookups. First you need to defined a key (this has to be done in the initialization part of the report). The syntax is:

<xsl:key name="keyname" match="node" use="indexexpression"/>

  • Name: is the name of the key.
  • Match: is the node that the key should return. It is like a table name in a database lookup. For example, if we have a structure like /Persons/Person/FirstName and /Persons/Person/LastName and we want to create a lookup to find all persons named „Peter“, we use /Persons/Person as Node or Table.
  • Use: this is the index field (like an index field in a database table). Since we are going to search by name we will use the element firstname.

    The key will therefore be:

    <xsl:key name="mySearch" match="/Persons/Person" use="FirstName"/>

The Lookup can be the executed using the key() function:

    key(keyname,expression)

The expression can be a constant like 'Peter' , a variable or a node (XPath)


For this input data:

<Persons>
    <Person>
        <FirstName>Peter</FirstName>
        <LastName>Smith</LastName>
    </Person>
    <Person>
        <FirstName>David</FirstName>
        <LastName>Brown</LastName>
    </Person>
    <Person>
        <FirstName>James</FirstName>
        <LastName>Davis</LastName>
    </Person>
    <Person>
        <FirstName>Peter</FirstName>
        <LastName>Jones</LastName>
    </Person>
</Persons>

The key function can be used in the report like this:
  • Execute the lookup and store the output in a variable named result. You can do this in the „Start code“ in the Advanced tab of the area (see next section)

    <xsl:variable name="result" select="key('mySearch','Peter')[1]"/>

    pay attention to the [1] which will store only the first returned node (in case there are several persons with name Peter)
  • You can use the variable of the previous step in a field of your area, for example setting the Xpath value  to $result/LastName.
  • <xsl:for-each select="key('mySearch','Peter')"> : This would return nodes 1 and 4. This creates a loop which need to be closed with </xsl:for-each>.

Tip! You can leave the XML Node of the area empty and instead you can use the Advanced fields (see next section) to create a custom loop for the area as below:





We deliver an example named PersonKey.xre where you can see the implementation  of this section. Please note there are other ways of achieving  the same result without using variables or keys. The only purpose of this example is to show these features in action.

Adding your own code


There are several way of adding XSL-FO code to your report:
  • The first one in the Free Code field. This allows the insertion of code in cells, rows and tables. We will not explain it in this section since it has already been explained in this guide.
  • The report initialization code can be set in the report properties, Other tab. This field can be used to define keys or report variables. For example we create here a variable which will contain  the order number. The variable can be used later in the report using $ordernumber.



    the code will then be placed at the very top of the generated code:

  • Each detail area and the report header contain an Advanced tab where you can place code in different locations. In the screenshot below we have added XML comments to highlight the output code location.

    • Start Code: will be place before the table creation for the area.

    • Before row code: the code will be placed after the table loop and before the row generation.

    • After row code: after each row repetitions

    • Finish code: after the loop.

Markers (variable data in page header and footer)


Markers are used in XSL:FO to keep track of the values in the pages as they are being rendered. The main purpose of the markers is to be used in Page Headers and Page Footer. By using markers you can have variable data in the page header and footers which otherwise can only contain constant data.

The delivered example tasksMarkers shows how to use the markers.

  • First the markers much be defined for an area. Two markers can defined by default. In this case the engine will collect information about the  TASK_NAME and ASSIGNED_TO values in the page



  • As second step the marker can be used in the pages header and footers
    • The page header field below will display the first marker value in the page. In this case the first TASK_NAME.



    • The page footer field below will display the last marker value in the page. In this case the last TASK_NAME.



    • The page footer barcode below will display the first marker value in the page. In this case the first ASSIGNED_TO value (note it uses Marker2).


The following screenshot shows the output of one of the page footer fields, the last value in the page has been added to the page footer, while the barcode shows the first name in the page




Note: if you need to define more than 2 markers the code below can be used in the "After row code" field

for report headers use:

<fo:block>
<fo:marker marker-class-name="markerName">   
<xsl:value-of select="yourXPATH"/>            
</fo:marker>
</fo:block>

for details areas use:

<fo:table-row  max-height="0mm"  height="0mm" border-collapse="separate" border-style="none">
<fo:table-cell  border-style="none">
<fo:block>
<fo:marker marker-class-name="markerName">   
<xsl:value-of select="yourXPATH"/>           
</fo:marker>
</fo:block>
</fo:table-cell>
</fo:table-row>


Advanced examples


The following examples show how to use some of the advanced features:
  • BooksGrouping2.xre: this is a „groupby“ report which creates a master detail structure using a flat input structure. The report groupy by the field CUSTOMER_ID to create a list of persons and a grouped list of booked borrowed by each person


  • BooksGrouping.xre: This is the same example as above but instead of using the built-in grouping functionality we group the books using a variable. This is done by selecting „Local group“



    and setting a variable to store the customer name:



    last in the detail 2 area we use the variable to select the books belonging to the current customer:


  • BooksAndCode.xre: This example is similar to the previous one. The difference here is that the input XML is not one flat structure but has 2 parallel structures that will be linked using a variable.

    In the ROWSET2_ROW nodes we have the list of customers which we will print out, this is the main detail area. We save the current customer in a variable for each row.



    In the subarea „Detail 2“ we use the variable to select only the corresponding records from the other structure ROWSET1_ROW.


Using third party XSLT templates

You can use third party XSLT template files to extend the functionality of the designer. One example is this library:

https://sourceforge.net/projects/xsltsl/


In the library you will find functions to, for example, format date/time date or string values.

The example tasks_xsl.xre shows how to use this feature. The steps are:

  1. extract one of the templates from the library. This is required to keep the report size small (do not use the original "big" files).

    For example this snippet would convert a day number to the name of the day in english (make sure you have namespace and prefix, see red texts):

    <xsl:template name="dt:get-day-of-the-week-name" xmlns:dt="http://xsltsl.org/date-time">
      <xsl:param name="day-of-the-week"/>
       <xsl:choose>
        <xsl:when test="$day-of-the-week = 0">Sunday</xsl:when>
        <xsl:when test="$day-of-the-week = 1">Monday</xsl:when>
        <xsl:when test="$day-of-the-week = 2">Tuesday</xsl:when>
        <xsl:when test="$day-of-the-week = 3">Wednesday</xsl:when>
        <xsl:when test="$day-of-the-week = 4">Thursday</xsl:when>
        <xsl:when test="$day-of-the-week = 5">Friday</xsl:when>
        <xsl:when test="$day-of-the-week = 6">Saturday</xsl:when>
        <xsl:otherwise>error: <xsl:value-of select="$day-of-the-week"/></xsl:otherwise>
      </xsl:choose>
    </xsl:template>

  2. copy this code to an XSL file (dayName.xsl) and place it in the designer in the directory as below ( create the directory if not existing):





  3. Use the reload templates button in the Xpath designer, you can use the insert button to add the new function:



  4. The code generated by the designer will now include the external code:



  5. The report will now show the result of the external function get-day-of-the-week-name