|
APGen Developer's Guide |
|
See Also: |
XML (Extensible Markup Language) is a critical standard for web content. APGen can be used to generate XML documents as easily as it can be used to generate HTML documents.
APGen is valuable for generating XML content from any data source. Many data sources do not return content in XML format - APG scripts can be written to access these data sources (via COM) and format the content in any desired XML schema.
XSLT (Extensible Stylesheet Language Transformations) is the standard XML-based language for transforming one class of XML document to another. While XSLT is often the best choice for XML transformation, Active Server Pages programmers may find APG scripts easier to use for generating web documents. APGen provides the best of both worlds and ultimate flexibility:
Generating XML in APG scripts is straightforward. These two pointers should help:
<%# @LANGUAGE="VBScript" #%>
<%#
Output.Filename = "quotes.xml"
...
#%>
<?xml version="1.0"
encoding="UTF-8"?>
<quotes>
...
</quotes>
<?xml >
directive. By changing it to:
<%# @LANGUAGE="VBScript" #%>
<%#
Output.Filename = "quotes.xml"
...
#%><?xml version="1.0"
encoding="UTF-8"?>
<quotes>
...
</quotes>
Util.XMLEncode() to encode content
that is not placed in <![CDATA[ ... ]]> blocks.
This will ensure that programmable content will not
prevent the XML document from being well-formed:
<%# @LANGUAGE="VBScript" #%>
<%#
Output.Filename = "quotes.xml"
Dim sQuote, sAuthor
sQuote = "My mother said to me, ""If you become a soldier " & _
"you'll be a general; if you become a monk you'll end " & _
"up as the pope."" Instead, I became a painter and wound " & _
"up as Picasso."
sAuthor = "Pablo Picasso"
#%><?xml version="1.0" encoding="UTF-8"?>
<quotes>
<quote
author="<%# =Util.XMLEncode(sAuthor) #%>"
><%# =Util.XMLEncode(sQuote) #%></quote>
</quotes>
To apply XSLT transforms to generated XML, you'll want to turn output buffering on:
Output.Buffer = True
Then, after the XML document is generated, the buffered output can
be retrieved and replaced using the
Output.BufferContents
property. An XSL transform can be applied to the buffered output:
<%#
' Buffer output
Output.Buffer = True
' Generate XML content
#%><?xml version="1.0"?>
<body>
. . .
</body>
<%#
' Load the buffered output into an XML object
Dim oXML
Set oXML = Script.CreateObject("Microsoft.XMLDOM")
If Not oXML.loadXML(Output.BufferContents) Then
Log.Write "Error loading XML", apgSeverityFatal
Script.Abort
End If
' Load an XSL stylesheet
Dim oXSL
Set oXSL = Script.CreateObject("Microsoft.XMLDOM")
If Not oXSL.load(Script.Dir & "transform.xsl") Then
Log.Write "Error loading XSL", apgSeverityFatal
Script.Abort
End If
'
Overwrite the output buffer with the transformed
content
Output.BufferContents = oXML.transformNode(oXSL)
' This flushes the buffer to the
file, then closes the file
Output.Close()
#%>
This example shows how to execute APG scripts and use XSLT to transform output to target different browsers or user devices. In this example each document generates output for uplevel browsers, downlevel browsers, and WAP clients. Familiarity with XML and XSLT is assumed, and we do not show the XML or XSLT documents used. This is a generic system for targeting different browsers and devices.
Page content and page-specific logic are separated from device presentation details, which makes web site development and maintenance easier. Performance is excellent because the page content is not generated for every request, and the device-specific transform is not performed for every request. By generating static pages only when page data changes, performance is outstanding.
APG scripts contain the content and page-specific logic for each web page. The APG scripts generate XML in a "generic" schema that is independent of browser or device details. Each XSLT transform corresponds to the display rules for different device types - the XSLT is responsible for transforming the generic schema to a browser or device-specific schema. Only one XSLT page needs to be developed for each targeted device - the same XSLT transform is applied to each APG script in the site. This generic schema and the device-specific XSLT transforms are out of the scope of this example - they are not shown.
In this example, an array lists the APG scripts to execute, and an array lists the XSLT transforms to apply to the output of each APG script. Each of the APG scripts is executed, the script's output is loaded into an XMLDOM, then all the XSLT transforms are applied to the XMLDOM.
An array of filename extensions is used to compute the
filename of each output combination. For example, the downlevel version of
the output of contents.apg is named contents_dnl.htm. The uplevel version of the
same document is named contents_upl.htm, and the WAP version is named
contents.wml.
<%# @LANGUAGE="VBScript" #%>
<%# Option Explicit #%>
<%#
'------------------------------------------------------
' MultiBrowser.apg
'
' Description: Executes some APG scripts, which generate
' XML content. This XML content is transformed using
' several XSLT transforms. Each XSLT transform corresponds
' to the display rules for different device types.
'
' For example: downlevel.xsl produces output for downlevel
' browsers. When downlevel.xsl is applied to the output
' from contents.apg, the result is contents_dnl.htm.
'
' Copyright (c) 1999-2001 WebGecko Software
'------------------------------------------------------
' List the APG scripts to execute
' Each of these generates XML
Dim rgScripts
rgScripts =
Array("default.apg", _
"contents.apg")
' List the XSLT transforms to apply, plus the output file
' extensions to use
Const nXSLTs = 3 ' The number of XSLTs
Dim rgXSLTs() ' Array of info about the XSLTs
ReDim rgXSLTs(nXSLTs-1, 1)
' Targets uplevel browsers (IE 4.0+, Netscape 6+)
rgXSLTs(0,0) = "uplevel.xsl"
rgXSLTs(0,1) = "_upl.htm" ' Uplevel pages end w/ this extension
' Targets downlevel web browsers
rgXSLTs(1,0) = "downlevel.xsl"
rgXSLTs(1,1) = "_dnl.htm" ' Downlevel pages end w/ this extension
' Targets WAP browsers
rgXSLTs(2,0) = "wap.xsl"
rgXSLTs(2,1) = ".wml" ' WAP pages end w/ this extension
' Create an APGen object, and set global settings
Dim oAPGen
Set oAPGen = Script.CreateObject("APGen")
' Place output here
oAPGen.OutputDir = Script.Dir & "output"
' Buffer output for all pages
oAPGen.BufferOutput = True
' Load the XSLT documents
Dim rgXSLTDOMs() ' Array of XSLT DOMs
ReDim rgXSLTDOMs(nXSLTs-1)
Dim i, oXSL, sXSLTFilename
For i = 0 To nXSLTs-1
' The name of the XSL file
sXSLTFilename = rgXSLTs(i, 0)
' Load a new XMLDOM
Set oXSL =
Script.CreateObject("Microsoft.XMLDOM")
If Not oXSL.load(Script.Dir & sXSLTFilename) Then
Err.Raise vbObjectError, "Multibrowser2.apg", "Error loading XSL doc " & sXSLTFilename
End If
' Store it in rgXSLTDOMs
Set rgXSLTDOMs(i) = oXSL
Next
' Execute the APG scripts
Dim sAPGScript
For Each sAPGScript In rgScripts
' Open the APG script
Dim oScript
Set oScript =
oAPGen.OpenScript(sAPGScript)
' Run it
oScript.Run
' Load an XML document from the APG script's output
Dim oXML
Set oXML =
Script.CreateObject("Microsoft.XMLDOM")
If Not oXML.loadXML(oScript.Output.BufferContents) Then
Err.Raise vbObjectError, "Multibrowser2.apg", _
"Error loading XML from the output of " & sAPGScript
End If
oScript.Output.ClearBuffer()
' Loop through the XSLTs, applying each one to the XML
For i = 0 To nXSLTs-1
Dim sExt ' The extension of the output file
Dim sFilename ' The name of the output file
sExt =
rgXSLTs(i,1)
' Compute the output filename
sFilename =
Left(sAPGScript, InStr(1, sAPGScript, ".")-1) & sExt
' Set the output filename
oScript.Output.Filename = sFilename
' Obtain the XSL DOM for this stylesheet
Set oXSL =
rgXSLTDOMs(i)
' Transform the XML document with it
oScript.Output.BufferContents = oXML.transformNode(oXSL)
' Flush buffered content to the output file, then close the file
oScript.Output.Close()
Next
Next ' For Each sAPGScript
#%>