XSL Stylesheets components

  • 16 February 2021
  • 0 replies
  • 124 views

Userlevel 3
Badge +2

An XSL Stylesheets component is an RDMI component that allows you to apply an XSLT 1.0 transformation, or a sequence of XSLT 1.0 transformations, to an input XML document.

In USoft, XSL Stylesheet components are typed as .NET components because they use .NET under the hood.

"XSLT transformation" and "XSLT stylesheet" are synonyms.

Why would you wrap XSL transformations in your own components when you can also apply them by calling the built-in USXSL component?

  • You can invent a functional name for the component which makes sense to a user and by which he can apply the transformation(s).
  • The transformation(s) are easier to deliver because they are an integral part of your application, not an external file or a CLOB value in an application table.
  • Constraints and other SQL contexts that need to apply the transformations become more compact. This is especially true if you apply a sequence of multiple transformations, because this would otherwise require multiple embedded calls to USXSL.
  • The transformations automatically participate in tool features that all RDMI components participate in: SQL Objects cross-referencing, Find In Repository, and Object Shopping.

You can also use an XSL Stylesheets component as a PDF or HTML report writer.

Defining a component for applying a single XSLT transformation

To define a component for applying a single XSLT transformation:

1. In USoft Definer, from the menu, choose Define, RDMI, dotNet Components, XSL Stylesheets from the Define menu. The "XSL Stylesheets" window opens.

2. Set any name for the component, e.g., TEST_SINGLE_XSLT.

3. Paste the XSLT code into the Program Source field. Save work.

4. Press the Check button in the top right corner. In the question box, choose the Yes button.

5. USoft has now generated an API consisting of the following methods. These allow you to apply the XSL transformation to input XML in a variety of ways:

Method Name Description
APPLY Applies the Program Source XSL to input XML.
APPLY0 Applies the first XSL transformation in the Program Source XSL to input XML.*
APPLY2FILE Applies the Program Source XSL to input XML and then writes the result to a file with the specified filepath.
APPLY2FILE0 Applies the first XSL transformation in the Program Source XSL to input XML and then writes the result to a file with the specified filepath.*
TEST_SINGLE_XSLT Constructor method with the name that you set in the Name field for the component. This method may not may not be apparent in the list of generated methods and is for technical purposes only.

* The "0" suffix in the method name is the 0-based index number of the transformation, i.e, the first transformation. Because, in this case, you specified a single transformation, the net effect of calling this method is equivalent to calling the same method name without the "0".

TIP 1: You can get the .NET code that USoft has generated by pressing the small 'copy' button immediately to the right of the Program Source prompt. The code is copied to clipboard:

TIP 2: The built-in USCSXSL component underlies this API:

SELECT   uscsxsl.apply( input-xml, xsl-stylesheet )

You can view the signature (parameter list) of each method in the Parameters box at the bottom of the window.

All APPLY... methods allow you to pass a list of input parameters (the args InListparameter listed). You can use this mechanism to pass values to XSL transformations that expect named input parameters as specified by

<xsl:param>

top-level elements. You can pass parameter values as name-value combinations in the following comma-separated syntax, as shown in Example 2 below:

... variable, value [, variable, value ... ]
variable    ::=    type:name
type        ::=    { string | document }

For each variable, a name and a value is required and a type prefix (followed by a colon) is optional. If you do not specify a type, a string value is expected.

Example 1

This example shows a transformation that strips certain timestamp attributes from the input XML.

If the Name set for the component is STRIP_LOG_INFO, and the Program Source set for the component is:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8" omit-xml-declaration="yes"/>

<xsl:template match="*|@*|comment()|processing-instruction()|text()">
<xsl:copy>
<xsl:apply-templates select="*|@*|text()|comment()|processing-instruction()"/>
</xsl:copy>
</xsl:template>

<xsl:template match="@CREATED_ON"/>
<xsl:template match="@CREATED_BY"/>
<xsl:template match="@CHANGED_ON"/>
<xsl:template match="@CHANGED_BY"/>

</xsl:stylesheet>

then this call:

SELECT strip_log_info.apply( '<Test CREATED_BY="User_1"/>')

yields this result:

<Test />

Example 2

This example shows input parameters. The Program Source for the component is:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8" omit-xml-declaration="yes"/>
<xsl:param name="string1"/>
<xsl:param name="string2"/>

<xsl:template match="*">
<xsl:variable name="myname"><xsl:value-of select="local-name(.)"/></xsl:variable>
<xsl:if test="$myname=''Tests'' or $myname=$string1 or $myname=$string2">
<xsl:copy>
<xsl:apply-templates select="*|@*|text()|comment()|processing-instruction()"/>
</xsl:copy>
</xsl:if>
</xsl:template>

<xsl:template match="@CREATED_ON"/>
<xsl:template match="@CREATED_BY"/>
<xsl:template match="@CHANGED_ON"/>
<xsl:template match="@CHANGED_BY"/>

<xsl:template match="@*|comment()|processing-instruction()|text()">
<xsl:copy>
<xsl:apply-templates select="*|@*|text()|comment()|processing-instruction()"/>
</xsl:copy>
</xsl:template>

</xsl:stylesheet>

If the Name of the component is STRIP_LOG_INFO, then this call:

SELECT strip_log_info.apply( 
'<Tests>
<Test1 CREATED_BY="User_1"/>
<Test2 CREATED_BY="User_1"/>
<Test3 CREATED_BY="User_1"/>
</Tests>'
, 'string1'
, 'Test1'
, 'string:string2'
, 'Test2'
)

yields this result:

<Tests>
<Test1 />
<Test2/>
</Tests>

Defining a component for applying multiple XSLT transformations in a sequence

To define a component that will apply a sequence of multiple XSLT transformations to your input XML, simply write the transformations in the Program Source field one after the other in the order in which you want to apply them. At runtime, if you apply all transformations, the result of each transformation is passed as input to the next transformation.

The API generated by USoft will give you methods for calling the entire sequence, but also methods for calling individual transformations in the sequence. Methods with the "0" suffix apply the first transformation only. Methods with the "1" suffix apply the second transformation only, and so on. Here are the methods generated when you submit two transformations:

Method Name Description
APPLY Applies both transformations.
APPLY0 Applies the first transformation.
APPLY1 Applies the second transformation.
APPLY2FILE Applies both transformations and outputs the result to file.
APPLY2FILE0 Applies the first transformation and outputs the result to file.
APPLY2FILE1 Applies the second transformation and outputs the result to file.

 

Example

This example has 2 transformations. The first transformation picks the Tests, Test1 and Test2 elements from the XML. The result is passed to the second transformation, which strips the timestamp attributes.

This particular example could just as well have been written as Example 2 above. In other words, all the work could be done by a single XSLT transformation. The code below is just to illustrate the principle of applying multiple transformations instead.

If the Name of the component is STRIP_LOG_INFO, and the Program Source for the component is:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8" omit-xml-declaration="yes"/>

<xsl:template match="Tests|Test1|Test2">
<xsl:copy>
<xsl:apply-templates select="*|@*|text()|comment()|processing-instruction()"/>
</xsl:copy>
</xsl:template>

<xsl:template match="@*|comment()|processing-instruction()|text()">
<xsl:copy>
<xsl:apply-templates select="*|@*|text()|comment()|processing-instruction()"/>
</xsl:copy>
</xsl:template>

</xsl:stylesheet>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8" omit-xml-declaration="yes"/>

<xsl:template match="*|@*|comment()|processing-instruction()|text()">
<xsl:copy>
<xsl:apply-templates select="*|@*|text()|comment()|processing-instruction()"/>
</xsl:copy>
</xsl:template>

<xsl:template match="@CREATED_ON"/>
<xsl:template match="@CREATED_BY"/>
<xsl:template match="@CHANGED_ON"/>
<xsl:template match="@CHANGED_BY"/>

</xsl:stylesheet>

then this call:

SELECT strip_log_info.apply( 
'<Tests>
<Test1 CREATED_BY="User_1"/>
<Test2 CREATED_BY="User_1"/>
<Test3 CREATED_BY="User_1"/>
</Tests>'
)

yields this result:

<Tests>
<Test1 />
<Test2 />
</Tests>

and this call:

SELECT strip_log_info.apply0( 
'<Tests>
<Test1 CREATED_BY="User_1"/>
<Test2 CREATED_BY="User_1"/>
<Test3 CREATED_BY="User_1"/>
</Tests>'
)

yields this result:

<Tests>
<Test1 CREATED_BY="User_1"/>
<Test2 CREATED_BY="User_1"/>
</Tests>

and this call:

SELECT strip_log_info.apply1( 
'<Tests>
<Test1 CREATED_BY="User_1"/>
<Test2 CREATED_BY="User_1"/>
<Test3 CREATED_BY="User_1"/>
</Tests>'
)

yields this result:

<Tests>
<Test1 />
<Test2 />
<Test3 />
</Tests>

This topic has been closed for comments