XML - Managing Data Exchange/C.6

president.xsl (XSL Stylesheet for a one-to-one model) edit

Now that you now how to create a schema to define a conceptual primary/foreign key relationship, you need to know how to access and display that data. Take a look at the stylesheet below for an example.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format">

<!-- See note below about new elements added  -->

<xsl:key name="predecessor" match="president" use="@primaryKey"/>
<!--xsl:key name="name referenced from within XSL file" match="element in XML file containing key"
use="attribute or sub-element containing actual value of key "-->
<!--key() function use: key('predecessor',2) will return the nodes contained 
by the president element with attribute: primaryKey="2"
Since a node list is returned, <xsl:value-of select="key('predecessor',2)/firstName"/> 
will output John -->
	<xsl:output method="html"/>
	<xsl:template match="/">
		<table style="font-family:arial">
			<tr style="background-color:#6495ED;font-weight:bold">
				<td>President First Name</td>
				<td>President Last Name</td>
				<td>Predecessor First Name</td>
				<td>Predecessor Last Name</td>
			</tr>
			<xsl:for-each select="//president">
				<tr style="background-color:#3CB371">
					<td>
						<xsl:value-of select="firstName"/>
					</td>
					<td>
						<xsl:value-of select="lastName"/>
					</td>
					<xsl:choose>
					<!--XSL equivolent to a programmatic if-else structure-->
						<xsl:when test="predecessor">
							<!--Test to see if there is a predecessor-->
							<td>
        <xsl:value-of select="key('predecessor',predecessor/@foreignKey)/firstName"/>
							</td>
							<td>
        <xsl:value-of select="key('predecessor',predecessor/@foreignKey)/lastName"/>
							</td>
						</xsl:when>
						<xsl:otherwise>
							<!--Equivolent to else-->
							<td colspan="2" style="text-align:center">
                                                 This is the first president!
                                                        </td>
						</xsl:otherwise>
					</xsl:choose>
				</tr>
			</xsl:for-each>
		</table>
	</xsl:template>
</xsl:stylesheet>

Table 6-3: XML stylesheet for President Entity – president.xsl

A look at the new elements: edit

  • <xsl:key> This element is a necessary declaration in order to use the key() function described next. There are three necessary attributes to be used in this element:
    • name: This attribute contains the name to be referenced from within XSL file in the key() function. The value in the name attribute can be thought of in programmatic terms as a variable containing an instance of an object, such as: “String stringVariable” in Java.
    • match: This attribute is similar to the .<xsd:selector> element described above. This is the element in XML file containing the parent key (primary key of the relationship).
    • use: This attribute is similar to the <xsd:field> element describe above. This is the field containing the parent key value.
  • key(string,object) function: This function returns a node set based on the parameters passed to it. The string parameter is the value defined in the name attribute in the <xsl:key> tag. The object parameter is the value of primary key for which you wish to get the nodes for. key('predecessor',2) will return the nodes contained by the president element with attribute: primaryKey="2" . Since a node set is returned, you can access child nodes of the returned set with an x-path expression just as you would any element. So: <xsl:value-of select="key('predecessor',2)/firstName "/> would output “John.” For more information on the key function visit: http://www.w3.org/TR/xslt#key
  • <xsl:choose> This XSL element provides a means for creating an if-else type structure in an XSL stylesheet. This is necessary in our example because the first President will not have a predecessor. We display the predecessor if only there is one! There are two elements within the <xsl:choose> element to perform this:
    • <xsl:when> This element is the equivalent to the programmatic 'if' statement. The test attribute contains a test statement as described in chapter 5. In the above example, it is simply testing to see if the predecessor element is there (if a President has a predecessor).
    • <xsl:otherwise> This element is the equivalent to the programmatic 'else' statement. Its contents are displayed if the test condition in the <xsl:when> statement fails.


 


team.xsl (XSL Stylesheet for a one-to-many model) edit

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform'> 
<xsl:stylesheet version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:fo="http://www.w3.org/1999/XSL/Format">
	<xsl:key name="squadCaptain" match="player" use="@playerId"/>
	<xsl:output method="html"/>
	<xsl:template match="/">
		<xsl:for-each select="//team">
			<table>
			 <tr style="background-color:#6495ED;font-weight:bold">
			  <td colspan="3">
			  Team Id: <xsl:value-of select="@teamId"/><br />
			  Team Name: <xsl:value-of select="teamName"/><br />
			  Team Type: <xsl:value-of select="teamType"/>
			  </td>
			 </tr>
			 <tr style="background-color:#F0E68C;font-weight:bold">
			  <td>Player Id</td>
                          <td>Player Name</td>
                          <td>Player Captain</td>
			 </tr>
			<xsl:for-each select="player">
			 <tr style="background-color:#D3D3D3">
			  <td><xsl:value-of select="@playerId"/></td>
			  <td><xsl:value-of select="firstName"/>&space;
                          <xsl:value-of select="lastName"/></td>
			<xsl:choose>
			<xsl:when test="squadCaptain">
			  <td>
<xsl:value-of select="key('squadCaptain',squadCaptain/@fk_playerId)/firstName"/>
&space;
<xsl:value-of select="key ('squadCaptain',squadCaptain/@fk_playerId)/lastName"/>		 			  </td>
			</xsl:when>
			<xsl:otherwise>
<td style="background-color:#FF0000;font-weight:bold">Squad Captain</td>
			</xsl:otherwise>
			</xsl:choose>
		 	 </tr>				
			</xsl:for-each>		
		</table>
		<br />
		</xsl:for-each>		
	</xsl:template>
</xsl:stylesheet>

Table 6-4: XML stylesheer for Team Entity – team.xsl

A look at the new elements edit

  • <!doctype stylesheet[….]> - This declaration is necessary to declare an entity and must come before the <xsl:stylesheet> tag
  • <!ENTITY space "<xsl:text xmlns:xsl='http://www.w3.org/1999/XSL/Transform'> </xsl:text>"> {2}- This declaration must come between the brackets “[]” in the doctype declaration shown above. “space” is the name of the entity you are defining. The value in between the double quotes is what the entity represents. In our example above, the entity space is referring to a single whitespace, represented with the <xsl:text> </xsl:text> statement. The xmlns attribute located within the <xsl:text> element is only necessary for parsers using the Microsoft XML parser, but should be included anyway for cross compliance. The syntax for using the entity is the same syntax for using any other entity in an XSL stylesheet, which is an ampersand (“&”) followed by the entity name and a semi-colon. In the example above, this would be &space; as shown on. Now whenever a space is needed in the style sheet “&space;” can be used instead of <xsl:text> </xsl:text>

 


accessory.xsl (XSL stylesheet for a many-to-many model) edit

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:fo="http://www.w3.org/1999/XSL/Format">
	<xsl:key name="subProduct" match="accessory" use="@accessoryId"/>
	<xsl:output method="html"/>
	<xsl:template match="/">
		<table>
			<tr style="background-color:#6495ED;font-weight:bold">
				<td>Accessory/Package</td>
				<td>Accessory/Package Price</td>
				<td>Subproduct(s)</td>
			</tr>
			<xsl:for-each select="//accessory">
				<tr  style="background-color:#D3D3D3;vertical-align:top;">
					<td>
						<xsl:value-of select="accessoryName"/>
					</td>
					<td>
	  <xsl:value-of select="format-number(accessoryPrice,'$###,###.00')"/>
					</td>
					<xsl:choose>
						<xsl:when test="subProduct ">
							<td>
			<table>
			<tr style="background-color:#F0E68C;font-weight:bold">
			     <td>Accessory Name</td>
                             <td>Accessory Price</td>
			</tr>		
			<xsl:for-each select="subProduct">
         		<tr style="background-color:#7B68EE">
<td><xsl:value-of select="key('subProduct',@fk_SubProductId)/accessoryName"/></td>
<td><xsl:value-of select="format-number_
(key ('subProduct',@fk_SubProductId)/accessoryPrice,'$###,###.00')"/></td>
			</tr>
			</xsl:for-each>
			</table>								
							</td>
						</xsl:when>
						<xsl:otherwise>
							<td>N/A</td>
						</xsl:otherwise>
					</xsl:choose>
				</tr>
			</xsl:for-each>
		</table>
	</xsl:template>
</xsl:stylesheet>

Table 6-9: XML stylesheet for Accessory Entity – accessory.xsl