Programmer to ProgrammerTM  
Wrox Press Ltd  
   
  Search ASPToday Living Book ASPToday Living Book
Index Full Text
 
ASPToday Home
 
 
Home HOME
Site Map SITE MAP
Index INDEX
Full-text search SEARCH
Forum FORUM
Feedback FEEDBACK
Advertise with us ADVERTISE
Subscribe SUBSCRIBE
Bullet LOG OFF
                         
      The ASPToday Article
October 17, 2001
      Previous article -
October 16, 2001
   
 
   
   
   
A simple document generation system using ASP and XML   Jason Salas  
by Jason Salas
 
CATEGORY:  XML/Data Transfer  
ARTICLE TYPE: Tutorial Reader Comments
   
    ABSTRACT  
 
Article Rating
 
   Useful
  
   Innovative
  
   Informative
  
 2 responses

Publishing content to the Web is a critical part of competition, but is still largely a complex task, which many organizations aren’t yet equipped for or comfortable with. Jason Salas looks at how we can make Web authoring easy for anyone in the work place, whilst making multi-platform web publishing possibe and ensuring that content syndication is possible to port to external sites.

   
                   
    Article Discussion   Rate this article   Related Links   Index Entries  
   
 
    ARTICLE

Technologies Used:

Summary:

Objectives

Level of Difficulty

Making Web publishing easier

It's the intent of software to make you work smarter, not harder.

One of the biggest challenges that traditional companies face when starting to embrace the online revolution is the publishing aspect of getting their content online (which for them, being newbies, can be a monstrosity of a challenge). Traditional Web authoring mandated that a content author would have to know the intricacies of HTML - which largely ruled out any staffers except for progressive MIS programmers or a few daring advertising and creative people - and also be savvy enough to know how to get their content online.

As the Web continued to mature, more people began to pick up how to create HTML documents, but simultaneously Web access became available from beyond the confines of the normative PC (mobile devices, Internet appliances, etc.) making publishing quite complex in terms of the creation and management of content. Controlling such a system is beyond the normal capacity of most organizations today.

Since I currently manage a Web site for which local news information is the prime attraction, it's important to me to be able to let our content producers easily get their work up online - quickly - without forcing them to actually write complex code (which they shouldn't have to do), and without me having to do the work for them (which I shouldn't have to do). Its part of our responsibility as developers to design and then deploy our applications, and then move on to the next thing.and not become slaves to them, doing manual data entry and updating.

In this lesson, we're going to build a very simple document management system, which anyone in the office can use, thus freeing up your Web staff to work on other projects. We'll be using XML documents to hold our core data - in this case, news articles - in combination with scripting within Active Server Pages to present the content nicely. I use a system not unlike the one we're about to create for running some aspects of our newsroom; you might use it for company newsletters, product examples, or your personal listing of your favorite episodes of "The Transformers". It's completely adaptable.

Letting your content get the most out of the Web (without breaking your back in the process)

When I was mapping our site and features early on, I theorized that to really be a superior competitor we would have to have our information available in a variety of formats (HTML for our public site on the World Wide Web, on mobile devices such as Palm Pilots, PocketPCs, on advanced mobile phones through WAP, on alphanumeric pagers, through push channels using RSS, and so on). I envisioned us having to have our data centralized and single-sourced, so as not to force an author to write one story six separate times, in six different formats.

It was also an interest of mine, as a marketing tactic, to develop a syndication service for our content and have our news content portable, so that our headlines could be implemented easily on other sites external to ours. I was also interested in getting our articles recognized by the major search engines like Google and Excite, as well as by search directories such as Yahoo and Snap.

Database-driven sites that generate querystring-based URLs (i.e., http://www.domain.com/filename.asp?id=8675309) aren't always crawled by search engine and search directory spiders and this results in pages not being indexed with the Web's major search services, which is a negative factor in getting your site recognized and marketed. Thus, I wanted to create a system that would output our stories in individual files that search services would be able to crawl and list more effectively.

Choose your weapons carefully.

OK, so it's not as dramatic as selecting pistols at dawn, but it's important to know the capabilities and limitations of the technologies your application is based upon. I chose XML as the fundamental data technology because of its universality, and the fact that we can take a single document and have it ported to different platforms (our public Web site, our mobile channels, our portable headlines) through the use of a number of written XSL stylesheets (eXtensible Stylesheet Language). The management of the various formats for the document is simple.

I use ASP as the presentation platform because it supports a very simple script construct that lets us display the data in an XML document, according to formatting defined in an XSL stylesheet:

<%
' Load the XML document
Set source = Server.CreateObject("Microsoft.XMLDOM")
source.async = false
source.load(Server.MapPath("an XML filename"))

' Load the XSL stylesheet
Set style = Server.CreateObject("Microsoft.XMLDOM")
style.async = false
style.load(Server.MapPath("an XSL stylesheet"))

' Write out the page contents
Response.Write(source.transformNode(style))
' Destroy all object references
Set source = Nothing
Set style = Nothing
%>

The script instantiates the Microsoft XML Document Object Model (MSXML DOM) twice, once for the XML document containing our story data, and once for the XSL stylesheet we're going to apply to it. The end result will be a file with the extension of .ASP , with the data in the XML document presented as HTML.

ANALYSIS OF FUNCTIONALITY

What this system makes possible is multi-platform publishing. Remember here that they key to make this app work is to make the core asset - the data - the key ingredient, and not limiting ourselves to a single method of presenting that data and likewise not imposing on ourselves the monstrous task of creating separate pages for multiple platforms (in my example, our public Web site, mobile device channel, push channel and external portable service). This makes expansion easier.

If we choose, we can also make this data available to be ported to other partners, who in my situation might be network news providers or local affiliates. They can take the core data in the XML documents and write their own formatting schemes using XSL's transformation language (XSLT) to have the XML data work according to their own system's specifications, and then apply XSL's formatting objects (XSLFO) to have it match their own color schemes and layout etc.

The way this system works is by:

Presenting the user with a simple Web form that they enter the appropriate data into

Passing the data through a processing script that will create an XML document on the fly and save it to the Web server, with customized tags that we'll define (and can easily modify)

Confirming the creation of the XML file and persisting filename information from the XML file to dynamically create an ASP file corresponding to the saved XML document

Creating an ASP Page and saving it to the Web server that will be presented as formatted HTML when viewed in the client's browser. Also check for the existence of errors, to ensure that files with the same name are not written to the Web server's disk, halting execution of the program, and reporting any found errors to the user without catastrophically crashing the program.

Applying formatting to each that we'll define in a series of XSL stylesheets to present our stories nicely in a variety of digital formats (Web, mobile devices, push)

Getting started

Firstly, make sure whichever Web server is hosting your application can support ASP 2.0 or higher. To follow the structure of this example, you should also create a subdirectory on your Web server and name it " xmlnews ", and an additional subdirectory within xmlnews called " images " (to contain all your graphics), such that the paths are as follows:

c:\inetpub\wwwroot\xmlnews\

c:\inetpub\wwwroot\xmlnews\images

Upload or save the images included in the Zip file containing the source code to the images directory. If your Web server is set up differently, you'll just need to change a couple of paths to reflect your own server's directory structure.

Note: this application is based on the default server path mapped by Microsoft Internet Information Server versions 4 and 5, as well as Microsoft Personal Web Server. If you are using a different Web server, or have modified your settings so that the path specified in the scripts is different, you'll need only to modify the server path referenced in CREATE-XML-DOC.ASP and NEW_STORY_TEMPLATE.ASP.

As in any good dynamic Web application, it's best to draw out exactly how we want the end result of our application's work to look. Since we're using XML, we get to define the tags ourselves that will make up our data document. Before being populated with data, the XML document should have the following structure:

<STORIES>
  <STORY>
    <DATE></DATE>
    <TITLE></TITLE>
    <SUBHEAD></SUBHEAD>
    <REPORTER></REPORTER>
    <REPORTERGRAPHIC></REPORTERGRAPHIC>
    <MAILTO></MAILTO>
    <BODY>
      <P1></P1>
      <P2></P2>
      <P3></P3>
      <P4></P4>
      <P5></P5>
      <P6></P6>
      <P7></P7>
      <P8></P8>
      <P9></P9>
      <P10></P10>
    </BODY>
    <GRAPHIC></GRAPHIC>
    <QUOTE></QUOTE>
    <QUOTEDPERSON></QUOTEDPERSON>
    <QUOTEDPERSONTITLE></QUOTEDPERSONTITLE>
  </STORY>
</STORIES>

These are all the elements that I use to populate our stories. If an element is left blank when a user enters information in the Web form, nothing is displayed in the resultant page. If a reporter has no significant quote from someone they interviewed, they just leave this field blank and it doesn't hurt the page.

The nodes DATE , TITLE , SUBHEAD , REPORTER , REPORTERGRAPHIC , MAILTO , BODY , GRAPHIC , QUOTE , QUOTEDPERSON , and QUOTEDPERSONTITLE are direct descendants of the STORY node, which itself falls under the document element STORIES . Since most of our stories are ten paragraphs or less I've written ten child nodes ( P1 , P3 ... P10 ) of the BODY node, which will make up the textual body of the story. Each XML document will contain only a single STORY node, so you have only one story per file.

We then examine the HTML behind it and determine a way in which we can create script code to dynamically perform the work for us. Once this architecture (the look) and the method (the means of programmatically creating the system to carry out the work) are in place, we can build our app.

NEWS-ARTICLE.XSL

Now that we have our data elements (the XML STORY nodes), we build a template using XSL to generate the desired layout with HTML formatting (i.e., functional hyperlinks and inserting an image within the story). Remember that the script that will fire in each ASP page will reference and load this file for styling via the XML Document Object Model (DOM), so this means that if management one day decided to go in a different direction, or we did a redesign of the site, we would need to modify NEWS-ARTICLE.XSL only, and all stories would automatically be retrofitted to reflect this change.

Here's the code for NEWS-ARTICLE.XSL :

<?xml version='1.0'?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">

<xsl:template match="/">

<xsl:for-each select="STORIES/STORY" order-by="DATE"> <HTML> <HEAD> <TITLE> <xsl:value-of select="TITLE"/> </TITLE> </HEAD> <BODY bgcolor="#FFFFFF"> <P> <font face="verdana" size="5" color="teal"> <b><xsl:value-of select="TITLE"/></b> </font> <br/> <font face="verdana" size="2" color="teal"> <b>by <a><xsl:attribute name="href"><xsl:value-of select="MAILTO"/> </xsl:attribute> <xsl:value-of select="REPORTER"/></a>, <xsl:value-of select="DATE"/> </b> </font> <br/> <br/> <font face="verdana" size="3" color="red"> <b><xsl:value-of select="SUBHEAD"/></b> </font> </P> <BLOCKQUOTE> <TABLE cellpadding="2" cellspacing="1" width="87%"> <tr> <td align="left" width="50%"> <img> <xsl:attribute name="src"> <xsl:value-of select="REPORTERGRAPHIC"/> </xsl:attribute> </img> </td> <td align="right" valign="top"> <font face="Arial" color="red" size="3"> <b><xsl:value-of select="QUOTE"/></b> </font> <br/> <font face="Arial" color="black" size="2"> <b><xsl:value-of select="QUOTEDPERSON"/></b> </font> <br/> <font face="arial" color="black" size="1"> <b><xsl:value-of select="QUOTEDPERSONTITLE"/></b> </font> </td> </tr> </TABLE> <font face="verdana" size="2" color="black"> <P align="justify"> <img align="right" hspace="30"> <xsl:attribute name="src"> <xsl:value-of select="GRAPHIC"/> </xsl:attribute> </img> <font size="3"><b><xsl:value-of select="BODY/P1"/></b></font><br/><br/> <font size="2"> <P align="justify"><xsl:value-of select="BODY/P2"/></P> <P align="justify"><xsl:value-of select="BODY/P3"/></P> <P align="justify"><xsl:value-of select="BODY/P4"/></P> <P align="justify"><xsl:value-of select="BODY/P5"/></P> <P align="justify"><xsl:value-of select="BODY/P6"/></P> <P align="justify"><xsl:value-of select="BODY/P7"/></P> <P align="justify"><xsl:value-of select="BODY/P8"/></P> <P align="justify"><xsl:value-of select="BODY/P9"/></P> <P align="justify"><xsl:value-of select="BODY/P10"/></P> </font> </P> </font> </BLOCKQUOTE> <hr size="1" color="salmon"/> </BODY> </HTML> </xsl:for-each> </xsl:template> </xsl:stylesheet>

Take note of how I'm using the XSL statement <xsl:value-of/> to insert the data from the XML document, and how I create a hyperlink for the reporter's e-mail address using the <xsl:attribute/>, with this codeblock:

<a>
  <xsl:attribute name="href">
    <xsl:value-of select="MAILTO"/>
    </xsl:attribute>
  <xsl:value-of select="REPORTER"/>
</a>

And also how I insert an image in two different places in the story (I get asked how to do this one all the time), in this block:

<img>
  <xsl:attribute name="src">	
    <xsl:value-of select="REPORTERGRAPHIC"/>
  </xsl:attribute>
</img>

NEWS-ARTICLE.XSL acts as a placeholder presenting the data with defined formatting in HTML when data from XML documents are loaded into it.

FORM.ASP

By all accounts, this is a normal Web form. The FormatDateTime function formats the date into the required format, and inserts it into the Date textbox on form.asp . This value is later inserted into the DATE node when the form is submitted:

<%=FormatDateTime(Date(),1)%>

Other than that, there's nothing really out of the ordinary going on here. Basic form fields are the order of the day, and the form uses the POST method to pass the data onto the CREATE-XML-DOC.ASP page for processing. The NAME attributes of each form field are used as the basis of our construction of child nodes in our XML document in the next step.

Here's the code for FORM.ASP:

<html>
<head>
 <title>
  Publish a new story
 </title>
</head>
<body bgcolor="#c0c0c0">
 <form action="create-xml-doc.asp" method="post">
  <h3 align=center><FONT face=Tahoma><U><FONT size=5>Enter your story information</FONT></U>   
</FONT></h3><FONT face=Tahoma><FONT size=2><STRONG>
  Title: <input name="TITLE" width="65" style="WIDTH: 320px; HEIGHT: 22px"><br>
  Subhead: <input name="SUBHEAD" width="65" style="WIDTH: 320px; HEIGHT: 22px"><br>
  Reporter: <select size="1" name="REPORTER">
    <option value="Sabrina Salas">Bri</option>
    <option value="Shawn Gumataotao">Shawn</option>
    <option value="Mindy Fothergill">Mindy</option>
    <option value="Yanna Person">Yanna</option>
    <option value="Jay Pascua">Jay</option>
    <option value="Rachel Taimanao">Rachel</option>
    <option value="Jason Salas">Jason</option>
  </select><br>
  E-mail address: 
  <select size="1" name="MAILTO">
  <option value="mailto:sabrina@kuam.com">sabrina@kuam.com</option>
  <option value="mailto:shawn@kuam.com">shawn@kuam.com</option>
  <option value="mailto:mindy@kuam.com">mindy@kuam.com</option>
  <option value="mailto:yanna@kuam.com">yanna@kuam.com</option>
  <option value="mailto:jay@kuam.com">jay@kuam.com</option>
  <option value="mailto:rachel@kuam.com">rachel@kuam.com</option>
  <option value="mailto:jason@kuam.com">jason@kuam.com</option>
  </select><br>
  Reporter Graphic:
  <select size="1" name="REPORTERGRAPHIC">
  <option value="images/sabrina.jpg">Bri</option>
  <option value="images/shawn.jpg">Shawn</option>
  <option value="images/mindy.jpg">Mindy</option>
  <option value="images/yanna.jpg">Yanna</option>
  <option value="images/jay.jpg">Jay</option>
  <option value="images/rachel.jpg">Rachel</option>
  <option value="images/jason2.jpg">Jas</option>
  </select><br>
  Date: <input width="65" name="DATE" value="<%=FormatDateTime(Date(),1)%>"& -
  style="WIDTH: 215px; HEIGHT: 25px"><br>
<hr width="85%" color="black">
<P><h3 align=center><u><FONT size=5>Enter 
your story's body</FONT>   </u></h3>
<P></P>Paragraph 1: <TEXTAREA style="WIDTH: 648px; HEIGHT: 38px" name=P1 cols=68></TEXTAREA><br>
  Paragraph 2: <TEXTAREA style="WIDTH: 648px; HEIGHT: 38px" name=P2 cols=48></TEXTAREA><br>
  Paragraph 3: <TEXTAREA style="WIDTH: 648px; HEIGHT: 38px" name=P3 cols=48></TEXTAREA><br>
  Paragraph 4: <TEXTAREA style="WIDTH: 648px; HEIGHT: 38px" name=P4 cols=48></TEXTAREA><br>
  Paragraph 5: <TEXTAREA style="WIDTH: 648px; HEIGHT: 38px" name=P5 cols=48></TEXTAREA><br>
  Paragraph 6: <TEXTAREA style="WIDTH: 648px; HEIGHT: 38px" name=P6 cols=48></TEXTAREA><br>
  Paragraph 7: <TEXTAREA style="WIDTH: 648px; HEIGHT: 38px" name=P7 cols=48></TEXTAREA><br>
  Paragraph 8: <TEXTAREA style="WIDTH: 648px; HEIGHT: 38px" name=P8 cols=48></TEXTAREA><br>
  Paragraph 9: <TEXTAREA style="WIDTH: 648px; HEIGHT: 38px" name=P9 cols=48></TEXTAREA><br>
  Paragraph 10: <TEXTAREA style="WIDTH: 648px; HEIGHT: 38px" name=P10 cols=48></TEXTAREA><br>
<hr width="85%" color="black">  
  URL for story graphic: <input name="GRAPHIC" style="WIDTH: 434px; & -
  HEIGHT: 22px" size=19 value="http://www.kuam.com/images/news8_images/primetime.jpg"><br>
  Quote: <input name="QUOTE" style="WIDTH: 450px; HEIGHT: 22px"><br>
  Person being quoted: <input name="QUOTEDPERSON" style="WIDTH: 450px; HEIGHT: 22px"><br>
  Title of person being quoted: <input name="QUOTEDPERSONTITLE" style="WIDTH: 450px; HEIGHT: 22px"><br>
  </STRONG></FONT></FONT>
<hr width="85%" color="black">
&nbsp;
      <input id="FILENAME" name="FILENAME"><BR><STRONG><FONT 
size=2>Filename for your XML file:<br>
  <input type="submit" id="btnSub" name="btnSub" value="Submit"></FONT></STRONG><br></FONT>
 </form>
</body>
</html>

CREATE-XML-DOC.ASP

This Active Server Page contains only script code that is used to build our XML documents, through the use of the Microsoft XML Document Object Model (MSXML DOM). It defines the structure of the XML document we planned out earlier. After declaring variables, it creates the root element of the XML document and named it STORIES by using the XML DOM createElement method. We then iterate through the document and create children of STORY , using the XML DOM appendChild method. Pay special attention to how the structure of the XML is defined by tacking specific child nodes onto their parents. The P1 through P10 nodes all are appended to the BODY node, as we defined above, with all other nodes falling under STORY .

In each node, we also call upon the .Text property of each node to populate it with data, which is retrieved from the Request.Form collection of FORM.ASP .

Now that the document has been created and filled with its data, we insert an XML processing instruction, which appears at the top of the document, to distinguish that this is in fact, an XML document. We then save the file to the Web server using the DOM's save content model, again using the value of the variable strFileName , which was retrieved from FORM.ASP .

' Create the XML processing instruction to tell the browser this is an XML document

Set objPI = objDom.createProcessingInstruction("xml", "version='1.0'")

objDom.insertBefore objPI, objDom.childNodes(0)

objDom.save "c:\inetpub\wwwroot\xmlnews\" & strFileName & ".xml"

Lastly, we call use the Response.Redirect method automatically advanced to QUERYSTRING.ASP and move to the next step in the process. We also insert a querystring value into the URL, the value of strFileName . This persists the value of the variable, as it will be extracted in the next step.

Response.Redirect ("querystring.asp?filename=" & strFileName)

At this point in the process, we've just created an XML document and populated it with data from the Web form. Next we'll create our ASP files dynamically. But first, here's the source code for CREATE-XML-DOC.ASP :>

<% @ Language = VBScript %>

<%
Dim objDom, objRoot, objChild1, objChild2, objChild3, objChild4, objPI
Dim strFileName, objChild5, objChild6, objChild7, objChild8, objChild9
Dim objChild10, objChild11, objChild12, objChild13, objChild14 
Dim objChildMailto, objChildSubHead, objChildStory, objChildQuote 
Dim objChildQuotedPerson, objChildQuotedPersonTitle, objChildGraphic 
Dim objChildReporterGraphic 
  strFileName = Request.Form("FILENAME")

  ' CREATE AN XML DOCUMENT

  ' Create the root element
  Set objDom = Server.CreateObject("Microsoft.XMLDOM")
  Set objRoot = objDom.createElement("STORIES")
  objDom.appendChild objRoot

  ' Create a 1st-level child element
  Set objChildStory = objDom.createElement("STORY")
  objRoot.appendChild objChildStory

  ' Create 1st-level child elements under the STORY element
  Set objChild2 = objDom.createElement("DATE")
  objChildStory.appendChild objChild2
  objChild2.Text = Request.Form("DATE")
  
  Set objChild1 = objDom.createElement("TITLE")
  objChildStory.appendChild objChild1
  objChild1.Text = Request.Form("TITLE")
  
  Set objChildSubHead = objDom.createElement("SUBHEAD")
  objChildStory.appendChild objChildSubHead
  objChildSubHead.Text = Request.Form("SUBHEAD")
  
  Set objChild3 = objDom.createElement("REPORTER")
  objChildStory.appendChild objChild3
  objChild3.Text = Request.Form("REPORTER")
  
  Set objChildReporterGraphic = objDom.createElement("REPORTERGRAPHIC")
  objChildStory.appendChild objChildReporterGraphic
  objChildReporterGraphic.Text = Request.Form("REPORTERGRAPHIC")
  
  Set objChildMailto = objDom.createElement("MAILTO")
  objChildStory.appendChild objChildMailto
  objChildMailto.Text = Request.Form("MAILTO")
  
  Set objChild4 = objDom.createElement("BODY")
  objChildStory.appendChild objChild4
  objChild4.Text = Request.Form("BODY")
  
  Set objChildGraphic = objDom.createElement("GRAPHIC")
  objChildStory.appendChild objChildGraphic
  objChildGraphic.Text = Request.Form("GRAPHIC")
  
  Set objChildQuote = objDom.createElement("QUOTE")
  objChildStory.appendChild objChildQuote
  objChildQuote.Text = Request.Form("QUOTE")
  
  Set objChildQuotedPerson = objDom.createElement("QUOTEDPERSON")
  objChildStory.appendChild objChildQuotedPerson
  objChildQuotedPerson.Text = Request.Form("QUOTEDPERSON")
  
  Set objChildQuotedPersonTitle = objDom.createElement("QUOTEDPERSONTITLE")
  objChildStory.appendChild objChildQuotedPersonTitle 
  objChildQuotedPersonTitle.Text = Request.Form("QUOTEDPERSONTITLE")
  

  ' The P1, P2, P3....PNth child elements fall under the 
  ' STORY/BODY element to hold story paragraphs individually
  Set objChild5 = objDom.createElement("P1")
  objChild4.appendChild objChild5
  objChild5.Text = Request.Form("P1")
  
  Set objChild6 = objDom.createElement("P2")
  objChild4.appendChild objChild6
  objChild6.Text = Request.Form("P2")
  
  Set objChild7 = objDom.createElement("P3")
  objChild4.appendChild objChild7
  objChild7.Text = Request.Form("P3")
  
  Set objChild8 = objDom.createElement("P4")
  objChild4.appendChild objChild8
  objChild8.Text = Request.Form("P4")
  
  Set objChild9 = objDom.createElement("P5")
  objChild4.appendChild objChild9
  objChild9.Text = Request.Form("P5")
  
  Set objChild10 = objDom.createElement("P6")
  objChild4.appendChild objChild10
  objChild10.Text = Request.Form("P6")
  
  Set objChild11 = objDom.createElement("P7")
  objChild4.appendChild objChild11
  objChild11.Text = Request.Form("P7")
 
  Set objChild12 = objDom.createElement("P8")
  objChild4.appendChild objChild12
  objChild12.Text = Request.Form("P8")
  
  Set objChild13 = objDom.createElement("P9")
  objChild4.appendChild objChild13
  objChild13.Text = Request.Form("P9")
  
  Set objChild14 = objDom.createElement("P10")
  objChild4.appendChild objChild14
  objChild14.Text = Request.Form("P10")
  
  
  ' Create the XML processing instruction
  Set objPI = objDom.createProcessingInstruction("xml", "version='1.0'")
  
  objDom.insertBefore objPI, objDom.childNodes(0)
  
  objDom.save "c:\inetpub\wwwroot\xmlnews\" & strFileName & ".xml"
  
  ' Destroy all instantiated object referneces
  Set objDom = nothing
  Set objChild1 = nothing
  Set objChildStory = nothing
  Set objSubhead = nothing
  Set objChild2 = nothing
  Set objChild3 = nothing
  Set objChildReporterGraphic = nothing
  Set objChildMailto = nothing
  Set objChild4 = nothing
  Set objChildGraphic = nothing
  Set objChildQuote = nothing
  Set objChildQuotedPerson = nothing
  Set objChildQuotedPersonTitle = nothing
  Set objChild5 = nothing
  Set objChild6 = nothing
  Set objChild7 = nothing
  Set objChild8 = nothing
  Set objChild9 = nothing
  Set objChild10 = nothing
  Set objChild11 = nothing
  Set objChild12 = nothing
  Set objChild13 = nothing
  Set objChild14 = nothing
  Set objPI = nothing
  
  Response.Redirect ("querystring.asp?filename=" & strFileName)
%>

QUERYSTRING.ASP

All this short script does is confirm to the user that the XML document has been created, and passes the user along to the page containing the script which will generate the ASP file, when the user clicks on the hyperlink.

We collect the variable strFileName with the Request.QueryString collection from the URL of CREATE-XML-DOC.ASP and regenerate this value by passing it along again in the URL, which we'll extract in the next page, NEW_STORY_TEMPLATE.ASP .

This is an ad hoc method of persisting variables, without the burden of cookies or complex session management.

<% @ Language = VBScript %>

  <%
    Dim strFileName
    strFileName = Request.QueryString("filename")

    Response.Write "<font face=tahoma size 2><b>Your story has been & -
	successfully created as an XML document.<br><br>&q

Response.Write "<a href=new_story_template.asp?filename=" & strFileName & - ">Click here</a> to finish the process and create your story for our public Web site.</font>" %>

NEW_STORY_TEMPLATE.ASP

This is it - the last step towards automated bliss! What we're doing here is quite simple - we're writing out the ASP script we described earlier, and extracting the value of filename from the URL querystring. We do this in a subroutine so the code will not be executed immediately, until it is formally called at the bottom of the page. All this happens in a matter of milliseconds, but it's an example of good, disciplined code writing you should get in the habit of practicing. While the code may be lengthy, it's really very easy to follow.

<% @ Language = VBScript %>
  <%
    Sub CreateNewASP
    
    On Error Resume Next
    
    strFileName = Request.QueryString("filename")
    Set FSO = CreateObject("Scripting.FileSystemObject")
    Set newStory = FSO.CreateTextFile("c:\inetpub\wwwroot\xmlnews\" & strFileName & ".asp", False)
      newStory.Write("<!-- XML content starts here -->")
      newStory.Write(vbcrlf & "<%" & vbcrlf)
      newStory.Write("' Load the XML document")
      newStory.Write(vbcrlf & "Set source = Server.CreateObject(")
      newStory.Write(Chr(34) & "Microsoft.XMLDOM")
      newStory.Write(Chr(34) & ")")
      newStory.Write(vbcrlf & "source.async = false")
      newStory.Write(vbcrlf & "source.load(Server.MapPath(")
      newStory.Write(Chr(34) & strFileName)
      newStory.Write(".xml")
      newStory.Write(Chr(34) & ")")
      newStory.Write(")")
      newStory.Write(vbcrlf & vbcrlf)
      newStory.Write("' Load the XSL stylesheet")
      newStory.Write(vbcrlf & "Set style = Server.CreateObject(")
      newStory.Write(Chr(34) & "Microsoft.XMLDOM")
      newStory.Write(Chr(34) & ")")
      newStory.Write(vbcrlf & "style.async = false")
      newStory.Write(vbcrlf & "style.load(Server.MapPath(")
      newStory.Write(Chr(34) & "news-article.xsl")
      newStory.Write(Chr(34) & ")")
      newStory.Write(")")
      newStory.Write(vbcrlf & vbcrlf)
      newStory.Write("' Write out the page contents")
      newStory.Write(vbcrlf & "Response.Write(source.transformNode(style))")
      newStory.Write(vbcrlf & "%" & ">")
      newStory.Write(vbcrlf & "' Destroy all object references")
      newStory.Write(vbcrlf & "Set source = nothing")
      newStory.Write(vbcrlf & "Set style = nothing")
      newStory.Write(vbcrlf & "<!-- XML content ends here -->")
      newStory.Close
      

      If Err.Number > 0 Then
        Response.Write("<font face=tahoma size=3>Your story has <b>NOT</b> been & -
		created!<br>A file with the name <b>" & Chr(34) & strFileName & Chr(34) & -
		"</b> already exists.<br><br>  <a href=javascript:history.go(-2)>Go & -
		back</a> and create it again!</font>") 
        Err.Clear
      Else
        Response.Write("<font face=tahoma size=3><b>Your story was successfully published!</b></font>")
      End If
      
      ' Destroy the instantiated object's reference
      Set FSO = nothing
      
    End Sub
  %>

  <%  Call CreateNewASP  %>

By using VBScript's Write method on the FSO object we declared, we include all of the syntax for our script as a string. Note how we escape in and out of HTML by use of the VBScript concatenation operator ("&"), and use VBScript's special characters (i.e., Chr(34) for double-quotes) and liberal uses of Visual Basic's vbcrlf function to insert line breaks within the code so it all comes out nice in the finished product. Failing to include line breaks would produce the script all on a single line.

This script encapsulates your XML-generated content within HTML comment tags, which you can see are written to the page within the script. So when a user browses to your ASP file, all of the content entered through the Web form will be marked nicely with start and end points in the HTML source code:

<html><body>

... page information ... <!-- XML content starts here --> ... your content ... <!-- XML content ends here --> ... more page information ... </body></html>

To make life simpler, I decided to double-up on the amount of protection on filenames being created. If this was to be a truly distributed application with more than one user logging on and trying to create stories, at some point two or more people might attempt to write files with the same name at the same time. So, within the script block I include the " False " parameter on the CreateTextFile method to programmatically rule out files being overwritten should the data passed through the form with the same filename. This syntactically prevents the dangerous scenario of file being erased from ever occurring. Optionally, if you use this system for less frequent applications than daily news, you could change the parameter to " True ", or just leave it out altogether, and files with the same name swill just be overwritten without warning.

I couple this with the err or-trapping statement On Error Resume Next to create a customized error message to report to the user that an error has occurred, later down the page. Our End...If statement prints a conditional message to the browser, that lets the user know whether the ASP file was created...or not. This ensures that the error is stated while not crashing the entire program. It's an example of better management of your Web applications.

Lastly, we call our subroutine and execute our script:

<% Call CreateNewASP %>

What results is that a new text file gets written to the server in our application's directory ( C:\inetpub\wwwroot\xmlnews\ ), with the filename inserted automatically from the variable strFileName , which was the sole value extracted from the Request.Querystring collection and the file extension of ".ASP":

Set newStory = FSO.CreateTextFile("c:\inetpub\wwwroot\xmlnews\" & strFileName & ".asp", False)

We used the POST method to transmit the form data into the HTTP header information of NEW_STORY_TEMPLATE.ASP , and tweaked the additional parameter of hard-coding into the querystring the filename value from QUERYSTRING.ASP . Sneaky!

Because this is an internal app I personally am fanatical about seeing what's going on within the script, and what values and parameters are being passed from page-to-page. Alternatively, you could have accomplished the same thing (passing the value of strFileName ). This would prevent anyone from knowing the string which was entered by the user at the onset in FORM.ASP by using hidden values within the ASP pages and passing them on between pages in the app, extracting them as necessary. For example, the following will also work:

<input type="hidden" value="<%=Request("strFileName")%>">

The script also takes the value of strFileName and inserts it into the path to the XML document within the script, and then tacks on the file extension of " .XML ". This creates an association to the XML document that was created by CREATE-XML-DOC.ASP :

newStory.Write(vbcrlf & "source.load(Server.MapPath(")
newStory.Write(Chr(34) & strFileName)
newStory.Write(".xml")
newStory.Write(Chr(34) & ")")

The output would then literally read:

source.load(Server.MapPath("strFileName.xml")

.and thus would create an Active Server Page, in which the content consists of the data contained in the XML document, rendered by the formatting instructions within the XSL stylesheet. You now have a one-to-one relationship for as many documents as you create, with one XML file corresponding to one ASP file.

Now that you have the back-end architecture for your system built, you should play with it by browsing to http://localhost/xmlnews and create a bunch of new files, viewing them in your browser. Mess around with the XSL stylesheet and develop a new presentation format

Summing it all up: ".but couldn't I just do this in HTML???"

Congratulations! You've successfully built a functional document generation system that takes in data inputted into a Web form and spits out XML documents, which can be used for a number of applications. If you want to play around and expand on this concept, you can build a new XSL stylesheet and have a script bind to that one (for a mobile version of your site, for instance).

If I want to increase the number of ways people can access our information, I just create new XSL stylesheets. A good practical example is providing users with the popular "Print This Article" service that most news-oriented sites make available. I would just write a simple XSL stylesheet that displayed the same article content from the XML document without graphics, and a fancy layout, all tucked nicely within a table with a maximum width of 450 pixels, so it would print on most major printer models. I then create a new ASP file that binds to that XSL stylesheet, and I've got it!

Using XML in this fashion also helps for other developers, if they want to use our news headlines on their own homepages as syndicated they just simply build their own stylesheet(s) using XSL and import the data - the headlines only - with my site still getting the eventual page visit if a user clicks on the link. Thus, I extend the breadth of my market reach and still manage to maintain my traffic levels, retaining my advertising revenue.

The question I most often get asked when describing to Web developers the benefits of employing XML into their Web projects is "Couldn't I just have done this in HTML?" It's also the question I always wind up asking myself at the end of the day. Yes, you very well could have just created individual HTML files, but you can do so much more with much less work than if you had published individual static HTML files for each type of document you wanted. But it likely would not have been as easy. And for our second and third objectives of this lesson, Make Web publishing for multi-platform devices possible, and Make content syndication possible, this would be a more efficient way in the long run.

And that's what you should aim for: long-term success with your Web projects, whether it function as a marketing tool to entice users to buy a product off of your public Web site, or serve its purpose as an internal LAN or intranet application, creating documents for internal corporate use.

As in most things on the Web, there's no predefined template for building the perfect Web application.it's all up to the individual and what's best for his or her organization.

 
 
   
  RATE THIS ARTICLE
  Please rate this article (1-5). Was this article...
 
 
Useful? No Yes, Very
 
Innovative? No Yes, Very
 
Informative? No Yes, Very
 
Brief Reader Comments?
Your Name:
(Optional)
 
  USEFUL LINKS
  Related Tasks:
 
 
   
 
 
       
  Search the ASPToday Living Book   ASPToday Living Book
 
  Index Full Text Advanced 
 
 
       
  Index Entries in this Article
 
  • appendChild method
  •  
  • concatenation operator
  •  
  • content management
  •  
  • createElement method
  •  
  • CreateTextFile method
  •  
  • DOM
  •  
  • ease of use
  •  
  • FileSystemObject object
  •  
  • Form collection
  •  
  • formatting
  •  
  • hidden variables
  •  
  • hyperlinks
  •  
  • load method
  •  
  • multi-platform publishing
  •  
  • name of field
  •  
  • news application
  •  
  • online content management
  •  
  • POST method
  •  
  • publishing an article
  •  
  • QueryString collection
  •  
  • Redirect method
  •  
  • Request object
  •  
  • Response object
  •  
  • Save method
  •  
  • search engines
  •  
  • TextFile object
  •  
  • using
  •  
  • using variety of formats
  •  
  • vbcrlf function
  •  
  • VBScript
  •  
  • Visual Basic
  •  
  • web forms
  •  
  • web publishing
  •  
  • Write method
  •  
  • XML documents
  •  
  • XML DOM
  •  
  • XSL stylesheets
  •  
  • xsl:attribute element
  •  
  • xsl:value-of element
  •  
     
     
    HOME | SITE MAP | INDEX | SEARCH | REFERENCE | FEEDBACK | ADVERTISE | SUBSCRIBE
    .NET Framework Components Data Access DNA 2000 E-commerce Performance
    Security Admin Site Design Scripting XML/Data Transfer Other Technologies

     
    ASPToday is brought to you by Wrox Press (http://www.wrox.com/). Please see our terms and conditions and privacy policy.
    ASPToday is optimised for Microsoft Internet Explorer 5 browsers.
    Please report any website problems to webmaster@asptoday.com. Copyright © 2001 Wrox Press. All Rights Reserved.