XSLT for Dummies

 
Chapter 12 - Combining XSLT Stylesheets
XSLT For Dummies
by Richard Wagner
Hungry Minds 2002
  

When you fully understand how xsl:include and xsl:import are used and their potential implications, you can use them effectively to make your stylesheet development process more efficient. Following is a fairly basic, yet practical example of how you can use xsl:import . Suppose that a company has an XML document of employees which it uses as the data source for multiple output needs:

  • An HTML summary report of employees

  • A comma-delimited text file which separates each piece of employee data with a comma for importing into an external database

  • A modified XML structure for use in another application

Listing 12-1 shows the XML source file.

Listing 12-1: company_emp.xml

<!-- company_emp.xml --> <?xml version="1.0"?> <employees> <employee id="101"> <lastname>Lamotte</lastname> <firstname>Mitch</firstname> <nickname>The Mitchster</nickname> <title>Director of Sales</title> </employee> <employee id="102"> <lastname>Williams</lastname> <firstname>Tim</firstname> <nickname>Timmy Boy</nickname> <title>Director of Quality Assurance</title> </employee> <employee id="103"> <lastname>Magruder</lastname> <firstname>Randy</firstname> <nickname>Randall</nickname> <title>Senior Engineer</title> </employee> <employee id="104"> <lastname>Drohan</lastname> <firstname>Doug</firstname> <nickname>Tooltime</nickname> <title>Building Director</title> </employee> <employee id="105"> <lastname>Burrer</lastname> <firstname>Phillip</firstname> <nickname>Flip</nickname> <title>Resident Physician</title> </employee> </employees>

 

To act on this source document, I have created three stylesheets, each of which generates one of the three outputs I want.

The first stylesheet (shown in Listing 12-2) defines a template rule for outputting the employee elements into an HTML-based list. An xsl:output element is added with method="html" to create an HTML file. A variable named reporttype is declared with a value of 1 , which is used in the calling stylesheet I define later.

Listing 12-2: emp_report_1.xsl

<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- Declare HTML output --> <xsl:output method="html"/> <!-- reporttype definition --> <xsl:variable name="reporttype" select="1"/> <!-- employee template rule for HTML output--> <xsl:template match="employee"> <p><b><xsl:value-of select="firstname"/><xsl:text> </xsl:text><xsl:value-of select="lastname"/></b></p><xsl:text> </xsl:text> <p> * Employee ID: <xsl:value-of select="@id"/></p> <p> * Serves as <xsl:value-of select="title"/></p><xsl:text> </xsl:text> <p> * Likes to be called <i><xsl:value-of select="nickname"/></i></p><xsl:text> </xsl:text> <hr></hr> </xsl:template> </xsl:stylesheet>

 

The second stylesheet is in Listing 12-3 and provides a template rule for creating a comma-delimited text file that lists the values of each child in the employee element. It has an xsl:output element in which the method attribute has a value of text , and its reporttype variable is set to 2 .

Listing 12-3: emp_report_2.xsl

<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- Declare Text output --> <xsl:output method="text"/> <!-- reporttype definition --> <xsl:variable name="reporttype" select="2"/> <!-- employee template rule for text-only output--> <xsl:template match="employee"> <xsl:value-of select="@id"/>,<xsl:value-of select="firstname"/>,<xsl:value-of select="lastname"/>,<xsl:value-of select="title"/>,<xsl:value-of select="nickname"/><xsl:text> </xsl:text> </xsl:template> </xsl:stylesheet>

 

The third stylesheet (shown in Listing 12-4) creates a template rule that transforms the original XML structure into a derivative XML document. The xsl:output s method is set to xml , while the reporttype variable is declared with a value of 3 .

Listing 12-4: emp_report_3.xsl

<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- Declare XML output --> <xsl:output method="xml"/> <!-- reporttype definition --> <xsl:variable name="reporttype" select="3"/> <!-- employee template rule for XML output--> <xsl:template match="employee"> <employee> <id><xsl:value-of select="@id"/></id> <name><xsl:value-of select="firstname"/><xsl:text> </xsl:text><xsl:value-of select="lastname"/></name> <title><xsl:value-of select="title"/></title> </employee> </xsl:template> </xsl:stylesheet>

 

Each of these stylesheets can be run independently on the source document to produce the results desired, but it may be more efficient to create a master stylesheet that conditionally runs one of these three stylesheets. This is especially true when you have identical code that needs to be run on each output type.

For example, because I have created these three stylesheets that transform the employee element, I now create a "master" stylesheet that brings everything together:

<!-- company_emp.xsl --> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- Import employee template rule --> <xsl:import href="emp_report_1.xsl"/> <!-- reportname variable declaration --> <xsl:variable name="reportname">Employee Summary</xsl:variable> <!-- Generate employees report --> <xsl:template match="employees"> <!-- HTML report --> <xsl:if test="$reporttype=1"> <h1><xsl:value-of select="$reportname"/></h1> <xsl:apply-templates/> </xsl:if> <!-- Comma-delimited text report --> <xsl:if test="$reporttype=2"> <xsl:text>id,name,title,nickname </xsl:text> <xsl:apply-templates/> </xsl:if> <!-- XML report --> <xsl:if test="$reporttype=3"> <xsl:text> </xsl:text><employees_sub1> <xsl:apply-templates/> </employees_sub1> </xsl:if> </xsl:template> </xsl:stylesheet>

The xsl:import element is used to specify which of the three reference stylesheets I want to use: emp_report_1.xsl for HTML (Listing 12-2), emp_report_2.xsl for text (Listing 12-3), or emp_report_3.xsl for XML (Listing 12-4). This href value is the only code that needs to be changed, depending on the output type desired.

The xsl:variable defines a reportname variable, which I use to generate a header for each report type in the employees template rule.

The employees template rule tests the value of the reporttype variable (defined in the referenced stylesheets) in the xsl:if statements to determine which of the three output types are desired:

  • For HTML output, the template adds a h1 header.

  • For text output, the field names are listed.

  • Or for XML output, the template adds employees_sub1 as the document element of the new XML file created.

When the company_emp.xsl file is applied to the Listing 12-1 XML file using <xsl:import href="emp_report_1.xsl"/> , the following HTML is generated:

<h1>Employee Summary</h1> <p><b>Mitch Lamotte</b></p> <p> * Employee ID: 101</p> <p> * Serves as Director of Sales</p> <p> * Likes to be called <i>The Mitchster</i></p> <hr> <p><b>Tim Williams</b></p> <p> * Employee ID: 102</p> <p> * Serves as Director of Quality Assurance</p> <p> * Likes to be called <i>Timmy Boy</i></p> <hr> <p><b>Randy Magruder</b></p> <p> * Employee ID: 103</p> <p> * Serves as Senior Engineer</p> <p> * Likes to be called <i>Randall</i></p> <hr> <p><b>Doug Drohan</b></p> <p> * Employee ID: 104</p> <p> * Serves as Building Director</p> <p> * Likes to be called <i>Tooltime</i></p> <hr> <p><b>Phillip Burrer</b></p> <p> * Employee ID: 105</p> <p> * Serves as Resident Physician</p> <p> * Likes to be called <i>Flip</i></p> <hr>

When run with <xsl:import href="emp_report_2.xsl"/> , the following text file is produced:

id,name,title,nickname 101,Mitch,Lamotte,Director of Sales,The Mitchster 102,Tim,Williams,Director of Quality Assurance,Timmy Boy 103,Randy,Magruder,Senior Engineer,Randall 104,Doug,Drohan,Building Director,Tooltime 105,Phillip,Burrer,Resident Physician,Flip

Finally, when run with <xsl:import href="emp_report_2.xsl"/> , the XML result is:

<?xml version="1.0" encoding="utf-8"?> <employees_sub1> <employee><id>101</id><name>Mitch Lamotte</name><title>Director of Sales</title></employee> <employee><id>102</id><name>Tim Williams</name><title>Director of Quality Assurance</title></employee> <employee><id>103</id><name>Randy Magruder</name><title>Senior Engineer</title></employee> <employee><id>104</id><name>Doug Drohan</name><title>Building Director</title></employee> <employee><id>105</id><name>Phillip Burrer</name><title>Resident Physician</title></employee> </employees_sub1>

  
 
 
2000-2002    Feedback

Категории