A348 ASP ADO XML XSL

Modified

Basics

Mixing ASP JavaScript, HTML, SQL, etc. in ASP scripts produces hard to write and read scripts that entangle the logic with the user interface. We have also seen that XML data can be transformed by XSL to generate HTML, very useful in separating representation data from its presentation.

Our goal is to divide the program logic from the user interface, allowing programmers and user interface designers to work somewhat independently. With data maintained mostly in databases, we will develop patterns for transforming the database tables into the variable part of the user interface. Our end result will be an ASP program to interact with the user and access data bases and XSL to present the user interface and data.

First an example of ASP and databases that combines the logic and user interface then a review of database tables, XML and XSL.

Access Database

Let's examine an Access database table first. The Portfolio table at right has 3 traders, 6 records, each with 4 fields: STOCKID, ID, SYMBOL and SHARES. Generally our ASP programs will be reading and updating the tables but, of course, we can use the Access application to do the same operations.

Exercise  0 - Access

  1. Open Access from Start | Programs | Microsoft Access
  2. Open File | Open... and select C:\Project\Project.mdb
  3. Select Tables | PORTFOLIO
  4. Add 5 new records with fields ID, SYMBOL and SHARES
  5. Save and close the table.

ASP and Database

We will again use the Portfolio table from the Stock Trading project as an example case.

To display the table contents in HTML for a browser we will need to:

  1. Select the records and fields
  2. Iterate through the records
  3. Transform the data into HTML for a table
Portfolio.ASP
<%@ Language=JScript%>
<%	
 var conn = Server.CreateObject("ADODB.Connection"); 
 conn.Mode = 3;
 conn.Open ("DSN=Project");
 var rs = conn.Execute("SELECT * FROM Portfolio;");

 Response.Write(
     "<h1>Exercise 0.5</h1>" +
     "<table border='1'><tr>" +
     "  <td>ID</td><td>Symbol</td></tr>");

 while (!rs.EOF) {
     Response.Write(
           "<tr><td>" + rs("ID")+ "</td>" +
           "<td>" + rs("SYMBOL") + "</td></tr>");
     rs.MoveNext();
 }
 Response.Write("</tables>");
 conn.Close();
%>
Table and partial HTML produced
ID Symbol
Ray IBM
Ray MSFT
Harold FORD
Robin UAL
<table border="1" >
  <tr>
	<td>ID</td>
	<td>Symbol</td>
  </tr>
  <tr>
	<td>Ray</td>
	<td>IBM</td>
  </tr>
  <tr>
	<td>Ray</td>
	<td>MSFT</td>
  </tr>
  <tr>
	<td>Harold</td>
	<td>FORD</td>
  </tr>
  <tr>
	<td>Robin</td>
	<td>UAL</td>
  </tr>

The weakness of this solution is that program logic and generation of the user interface (e.g. the table) are combined. Changes to logic requires a programmer; changes to the user interface requires a user interface designer to design and test the interface and a programmer to change the code. We prefer to separate the two so that the programmer implements the program logic and an interface designer implements the interface.

Exercise  0.5 - ASP

  1. Open FrontPage
  2. Open File | New
  3. Copy, paste and save the above Portfolio.asp to a virtual drive (i.e. C:\Project).
  4. Test by loading Portfolio.asp into the browser (i.e. http://localhost/Project/Portfolio.asp).
  5. Change the Portfolio.asp to display SHARES also.
  6. Test by loading Portfolio.asp into the browser (i.e. http://localhost/Project/Portfolio.asp)

XML and XSL Transformations - A Review

We will again use the Portfolio table from the Stock Trading project as an example case. The table with three traders appears at right.

The Portfolio database table can be represented as the XML structure below:

Portfolio.xml
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" 
      href="PortfolioContent.htm"?>

 <Portfolio>
    <STOCKID>1
	<ID>Ray</ID><SYMBOL>IBM</SYMBOL><SHARES>10</SHARES>
    </STOCKID>
    <STOCKID>2
	<ID>Ray</ID><SYMBOL>MSFT</SYMBOL><SHARES>100</SHARES>
    </STOCKID>
    <STOCKID>3
	<ID>Harold</ID><SYMBOL>FORD</SYMBOL><SHARES>15</SHARES>
    </STOCKID>
    <STOCKID>4
	<ID>Robin</ID><SYMBOL>UAL</SYMBOL><SHARES>230</SHARES>
    </STOCKID>
    <STOCKID>5
	<ID>Robin</ID><SYMBOL>FORD</SYMBOL><SHARES>100</SHARES>
    </STOCKID>
</Portfolio>

We have seen how Portfolio.xml can be transformed using XSL into HTML for the browser. The following is the PortfolioContent.htm for the transformation, yielding the same result as Portfolio.ASP earlier.

PortfolioContent.htm
<xsl:stylesheet version="2.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns="http://www.w3.org/1999/xhtml">
  <xsl:output method="html" />

  <xsl:template name="PortfolioContent">
       <h1>Exercise 1 and 2</h1>
       <table border="1">
	<tr>
	  <td>ID</td>
	  <td>Symbol</td>
	</tr>
	<xsl:for-each select="Portfolio/STOCKID">
	  <tr>
	     <td><xsl:value-of select="ID" /></td>
	     <td><xsl:value-of select="SYMBOL" /></td>
	  </tr>
	</xsl:for-each>
      </table>
  </xsl:template>

  <xsl:template match="/">
      <xsl:call-template name="PortfolioContent" />
  </xsl:template>
</xsl:stylesheet>

ID Symbol
Ray IBM
Ray MSFT
Harold FORD
Robin UAL

 

HTML output

<table border="1" >
  <tr>
	<td>ID</td>
	<td>Symbol</td>
  </tr>
  <tr>
	<td>Ray</td>
	<td>IBM</td>
  </tr>
  <tr>
	<td>Ray</td>
	<td>MSFT</td>
  </tr>
  <tr>
	<td>Harold</td>
	<td>FORD</td>
  </tr>
  <tr>
	<td>Robin</td>
	<td>UAL</td>
  </tr>
 </table>

Up to this point, we have used the browser to combine XML and XSL to display a HTML page. The approach is illustrated below where the XML file references the XSL file when loaded to display a table based upon the data structure defined in XML. 

How it works 

  1. IE browser loads and parses the XML file into a tree. 
  2. XSL style sheet file loaded and parsed to transform the tree.
  3. Transformed XML by XSL produces an HTML result.
  4. IE renders the HTML to display.

Exercise  1 - XML XSL

  1. Copy and paste as HTML the above Portfolio.xml and PortfolioContent.htm to a virtual drive (i.e. C:\Project).
  2. Test by loading Portfolio.xml into the browser (i.e. http://localhost/Project/Portfolio.xml).
  3. Change the PortfolioContent.htm to display SHARES also.
  4. Test by loading Portfolio.xml into the browser.

ASP with XML and XSL

Combining XML and XSL on the server running an ASP program rather than on the browser client has three key advantages:

  1. The XML can be generated dynamically by the server through user interaction, extraction from a database, etc.
  2. Pure HTML can be produced as a result of the XML/XSL transformations.
  3. The XML/XSL tree can be modified before writing to the client.

The simplest use is to combine XML and XSL on the server in ASP to apply the transformations and write out the result as HTML. The following ASP example:

  1. builds the XML tree data structure named source from the Portfolio.xml file,
  2. transforms the XML tree to HTML by applying the XSL in file PortfolioContent.htm,
  3. writes the transformed tree to browser as HTML
Portfolio.asp
<%@ LANGUAGE = JScript %>
<%
  	// Load the XML 
  var xml = Server.CreateObject("MSXML2.DOMDocument");
  xml.async = false;
  xml.load(Server.MapPath("Portfolio.xml"));

  	// Load the XSL
  var xsl = Server.CreateObject("MSXML2.DOMDocument");
  xsl.async = false;
  xsl.load(Server.MapPath("PortfolioContent.htm"));

  Response.Write(xml.transformNode(xsl));
%>

 

Exercise  2 - ASP XML XSL

  1. Copy and paste the above Portfolio.ASP to a virtual drive (i.e. C:\Project).
  2. Test by loading Portfolio.ASP into the browser (i.e. http://localhost/Project/Portfolio.asp).
  3. Results should be the same as Exercise 1.
  4. In browser, View | Source, to examine the HTML output from the ASP.

XML and Database

XML can be dynamically generated directly from a database rather than coding the XML by hand. The following example:

  1. selects all records from the Portfolio database table - "SELECT ID, SYMBOL FROM Portfolio"
  2. constructs the XML parse tree from the table - rs.Save (xmlDoc, 1);
  3. Saves the XML, not necessary but useful to understand the database to XML conversion - xmlDoc.save(Server.MapPath("FromPortfolio.xml"))
  4. applies the XSL transformations to the tree from file PortfolioContent.htm. The transformation generates a table of ID and SYMBOL - xmlDoc.transformNode(xsl)
  5. writes the transformed tree to the browser as HTML

Note that database table field names are transformed to XML attributes. For example, the first table row entry for fields ID and SYMBOL is XML:

 <z:row ID="Ray" SYMBOL="IBM"/>.

Portfolio.ASP
<%@ Language=JScript%>
<%	
   conn = Server.CreateObject("ADODB.Connection"); 
   conn.Mode = 3;
   conn.Open ("DSN=Project");
   rs = conn.Execute("SELECT ID, SYMBOL FROM Portfolio");

   var xmlDoc = Server.CreateObject("Msxml2.DOMDocument");
   xmlDoc.async = false;
   rs.Save (xmlDoc, 1) ;     
         // Convert rs recordset to XML tree
         // Save as XML (not required)
  xmlDoc.save(Server.MapPath("FromPortfolio.xml"))

   var xsl = Server.CreateObject("Msxml2.DOMDocument");
   xsl.async = false;           
         // Convert XML tree using XSL   
   xsl.load(Server.MapPath("PortfolioContent.htm"))
         // Write tree as HTML
   Response.Write(xmlDoc.transformNode(xsl)); 
   conn.Close();
%>

Table and partial HTML produced

ID Symbol
Ray IBM
Ray MSFT
Harold FORD
Robin UAL
Robin FORD
<table border="1" >
  <tr>
	<td>ID</td>
	<td>Symbol</td>
  </tr>
  <tr>
	<td>Ray</td>
	<td>IBM</td>
  </tr>
  <tr>
	<td>Ray</td>
	<td>MSFT</td>
  </tr>
PortfolioContent.htm
<xsl:stylesheet version="2.0" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
     xmlns="http://www.w3.org/1999/xhtml" 
     xmlns:rs="urn:schemas-microsoft-com:rowset" 
     xmlns:z="#RowsetSchema">
 <xsl:output method="html" />

 <xsl:template name="PortfolioContent">
     <h1>Exercise 3</h1>
     <table border="1" ID="Table1">
       <tr>
          <td>ID</td>
          <td>Symbol</td>
        </tr>
        <xsl:for-each select="xml/rs:data/z:row">
           <tr>
             <td><xsl:value-of select="@ID" /></td>
             <td><xsl:value-of select="@SYMBOL" /></td>
            </tr>
         </xsl:for-each>
       </table>
  </xsl:template>

  <xsl:template match="/">
       <xsl:call-template name="PortfolioContent" />
  </xsl:template>
</xsl:stylesheet>

Partial XML produced by rs.Save (xmlDoc, 1);  

<xml>
 <rs:data>
   <z:row ID="Ray" SYMBOL="IBM"/>
   <z:row ID="Ray" SYMBOL="MSFT"/>
   <z:row ID="Harold" SYMBOL="FORD"/>
   <z:row ID="Robin" SYMBOL="UAL"/>
   <z:row ID="Robin" SYMBOL="FORD"/>
 </rs:data>
</xml>

 

Exercise  3 - ASP XML XSL Database

  1. Define Project as a data source on your machine. Click for instructions if not already defined.
  2. Copy and paste Portfolio.ASP to a virtual drive (i.e. C:\Project). Modify to select SHARES also.
  3. Copy and paste PortfolioContent.htm same directory. Modify to output a column for SHARES.
  4. Test by loading Portfolio.ASP into the browser (i.e. http://localhost/Project/Portfolio.asp).
  5. In browser, View | Source, to examine the HTML output from the ASP.

 

  1. Open FromPortfolio.xml in FrontPage. This was produced by Portfolio.asp from the Portfolio database table.
  2. Insert as the top line:
    • <?xml-stylesheet type="text/xsl"  href="PortfolioContent.htm"?>
  3. Test by loading FromPortfolio.xml into browser (i.e. http://localhost/Project/FromPortfolio.xml).
  4. The results should be identical to executing the Portfolio.asp script.

Join Database Tables

Combining or joining data from several database table sources is a fundamental operation of relational database systems. For the project, we will often need to join data from two or more table through defined relationships.

Consider the portfolio problem. A trader needs a list of stock symbols, number of shares and total value of each stock. The necessary data is held in the two tables: Portfolio and Stock.

The two tables share a common field, SYMBOL, that defines a many to one relation from Portfolio to Stock (i.e. there are many FORD symbols in Portfolio to one FORD symbol in Stock). To produce Harold's portfolio requires data from both tables, ID='Harold', SHARES and SYMBOL from Portfolio; and PRICE for the corresponding SYMBOL from Stock table.

Logically, we first need all the "Harold" Portfolio records and all the Stock records where the SYMBOL matches. In database terms, we need a new table from joining the tables when the Portfolio SYMBOL = Stock Symbol. The SQL statement giving all fields is:

Reducing the fields to those needed:

and produces the following new table of records. The INNER JOIN is also know more intuitively as the EQUI-JOIN.

Since we wanted Harold's portfolio, we need to keep only records where ID='Harold' by:

The ASP and XSL to produce Harold's portfolio is given below. Notice that only the SELECT statement changed in the ASP from our previous example. Here we only need the SYMBOL and PRICE. The XSL file, PortfolioContent.htm must be changed to accommodate the PRICE field.

Portfolio.ASP
<%@ Language=JScript%>
<%	
   conn = Server.CreateObject("ADODB.Connection"); 
   conn.Mode = 3;
   conn.Open ("DSN=Project");
   rs = conn.Execute(
     "SELECT PORTFOLIO.SYMBOL, PRICE " +
     "FROM STOCK INNER JOIN PORTFOLIO ON " +
     "STOCK.SYMBOL = PORTFOLIO.SYMBOL " +
     "WHERE ID='Harold';");

   var xmlDoc = Server.CreateObject("Msxml2.DOMDocument");
   xmlDoc.async = false;
   rs.Save (xmlDoc, 1) ;        // Convert recordset to XML
                                           // Save as XML
    var xsl = Server.CreateObject("Msxml2.DOMDocument");
   xsl.async = false;              // Convert XML tree using XSL   
   xsl.load(Server.MapPath("PortfolioContent.htm"))
                                            // Write tree as HTML
   Response.Write(xmlDoc.transformNode(xsl)); 
   conn.Close();
%>

Table and partial HTML produced

Symbol Price
GMC 38.1000
FORD 15.6700
<table border="1">
 <tr>
	<td>Symbol</td>
	<td>Price</td>
 </tr>
 <tr>
	<td>GMC</td> <td>38.1000</td>
 </tr>
 <tr>
	<td>FORD</td> <td>15.6700</td>
 </tr>
</table>
PortfolioContent.htm
<xsl:stylesheet version="2.0" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
     xmlns="http://www.w3.org/1999/xhtml" 
     xmlns:rs="urn:schemas-microsoft-com:rowset" 
     xmlns:z="#RowsetSchema">
 <xsl:output method="html" />

 <xsl:template name="PortfolioContent">
   <h1>Exercise 4</h1>
   <table border="1">
     <tr>
       <td>Symbol</td>
       <td>Price</td>
     </tr>
     <xsl:for-each select="xml/rs:data/z:row">
        <tr>
         <td><xsl:value-of select="@SYMBOL" /></td>       
         <td><xsl:value-of select="@PRICE" /></td>
        </tr>
      </xsl:for-each>
    </table>
  </xsl:template>

  <xsl:template match="/">
       <xsl:call-template name="PortfolioContent" />
  </xsl:template>
</xsl:stylesheet>

Partial XML produced by rs.Save (xmlDoc, 1);  

<xml>
 <rs:data>
    <z:row SYMBOL="GMC" PRICE="38.1000"/>
    <z:row SYMBOL="FORD" PRICE="15.6700"/>
 </rs:data>
</xml>

    

 

Exercise  4 - ASP XML XSL Database Join

  1. Open the Project.mdb file in Access
  2. Click on Queries | Create Query in Design View
  3. Close the Show Table dialog.
  4. Click in menu: View | SQL View
  5. Copy and paste the following. Change 'Harold' to an ID in your Portfolio table:
SELECT * FROM STOCK INNER JOIN PORTFOLIO ON STOCK.SYMBOL = PORTFOLIO.SYMBOL WHERE ID='Harold'
  1. Click in menu: Query | Run
  2. Click in menu: View | SQL View
  3. Modify to select only PRICE, SHARES, Portfolio.SYMBOL and ID.
  4. Click in menu: Query | Run
  1. Define Project as a data source on your machine. Click for instructions if not already defined.
  2. Copy and paste Portfolio.ASP to a virtual drive (i.e. C:\Project). Modify to select SHARES also.
  3. Copy and paste PortfolioContent.htm same directory. Modify to output a column for SHARES.
  4. Test by loading Portfolio.ASP into the browser (i.e. http://localhost/Project/Portfolio.asp).
  5. In browser, View | Source, to examine the HTML output from the ASP.

Computing New Fields

The portfolio still needs a total value of each stock requiring the computation: STOCKVALUE = SHARES * PRICE. The SQL statement is:

The ASP and XSL to produce Harold's portfolio is given below. Notice that only the SELECT statement changed in the ASP from our previous example. Here we only need the SYMBOL, PRICE and computed STOCKVALUE. The XSL file, PortfolioContent.htm must be changed to accommodate the STOCKVALUE field.

Portfolio.ASP
<%@ Language=JScript%>
<%	
   conn = Server.CreateObject("ADODB.Connection"); 
   conn.Mode = 3;
   conn.Open ("DSN=Project");
   rs = conn.Execute(
     "SELECT PORTFOLIO.SYMBOL, PRICE,  " +
     "SHARES*PRICE as STOCKVALUE " +
     "FROM STOCK INNER JOIN PORTFOLIO ON " +
     "STOCK.SYMBOL = PORTFOLIO.SYMBOL " +
     "WHERE ID='Harold';");

   var xmlDoc = Server.CreateObject("Msxml2.DOMDocument");
   xmlDoc.async = false;
   rs.Save (xmlDoc, 1) ;        // Convert rs recordset to XML tree
                                           
   var xsl = Server.CreateObject("Msxml2.DOMDocument");
   xsl.async = false;              // Convert XML tree using XSL   
   xsl.load(Server.MapPath("PortfolioContent.htm"))
                                            // Write tree as HTML
   Response.Write(xmlDoc.transformNode(xsl)); 
   conn.Close();
%>

Partial XML produced by rs.Save (xmlDoc, 1);  

<xml>
 <rs:data>
   <z:row SYMBOL="GMC" PRICE="38.1000" STOCKVALUE="762.0000"/>
   <z:row SYMBOL="FORD" PRICE="15.6700" STOCKVALUE="235.0500"/>
 </rs:data>
</xml>

 

Exercise  4.5 - Computing New Fields

  1. Open the Project.mdb file in Access
  2. Click on Queries | Create Query in Design View
  3. Close the Show Table dialog.
  4. Click in menu: View | SQL View
  5. Copy and paste the following query. Change 'Harold' to an ID in your Portfolio table:
SELECT * FROM STOCK INNER JOIN PORTFOLIO ON STOCK.SYMBOL = PORTFOLIO.SYMBOL WHERE ID='Harold'
  1. Click in menu: Query | Run
  2. Click in menu: View | SQL View
  3. Modify the query to compute to compute the STOCKVALUE field.
  4. Click in menu: Query | Run

 

Editing the Tree

We've seen that XML can be generated dynamically in ASP from a database and transformed to HTML by XSL. This section examines how to modify the XML, XSL or HTML in a parse tree directly. For example, a user name can be used to personalize a HTML page; the HTML file is parsed into the tree, a node for user name inserted, and the HTML then output to produce the personalized HTML page. 

Editing nodes

In the example below, the <Name> element text of file NameEdit.htm is assigned new text of 'Ray Wisman' and written to browser.

Points of note:

  1. Assign HTML document parse tree root - var root = htmlDOC.documentElement;
  2. Select the node to access - var node = root.selectSingleNode("body/Name")
  3. Modify the node text - node.text = 'Ray Wisman';
  4. Write the document tree to browser - Response.Write(htmlDOC.xml);
<%@ LANGUAGE = JScript %>
<%
  		// Load the HTML file into parse tree
  var htmlDOC = Server.CreateObject("MSXML2.DOMDocument");
  htmlDOC.async = false;
  htmlDOC.load(Server.MapPath("EditNode.htm"));
		// root of document
  var root = htmlDOC.documentElement;
                       // Make current node "body/Name"
  var node = root.selectSingleNode("body/Name"); 
                      	// Assign current node text to 'Ray Wisman'
  node.text = 'Ray Wisman';
                    	// Write tree as XML
  Response.Write(htmlDOC.xml);
%>
EditNode.htm

<html xmlns="http://www.w3.org/1999/xhtml">
  <body>
     Welcome <Name>Anonymous</Name>
     to the personalized Web page.
  </body>
</html>


HTML output

<html xmlns="http://www.w3.org/1999/xhtml">
  <body>
     Welcome <Name>Ray Wisman</Name>
     to the personalized Web page.
  </body>
</html>

 

Creating XML data

We have automatically converted relational database tables into XML trees before transforming using XSL, allowing us to focus on the logic in ASP rather than the user interface. XML trees can also be constructed directly. The following example defines an XML tree in which values are inserted to be displayed by XSL.

Points of note:

  1. var area=height*width; - calculates the area of a rectangle from the height and width,
  2. xmlData.loadXML(
                "<RECTANGLE><AREA/><WIDTH/><HEIGHT/></RECTANGLE>");

    Creates a XML tree with nodes RECTANGLE, AREA, WIDTH, HEIGHT
     
  3. var node = root.selectSingleNode("AREA"); - selects the AREA node in the XML tree.
  4. node.text = area; - stores the area value as text in XML tree for AREA node,
  5. Response.Write(xmlData.transformNode(xslDoc)); - transforms the XML with XSL to HTML

 

 Tree construction 

   xmlData.loadXML(
                                  "<RECTANGLE>" +
                      "<AREA/><WIDTH/><HEIGHT/>" +   
                                  "</RECTANGLE>"); 

 

 Tree with text nodes added 

    var node = root.selectSingleNode("HEIGHT");
    node.text = 23.5;

CreateXML.asp

<%@ Language=JScript%>
<%	   
  var height=23.5;
  var width=10.0;
  var area=height*width;
  
  var xmlData = Server.CreateObject("Microsoft.XMLDOM");
  xmlData.async = false;
  xmlData.loadXML(
                                  "<RECTANGLE>" +
                      "<AREA/><WIDTH/><HEIGHT/>" +    
                                  "</RECTANGLE>");  
  
  var xslStyle = Server.CreateObject("Microsoft.XMLDOM");
  xslStyle.async = false;
  xslStyle.load(Server.MapPath("Rectangle.htm"));

  var root = xmlData.documentElement;	     // Root of XML treee
  var node = root.selectSingleNode("AREA"); // AREA node
  node.text = area;			                //<AREA>235</AREA>
  var node = root.selectSingleNode("HEIGHT"); 	
  node.text = height;
  var node = root.selectSingleNode("WIDTH"); 
  node.text = width;

  Response.Write(xmlData.transformNode(xslStyle));   
%>
Rectangle.htm
<xsl:stylesheet version="2.0" 
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
   xmlns="http://www.w3.org/1999/xhtml">
   <xsl:output method="html" />

   <xsl:template match="/">
       Area of Rectangle
       <xsl:value-of select="RECTANGLE/AREA" />=
       <xsl:value-of select="RECTANGLE/HEIGHT" />*
       <xsl:value-of select="RECTANGLE/WIDTH" />
   </xsl:template>
</xsl:stylesheet>

XML tree after editing AREA, HEIGHT, WIDTH

<RECTANGLE>
   <AREA>235</AREA>
   <WIDTH>10</WIDTH>
   <HEIGHT>23.5</HEIGHT>
</RECTANGLE>


HTML output

Area of Rectangle 235= 23.5 * 10

 

Exercise  4.75 - Nodes and Elements

  1. Copy and paste CreateXML.ASP and Rectangle.htm to a virtual drive (i.e. C:\A348).
  2. Test by:
    • localhost/A348/CreateXML.asp
  3. Define XML with:
    1. Root: PERSON
    2. Elements: NAME and AGE
  4. Set the text of NAME and AGE elements to your name and age similar to:
    • var node = root.selectSingleNode("HEIGHT");
    • node.text = height;
  5. Modify Rectangle.htm to display AGE and NAME.
    • The XSL style sheet should have:    <xsl:output method="html" />
  6. Test by loading CreateXML.ASP into the browser.
  7. In browser, View | Source, to examine the HTML output from the ASP.

 

Deleting nodes

This approach can be used with user input from HTML forms to tailor an otherwise static HTML page for a specific purpose. In the following example, if a user makes a purchase, the <Nosale> node is deleted; if they do not make a purchase the <Sale> node is deleted. 

The script consists of two parts, one to handle a sale and a no sale.

Nosale:

  1. When the user request is empty
  2. select the node "body/Sale" 
  3. remove it from the tree

Sale:

  1. When user request is not empty, for example, contains 
    "Purchase=surf board"
  2. select the "body/Nosale" node
  3. remove from tree
  4. select the "body/Sale/Purchase" node
  5. add "surf board" text

The tree is then output as HTML.

<%@ LANGUAGE = JScript %>
<%
  // Load the HTML
  var htmlDOC = Server.CreateObject("MSXML2.DOMDocument");
  htmlDOC.async = false;
  htmlDOC.load(Server.MapPath("DeleteNode.htm"));
  var root = htmlDOC.documentElement;

  if(Request("Purchase").count == 0) {      // No Purchase
      var node = root.selectSingleNode("body/Sale"); 
      var parent = node.parentNode; 
      parent.removeChild(node);
  }
  else {
      var node = root.selectSingleNode("body/Nosale"); 
      var parent = node.parentNode; 
      parent.removeChild(node);
      var node = root.selectSingleNode("body/Sale/Purchase"); 
      node.text = Request("Purchase");
  }
  Response.Write(htmlDOC.xml);
%>

DeleteNode.asp?Purchase=surf board

DeleteNode.htm

<html xmlns="http://www.w3.org/1999/xhtml">
  <body>
     We <b>appreciate</b> your business.
     <Sale>
          Thanks for your money. 
          Your 
            <Purchase></Purchase> 
           will be in the mail.
      </Sale>
      <Nosale>
           Sorry that we didn't have what you wanted.
      </Nosale>
   </body>
</html>


HTML output

<html xmlns="http://www.w3.org/1999/xhtml">
  <body>
      We <b>appreciate</b> your business.
      <Sale>
          Thanks for your money. 
          Your 
            <Purchase>surf board</Purchase> 
           will be in the mail.
      </Sale>
   </body>
</html>

Points of note:

  1. Remove either the <Sale> or <Nosale> node by locating the parent and removing the child:
  2. Modify the <Purchase> node adding the text of user input - node.text = Request("Purchase");

 

Adding Text Nodes

A text node consists of text but not an element (i.e. <element>). In the following a text node is added whether or not a purchase is made, with appropriate text of the node. The appropriate place to add the node here is as a child of the <body> node. 

The tree is then output as HTML.

<%@ LANGUAGE = JScript %>
<%
  // Load the HTML
  var htmlDOC = Server.CreateObject("Microsoft.XMLDOM");
  htmlDOC.async = false;
  htmlDOC.load(Server.MapPath("AddNode.htm"));
  var root = htmlDOC.documentElement;

  var parent = root.selectSingleNode("body"); 
  var textNode;

  if(Request("Purchase").count == 0) {        // No Purchase
    textNode = htmlDOC.createTextNode(
                          "Sorry we didn't have what you wanted.");	 
  }
  else {
    textNode = htmlDOC.createTextNode(
                       "Thanks for purchasing the " 
                      + Request("Purchase"));
  }
  parent.appendChild(textNode);
  Response.Write(htmlDOC.xml);
%>
AddNode.htm

<html xmlns="http://www.w3.org/1999/xhtml">
<body>
We <b>appreciate</b> your business.
</body>
</html>


HTML output

<html xmlns="http://www.w3.org/1999/xhtml">
 <body>
  We <b>appreciate</b> your business.
  Thanks for purchasing the surf board
 </body>
</html>


AddNode.asp?Purchase=surf board


Points of note:

  1. Locate the parent node <body>.
  2. Create a new text node in the tree:
  3. Add the text node as a child of <body>, by default as the last child.

 

Adding Elements

An element in XML is <element> </element>. An element and a text node is <element> text </element>. For simplicity, we have only diagrammed elements in the parse tree. The previous example added a text node to the tree, this example adds an element and appends a text node to the element. A node is added whether or not a purchase is made, through the text of the node is different. The appropriate place to add the node is as a child of the <body> node. 

The tree is then output as HTML.

AddElement.asp

<%@ LANGUAGE = JScript %>
<%
  var htmlDOC = Server.CreateObject("Microsoft.XMLDOM");
  htmlDOC.async = false;
  htmlDOC.load(Server.MapPath("AddElement.htm"));
  var root = htmlDOC.documentElement;

  var parent = root.selectSingleNode("body"); 
  var element = htmlDOC.createElement("response");

  var textNode;

  if(Request("Purchase").count == 0) {     // No Purchase
     textNode = htmlDOC.createTextNode(
          "Sorry we didn't have what you wanted.");	 
  }
  else {
      textNode = htmlDOC.createTextNode(
     "Thanks for purchasing the " + Request("Purchase"));
  }
 			            	// AppendChild <response> 
  element.appendChild(textNode);  // to parent <body>
  parent.appendChild(element);

  Response.Write(htmlDOC.xml);
%>
AddElement.htm

<html xmlns="http://www.w3.org/1999/xhtml">
  <body>
    We <b>appreciate</b> your business.
  </body>
</html>


HTML output

<html xmlns="http://www.w3.org/1999/xhtml">
 <body>
   We <b>appreciate</b> your business.
   <response xmlns="">
      Thanks for purchasing the boat
   </response>
  </body>
</html>


AddElement.asp?Purchase=boat

 

Points of note:

  1. Create an element named <response>.
  2. Append the text node to the <response> element.
  3. Append the <response> element as a child to the parent.

Exercise  5 - Nodes and Elements

  1. Copy and paste AddElement.ASP and AddElement.htm to a virtual drive (i.e. C:\A348).
  2. Test with and without user input by:
    • localhost/A348/AddElement.asp?Purchase=boat
    • localhost/A348/AddElement.asp
  3. Add element
    1. Modify the ASP script to add an element when the user gives input. 
    2. The element name is the user input.
    3. Append the text node to the element.
  4. Delete the <b> element.
  5. Test by loading AddElement.ASP into the browser.
  6. In browser, View | Source, to examine the HTML output from the ASP.

 

Putting it all together

Editing the XSL/HTML parse tree before applied to transform XML allows us to control at runtime the result of the transform. The following example deletes the element <FIRST> from the XSL parse tree, then applies the XSL tree to the XML to output as HTML.

EditXSL.asp

<%@ LANGUAGE = JScript %>
<%
  var xmlData = Server.CreateObject("Microsoft.XMLDOM");
  xmlData.async = false;
  xmlData.load(Server.MapPath("Portfolio.xml"));

  var xslDoc = Server.CreateObject("Microsoft.XMLDOM");
  xslDoc.async = false;
  xslDoc.load(Server.MapPath("EditXSL.htm"));
  var root = xslDoc.documentElement;

  var node = root.selectSingleNode(
          "body/table/xsl:for-each/tr/FIRST"); 
  var parent = node.parentNode; 
  parent.removeChild(node);
  			// Apply transformations
  Response.Write(xmlData.transformNode(xslDoc));
%>

Portfolio.xml

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" 
      href="EditXSL.htm"?>

 <Portfolio>
    <STOCKID>1
	<ID>Ray</ID><SYMBOL>IBM</SYMBOL>
    </STOCKID>
    <STOCKID>2
	<ID>Ray</ID><SYMBOL>MSFT</SYMBOL>
    </STOCKID>
    <STOCKID>3
	<ID>Harold</ID><SYMBOL>FORD</SYMBOL>
    </STOCKID>
    <STOCKID>4
	<ID>Robin</ID><SYMBOL>UAL</SYMBOL>
    </STOCKID>
    <STOCKID>5
	<ID>Robin</ID><SYMBOL>FORD</SYMBOL>
    </STOCKID>
</Portfolio>  
EditXSL.htm

<html xsl:version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/1999/xhtml">
 <body>
  <table border="1">
    <tr>
      <td>ID</td>
      <td>SYMBOL</td>
    </tr>
    <xsl:for-each select="Portfolio/STOCKID"> 
       <tr>
           <FIRST> 
              <td><xsl:value-of select="ID"/></td>
           </FIRST>
           <td><xsl:value-of select="SYMBOL"/></td>
       </tr>
     </xsl:for-each>
   </table>
 </body>
</html>


Resulting XSL

<html xsl:version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
 <body>
   <table border="1">
     <tr>
        <td>ID</td>
        <td>SYMBOL</td>
     </tr>
     <xsl:for-each select="Portfolio/STOCKID">
       <tr>
          <td><xsl:value-of select="SYMBOL" /></td>
       </tr>
     </xsl:for-each>
    </table>
  </body>
</html>

Points of note:

  1. The element <FIRST> in EditXSL.htm file.
  2. Locate the <FIRST> element node:
  3. Apply transform to produce HTML: