|
||
| Inside Technique : Building Documents with XML, XSL, and CSS : Transforming with XSL II We are now going to explore how we generate the content portion of the document. We are first going to explore how to extract an attribute from an XML element. So far you have only seen how the contents of an element can be retrieved and displayed in your document. If you look at the XML article, you will notice that we specify the author's e-mail address as an attribute on the author element: <author email="scotti@SiteExperts.com">Scott Isaacs</author> When we output the author's name, we want to create a mailto link out of this e-mail address. Extracting attribute values is very similar to extracting the contents of an element. You define the path to the attribute, where the attribute is specified using the "@" operator. Now we create our mailto link extracting the e-mail address and the author's name as follows: <A> <xsl:attribute name="href">mailto: <xsl:value-of select="article/meta/author/@email"/> </xsl:attribute> <xsl:value-of select="article/meta/author"/> </A> That was pretty straightforward. Now we are ready to explore the most complicated piece of our XSL template - generating a live table of contents. The table of contents creates an interesting challenge. We need to dynamically generate the table of contents with links to the live sections. To create the link, we are going to retrieve the index of each chapter using the XSL eval element. The eval element executes and returns the result of script. Let's look at the table of contents generation:
<H2>Table of Contents</H2>
<OL ID="toc">
<xsl:for-each select="article/chapter">
<LI>
<A>
<xsl:attribute name="HREF">#H
<xsl:eval>
formatIndex(childNumber(this),"1")
</xsl:eval>
</xsl:attribute>
<xsl:value-of select="title"/>
</A>
</LI>
</xsl:for-each>
</OL>
The table of contents demonstrates almost every technique in this article. First, we output the static table of contents header and the opening of our ordered list. Next, we enumerate all the chapters in the article. At each chapter, we create a link formatted as "#Hn" where n is the chapter number. The contents of each link is the chapter title. We are now ready to output the contents of the article. Since the article consists of chapters, we are going to enumerate over each chapter and then over each element within the chapter's body. Within the chapter body there can be either a code or p element. For code elements we wrap the contents in a PRE element, and for p element we wrap the contents in an HTML p element. To distinguish between these two elements we apply an XSL template. Each element is matched and applied against the template. We also use templates to match the contents of each paragraph. Within a paragraph there can be pullquotes. Below is the complete XSL template for transforming the chapter body. Notice how every XSL element can also be nested to provide more context to your transformation.
<xsl:for-each select="article/chapter">
<A>
<xsl:attribute name="NAME">H
<xsl:eval>
formatIndex(childNumber(this),"1")
</xsl:eval>
</xsl:attribute>
</A>
<H3>
<xsl:eval>
formatIndex(childNumber(this),"1")
</xsl:eval>.
<xsl:value-of select="title"/>
</H3>
<DIV>
<xsl:for-each select="body">
<xsl:apply-templates>
<xsl:template match="code">
<PRE><xsl:value-of/></PRE>
</xsl:template>
<xsl:template match="p">
<p>
<xsl:if test="context()[0]">
<xsl:attribute name="CLASS">START</xsl:attribute>
</xsl:if>
<xsl:apply-templates>
<xsl:template match="pullquote">
<SPAN CLASS="pullquote">...<xsl:value-of/></SPAN>
<xsl:value-of/>
</xsl:template>
<xsl:template match="text()"><xsl:value-of/></xsl:template>
</xsl:apply-templates>
</p>
</xsl:template>
</xsl:apply-templates>
</xsl:for-each>
</DIV>
</xsl:for-each>
The last step is to look at our CSS style sheet. This style sheet is applied to the resulting HTML document. (Remember, in our head section we output a LINK to an external style sheet.) This style sheet allows us to update appearance of the document without needing to update the transformation. For our article, we created a fairly simple stylesheet:
BODY {font-family: arial, geneva}
#about {text-align: center;font-weight: bolder}
#author {font-size: 110%}
#abstract {margin-left: 3em; margin-right: 3em}
#article {border-top: 1px gray solid}
.pullquote {float: right; font-weight: bold;
border: 1px lightgrey solid; width: 10em; clear: both}
P {text-indent: 2em;margin-top:0pt;margin-bottom: 0pt;font-size: 10pt}
P.start {text-indent: 0pt}
H1 {color: navy; text-align: center; border-top: 1px gray solid;
border-bottom: 1px gray solid; background: lightblue;}
H3 {clear: both;margin-bottom: 0pt}
Last, if you are running Internet Explorer 5.0, you can view a version of the first two pages of this article written using XML, transformed using the described XSL, and formatted with CSS! We also recommend you read our followup article that shows you how to use XML and XSL on the server using ASP. By performing the transformations on the server you are not limited to IE5 only. Page 1:Building Documents with XML, XSL, and CSS © 1997-2000 InsideDHTML.com, LLC. All rights reserved. |