Set xmldoc = Server.CreateObject("Msxml2.FreeThreadedDOMDocument.3.0")
xmldoc.async = false
xmldoc.load(Server.mapPath("TestDoc.xml"))
Set xsldoc = Server.CreateObject("Msxml2.FreeThreadedDOMDocument.3.0")
xsldoc.async = false
xsldoc.load(Server.mapPath("DocTransform.xsl"))
Set template=Server.CreateObject("MSXML2.XSLTemplate")
template.stylesheet=xsldoc
Set processor=template.createProcessor
processor.input = xmldoc
strVal = Request.querystring("acctid")
if strVal <> "" then
processor.addParameter "acctid", strVal
end if
processor.transform()
Response.write (processor.output)
But then I
realized I could probably throw together a VB app to do this, put in some Common
Dialogs for opening and saving the files, and get a lot more functionality out
of it. "Pete's Nifty XSL Transform Tester" is the result. Not only
can you load and save your XML and XSL files, you can pass in an optional parameter
name and value, and you can make minor edits and, using a right-click context
menu, you can save the revised file back to the filesystem. It also uses the
parseError properties and methods to give detailed error messages. Let's take
a look at this simple but extremely useful project and how it works:

Looking
at the screen shot above, you see we have a rich text box for the XML,
one on the right for the XSL, and a big one on the bottom to view the
Transform output. Over on the left we have a "Load XML" button,
one to "Load XSL", a checkbox for "HTML output" (as
opposed to text output - I'll get to that neat trick in a moment), and
finally, a "PROCESS" button to fire off the transform and display
the result. We also have two small textboxes to enter a parameter name
and value.
The neat thing
about the bottom textbox is that its actually two controls, one sitting right
on top of the other. One is a regular text box with its multiline property set
to True - so we can look at the results of <xsl:output
method="text"/> template directives. The second one is a WebBrowser
control - exactly the same size and layout. In this manner, when we test for
the "HTML Output" checkbox control and it's checked, we simply set
the visible property of the textbox to false, the WebBrowser control to true,
and write our output to the WebBrowser control. When the "HTML Output"
checkbox is empty, we set the visible property of the textbox control to true
and write our output there. Pretty cool, eh?
Now, let's
step through the code:
Option Explicit
Private m_hMenu As Long
Public sContent As String
Private Sub Form_Load()
m_hMenu = CreatePopupMenu()
Call mnuAddItem(m_hMenu, 100, , "Save File")
End Sub
Private Function OpenFile(sFileName) As String
If Len(sFileName) = 0 Then Exit Function
Dim fs As New Scripting.FileSystemObject
Dim f As Scripting.TextStream
Set f = fs.OpenTextFile(sFileName, ForReading, False)
OpenFile = f.ReadAll
f.Close
Set f = Nothing
End Function
Private Sub SaveTheFile(sControl As String)
If sControl = "txtXML" Then
dlg.Filter = "XML Files (*.xml)|*.xml"
sContent = txtXML.Text
dlg.ShowSave
WriteFile dlg.FileName, sContent
Else
dlg.Filter = "XSL Files (*.xsl)|*.xsl"
sContent = txtXSL.Text
dlg.ShowSave
WriteFile dlg.FileName, sContent
End If
End Sub
Private Sub WriteFile(sFileNameAndPath As String, sContent As String)
Dim fs As New Scripting.FileSystemObject
Dim f As Scripting.TextStream
If Not sFileNameAndPath = "" Then
Set f = fs.OpenTextFile(sFileNameAndPath, ForWriting, True, TristateUseDefault)
f.Write sContent
f.Close
MsgBox "File " & sFileNameAndPath & " Saved."
End If
End Sub
Private Sub cmdLoadXML_Click()
dlg.Filter = "XML Files (*.xml)|*.xml"
dlg.ShowOpen
txtXML.Text = OpenFile(dlg.FileName)
End Sub
Private Sub cmdLoadXSL_Click()
dlg.Filter = "XSL Files (*.xsl)|*.xsl"
dlg.ShowOpen
txtXSL.Text = OpenFile(dlg.FileName)
End Sub
Private Sub cmdProcess_Click()
Dim strParamVal As String
Dim strParamName As String
Dim myDoc As Object
Dim xmlDoc As New FreeThreadedDOMDocument30
Dim xslDoc As New FreeThreadedDOMDocument30
Dim template As New MSXML2.XSLTemplate30
Dim processor As MSXML2.IXSLProcessor
If (txtXML.Text <> "" And txtXSL.Text <> "") Then
xslDoc.validateOnParse = True
xmlDoc.validateOnParse = True
xslDoc.loadXML txtXSL.Text
xmlDoc.loadXML txtXML.Text
Set template.stylesheet = xslDoc
Set processor = template.createProcessor
processor.input = xmlDoc
strParamVal = txtParamValue.Text
strParamName = txtParamName.Text
If strParamVal <> "" Then
processor.addParameter strParamName, strParamVal
End If
processor.Transform
If Check1.Value = 1 Then ' HTML Output
WebBrowser1.Visible = True
txtResult.Enabled = False
txtResult.Visible = False
WebBrowser1.Navigate "about:blank"
Set myDoc = WebBrowser1.Document
myDoc.Open
myDoc.Write processor.output
myDoc.Close
Else
WebBrowser1.Visible = False
txtResult.Visible = True
txtResult.Text = processor.output
End If
End If
End Sub
Private Sub txtXML_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
Dim lngID As Long
If Button = vbRightButton Then
lngID = mnuPopMenu(m_hMenu, Me.hwnd, TPM_RETURNCMD)
If lngID = 0 Then
MsgBox ("Canceled")
Else
If lngID = 100 Then SaveTheFile txtXML.Name
End If
End If
End Sub
Private Sub txtXSL_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
Dim lngID As Long
If Button = vbRightButton Then
lngID = mnuPopMenu(m_hMenu, Me.hwnd, TPM_RETURNCMD)
If lngID = 0 Then
MsgBox ("Canceled")
Else
If lngID = 100 Then SaveTheFile txtXSL.Name
End If
End If
End Sub
Basically
we load our form, hook CommonDialog "Load" methods into the "LOAD
XML" and "LOAD XSL" button events, and check our validateonParse
method to make sure the XML and XSL Documents are valid. Then we go ahead
and do our transform, using the createProcessor method of the IXSLProcessor
object ( Dim template As New MSXML2.XSLTemplate30, Dim
processor As MSXML2.IXSLProcessor) Here is the "meat" of
the code that actually does any parameter adding and calls the transform:
Set template.stylesheet = xslDoc
Set processor = template.createProcessor
processor.input = xmlDoc
strParamVal = txtParamValue.Text
strParamName = txtParamName.Text
If strParamVal <> "" Then
processor.addParameter strParamName, strParamVal
End If
processor.Transform
Then we check to see if HTML
output is checked, and decide where to send the output:
If Check1.Value = 1 Then ' HTML Output
WebBrowser1.Visible = True
txtResult.Enabled = False
txtResult.Visible = False
WebBrowser1.Navigate "about:blank"
Set myDoc = WebBrowser1.Document
myDoc.Open
myDoc.Write processor.output
myDoc.Close
Else
WebBrowser1.Visible = False
txtResult.Visible = True
txtResult.Text = processor.output
End If
The rest
of the code simply provides a hook into the content menu item that allows
a user to make a change to either document, and save it back to the filesystem,
calling the save routine:
Private Sub WriteFile(sFileNameAndPath
As String, sContent As String)
Dim fs As New Scripting.FileSystemObject
Dim f As Scripting.TextStream
If Not sFileNameAndPath = "" Then
Set f = fs.OpenTextFile(sFileNameAndPath, ForWriting, True, TristateUseDefault)
f.Write sContent
f.Close
MsgBox "File " & sFileNameAndPath & " Saved."
End If
End Sub
The code
for the Contents menu is in modCBMenuHelpers, which is included with the source
code download. This is pretty simple stuff, but it sure has saved me a lot
of time. I am sure you can think of some great ways to enhance this and add
new features. Hope you enjoy "Pete's Nifty VB XSLT Tester!
Download the code for this article
Peter Bromberg is an independent consultant specializing in distributed .NET solutionsa Senior
Programmer /Analyst at in Orlando and a co-developer of the NullSkull.com
developer website. He can be reached at info@eggheadcafe.com