Figure 3   MsMag XML Code


 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE MSMAG SYSTEM "MsMag.dtd">
 <?xml-stylesheet type="text/xsl" href="MsMag.xsl"?>
 
 <MSMAG name="&MIND;" publisher="&MFI;" description="&MIND_D;">
 <EDITORIAL volume="4" number="3" month="March" />
 
 <COVER
    title="Windows 2000" 
    subtitle="What Every Web Developer Needs to Know">
 </COVER>
 
 <ARTICLES>
 <FEATURE author="D. Esposito">
 Windows 2000 for Web Developers</FEATURE> 
 <FEATURE author="B. Shankle">
 Find Recombinant Success with Windows DNA</FEATURE > 
 <FEATURE author="M. Tabini">
 Using Stored Procedures in SQL Server</FEATURE> 
 <FEATURE author="C. Nolan">
 Put Advanced SQL Server Features to Work</FEATURE> 
 
 <COLUMN name="Flux" author="D. Boling">
 Pentium III</COLUMN> 
 <COLUMN name="New Stuff" author="T. Carey">
 </COLUMN> 
 <COLUMN name="Geektogeek" author="R. Hess">
 </COLUMN> 
 <COLUMN name="Beyond the Browser" author="K. Spencer">
 Visual InterDev 6.0 Form Manager</COLUMN> 
 <COLUMN name="FAQ" author="K. Kotipalli">
 Namespace Extension AppWizard</COLUMN> 
 <COLUMN name="Extreme C++" author="S. Zimmerman">
 Scalability, State and MTS</COLUMN> 
 </ARTICLES>
 
 </MSMAG>

Figure 5   MsMag.dtd


 <!-- Document Type Definition for a Magazine Language -->
 
 <!ENTITY MSJ    "Microsoft Systems Journal">
 <!ENTITY MIND   "Microsoft Internet Developer">
 <!ENTITY MIND_D "The Microsoft Magazine for Web Developers">
 <!ENTITY MFI    "Miller Freeman">
 
 <!ENTITY % Binary  "yes | no">
 
 <!ELEMENT MSMAG (EDITORIAL, COVER*, ARTICLES, COMMENTS?)>
 <!ATTLIST MSMAG name        CDATA #REQUIRED
                 publisher   CDATA #REQUIRED
                 description CDATA #IMPLIED>
  
 <!ELEMENT EDITORIAL (#PCDATA)>               
 <!ATTLIST EDITORIAL volume    CDATA #IMPLIED 
                     number    CDATA #IMPLIED 
                     month     CDATA #IMPLIED
                     year      CDATA "1999"  
                     published (%Binary;) #IMPLIED>
 
 <!ELEMENT COVER (#PCDATA)>
 <!ATTLIST COVER title    CDATA #REQUIRED
                 subtitle CDATA #REQUIRED>
 
 <!ELEMENT ARTICLES (FEATURE+, COLUMN+)>
 
 <!ELEMENT FEATURE (#PCDATA)>
 <!ATTLIST FEATURE author CDATA #REQUIRED>
 
 <!ELEMENT COLUMN (#PCDATA)>
 <!ATTLIST COLUMN name   CDATA #REQUIRED
                  author CDATA #REQUIRED>
 
 <!ELEMENT COMMENTS (#PCDATA)>

Figure 6 Common XSL Keywords

Keyword
Description
<xsl:template match=tag>
Defines the HTML code for the given XML tag.
<xsl:value-of select=name>
Returns the value of the specified tag attribute or the text associated with the node.
<xsl:for-each select=name>
...
Repeats what follows for each element that matches the specified tag name.
</xsl:for-each>
<xsl:apply-templates match=name>
Applies all the possible templates to the elements that match the description.
<xsl:eval>FuncName()</xsl:eval>
Evaluates a piece of script code (VBScript or JScript). FuncName is the name of the function to execute. What the function returns replaces the command. The function can access the XML object model using this as the entry point to the XML root node.
<xsl:element name="Name">
Defines an HTML element dynamically. Within the body you can add as many attributes as needed.
<xsl:attribute name=name>
Value</xsl:attribute>
Defines an attribute for an element. The name field is the name of the attribute while the content of the tag is the value assigned to the attribute.


Figure 7   MsMag.xsl


 <?xml version="1.0"?>
 
 <xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl" 
                 xmlns:html="http://www.w3.org/TR/REC-html40"
                 result-ns=""
                 language="JScript">
 
 <xsl:template match="/">
 <HTML>
 <HEAD>
 <LINK REL="stylesheet" TYPE="text/css" HREF="msmag.css"/>
 <TITLE><xsl:value-of select="MSMAG/@name"/>, <xsl:value-of select="MSMAG/EDITORIAL/@month"/>
 <xsl:value-of select="MSMAG/EDITORIAL/@year"/> </TITLE>
 </HEAD>
 
 <BODY>
 <TABLE width="100%">
 <TR>
 <TD class="EditVolume">Volume <xsl:value-of select="MSMAG/EDITORIAL/@volume"/> </TD>
 <TD class="EditVolume">Number <xsl:value-of select="MSMAG/EDITORIAL/@number"/> </TD>
 <TD class="EditIssue"> 
 <xsl:value-of select="MSMAG/EDITORIAL/@month"/> <xsl:value-of select="MSMAG/EDITORIAL/@year"/> 
 </TD>
 </TR>
 </TABLE>
 
 <HR />
 
 <TABLE width="100%">
 <TD class="Desc"> <xsl:value-of select="MSMAG/@description"/> </TD>
 <TD class="Publ"> <xsl:value-of select="MSMAG/@publisher"/> </TD>
 </TABLE>
 
 <HR />
 
 <TABLE width="100%">
 <TR><TD class="Magz"> <xsl:value-of select="MSMAG/@name"/> </TD></TR>
 <TR><TD class="IssueTitle"><xsl:eval>GetTitle()</xsl:eval>  </TD></TR>
 <TR><TD class="IssueSubTitle"> <xsl:eval>GetSubTitle()</xsl:eval> </TD></TR>
 </TABLE>
 
 <TABLE width="100%">
 <TR>
 
 <TD valign="top">
 <TABLE bgcolor="lightyellow" border="1" width="100%">
 <TR><TH class="ColTitle">Features</TH></TR>
 
 <TD class="StdText">
 <xsl:for-each select="MSMAG/ARTICLES">
     <xsl:apply-templates select="FEATURE"/>
 </xsl:for-each>
 </TD>
 </TABLE>
 </TD>
 
 <TD valign="top">
 <TABLE bgcolor="lightgrey" border="1" width="100%">
 <TR><TH class="ColTitle">Columns</TH></TR>
 
 <TD class="StdText">
 <xsl:for-each select="MSMAG/ARTICLES">
     <xsl:apply-templates select="COLUMN"/>
 </xsl:for-each>
 </TD>
 </TABLE>
 </TD>
 
 </TR>
 </TABLE>
 
 </BODY>
 </HTML>
 
 </xsl:template>
 
 
 <xsl:script language="JScript">
 <![CDATA[
 
 function GetTitle() {
   list = this.selectNodes("MSMAG/COVER");
   if (list.length == 0)
     return "No title provided"; 
   else
     return list.item(0).attributes.getNamedItem("title").text;
 }
 
 function GetSubTitle() {
   list = this.selectNodes("MSMAG/COVER");
   if (list.length == 0)
     return "No subtitle provided"; 
   else
     return list.item(0).attributes.getNamedItem("subtitle").text;
 }
 
 ]]>
 </xsl:script>
 
 
 <xsl:template match="COLUMN">
 <B><xsl:value-of select="@name"/>-</B> <xsl:value-of select="@author"/>,
 <I><xsl:value-of /></I> <HR />
 </xsl:template>
 
 <xsl:template match="FEATURE">
 <xsl:value-of select="@author"/>, <I><xsl:value-of /></I> <HR />
 </xsl:template>
 
 </xsl:stylesheet>

Figure 10   Detecting the Browser


 <% 
   uAgent = Request.ServerVariables("HTTP_USER_AGENT")
   if Instr(uAgent, "MSIE 5.0") <= 0 then
     Set xml = Server.CreateObject("Microsoft.XMLDOM")
     Set xsl = Server.CreateObject("Microsoft.XMLDOM")
 
     ' fully-qualified name for the XML and XSL files
     path = Request.ServerVariables("PATH_TRANSLATED")
     fileXML = Replace(path, ".asp", ".xml", 1)
     fileXSL = Left(path, InstrRev(path, "\")) + "MsMag.xsl"
 
     ' load the documents
     xml.load(fileXML)   
     xsl.load(fileXSL)    
 
     ' return the related HTML code
     Response.Write xml.transformNode(xsl.documentElement)
     Response.End
   end if
 %>

Figure 11   XML for Other Browsers


 <% 
   uAgent = Request.ServerVariables("HTTP_USER_AGENT")
   if Instr(uAgent, "MSIE 5.0") <= 0 then
     Set xml = Server.CreateObject("Microsoft.XMLDOM")
     Set xsl = Server.CreateObject("Microsoft.XMLDOM")
 
     ' get the fully-qualified name for the XML and XSL files
     path = Request.ServerVariables("PATH_TRANSLATED")
     fileXML = Replace(path, ".asp", ".xml", 1)
     fileXSL = Left(path, InstrRev(path, "\")) + "MsMag.xsl"
     
     ' read the ASP file into a variable
     Set fso = Server.CreateObject("Scripting.FileSystemObject")
     Set f = fso.OpenTextFile(path, 1, 0)
     strXML = f.ReadAll()
     f.Close
 
     ' strip off the chars until the final % 
     strEndAsP = Chr(37) & ">" 
     x = Instr(strXML, strEndASP)
     strXML = Right(strXML, Len(strXML)-x-(Len(strEndASP)+1))
    
     ' creates a XML file on the fly and assigns it the XML body
     Set f = fso.CreateTextFile(fileXML)
     f.Write strXML
     f.Close
 
     ' load the documents
     xml.load(fileXML)   
     xsl.load(fileXSL)    
 
     ' return the related HTML code and delete the temp XML file
     Response.Write xml.transformNode(xsl.documentElement)
     fso.DeleteFile fileXML
     Response.End
   end if
 %>

Figure 12   A Typical XML Server Page


 <% 
   uAgent = Request.ServerVariables("HTTP_USER_AGENT")
   if Instr(uAgent, "MSIE 5.0") <= 0 then
     Set xml = Server.CreateObject("Microsoft.XMLDOM")
     Set xsl = Server.CreateObject("Microsoft.XMLDOM")
 
     ' get the fully-qualified name for the XML and XSL files
     path = Request.ServerVariables("PATH_TRANSLATED")
     fileXML = Replace(path, ".asp", ".xml", 1)
     fileXSL = Left(path, InstrRev(path, "\")) + "MsMag.xsl"
     
     ' read the ASP file into a variable
     Set fso = Server.CreateObject("Scripting.FileSystemObject")
     Set f = fso.OpenTextFile(path, 1, 0)
     strXML = f.ReadAll()
     f.Close
 
     ' strip off the chars until the final % 
     strEndAsP = Chr(37) & ">" 
     x = Instr(strXML, strEndASP)
     strXML = Right(strXML, Len(strXML)-x-(Len(strEndASP)+1))
    
     ' creates a XML file on the fly and assigns it the XML body
     Set f = fso.CreateTextFile(fileXML)
     f.Write strXML
     f.Close
 
     ' load the documents
     xml.load(fileXML)   
     xsl.load(fileXSL)    
 
     ' return the related HTML code
     Response.Write xml.transformNode(xsl.documentElement)
     fso.DeleteFile fileXML
     Response.End
   end if
 %>
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml-stylesheet type="text/xsl" href="MsMag.xsl"?>
 <!DOCTYPE MSMAG SYSTEM "MsMag.dtd">
 
 
 <MSMAG name="&MIND;" publisher="&MFI;" description="&MIND_D;">
 <EDITORIAL volume="4" number="3" month="March" />
 
 <COVER
    title="Windows 2000"
    subtitle="What Every Web Developer Needs to Know">
 </COVER>
 
 <ARTICLES>
 <FEATURE author="D. Esposito">
 Windows 2000 for Web Developers</FEATURE> 
 <FEATURE author="B. Shankle">
 Find Recombinant Success with Windows DNA</FEATURE > 
 <FEATURE author="M. Tabini">
 Using Stored Procedures in SQL Server</FEATURE> 
 <FEATURE author="C. Nolan">
 Put Advanced SQL Server Features to Work</FEATURE> 
 
 <COLUMN name="Flux" author="D. Boling">
 Pentium III</COLUMN> 
 <COLUMN name="New Stuff" author="T. Carey">
 </COLUMN> 
 <COLUMN name="Geektogeek" author="R. Hess">
 </COLUMN> 
 <COLUMN name="Beyond the Browser" author="K. Spencer">
 Visual InterDev 6.0 Form Manager</COLUMN> 
 <COLUMN name="FAQ" author="K. Kotipalli">
 Namespace Extension AppWizard</COLUMN> 
 <COLUMN name="Extreme C++" author="S. Zimmerman">
 Scalability, State and MTS</COLUMN> 
 </ARTICLES>
 
 </MSMAG>

Figure 13   XML to HTML Offline Converter


 // CreateHTML.js 
 // XML to HTML converter
 // 
 // Usage: CreateHTML xml xsl html
 // --------------------------------------------------------
 
 
 var xml, xsl;
 var fileXML, fileXSL, fileHTM;
 var fso, f;
 
 fileXML = WScript.Arguments(0);
 fileXSL = WScript.Arguments(1);
 fileHTM = WScript.Arguments(2);
 
 xml = new ActiveXObject("Microsoft.XMLDOM");
 xsl = new ActiveXObject("Microsoft.XMLDOM");
 xml.load(fileXML);
 xsl.load(fileXSL);
 
 fso = new ActiveXObject("Scripting.FileSystemObject");
 f = fso.CreateTextFile(fileHTM);
  
 f.Write(xml.transformNode(xsl.documentElement));
 f.Close();