Can’t Save your XSL/T File? Have You Closed Your XMLReader?

This week I have been working on a server control for a site I’m working on which reads in an XML file containing some product information and then using an XSL/T file transforms the output into correctly formatted XHTML.  One problem which occurred with the development of the server control was that a colleague of mine who was making modifications to the XSL/T File was unable to save the changes whilst viewing the resultant XHTML in their browser.  At first hand it would appear that it would be a permissions issue, and after much checking of the permissions to confirm they were correct, it was determined this was not the issue. 

My colleague had been able to save changes to the XSL/T after a short while of the page processing which immediately pointed me to the fact that the object was still holding onto the resources.  This was further confirmed with some investigation work which I did with the help of Craig Murphy

The XMLReader object which was reading and transforming the XML using the XSL/T was still holding on to the file and placing a lock on it because the XMLReader object doesn’t have a dispose method and so therefore despite my setting the object to nothing, until the garbage collector picked up the objects then the lock on the XSL/T file remained.  Craig suggested I call the XMLReader.Close() method after I had finished processing the XML, this was a method I wasn’t aware of and had not seen used in any example when I did my research into the changed syntax since version 2.0 of the .Net Framework. 

Here is a code snippet below of an example of how to use the XMLReader.Close() method to release the locks on resources:

Dim strProductDataXML As String = "ProductData.xml"
Dim strProductDataXSLT As String = "ProductDataTransform.xsl"
Dim sb As New StringBuilder()
Dim sw As New StringWriter(sb)

' Create XSL CompiledTransform to hold XSLT
Dim objXSL As New XslCompiledTransform
' Create XsltSettings to hold XSLT Settings
Dim objXSLTSettings As New XsltSettings(False, True)
' Create XmlReader Object to read the XSLT
Dim objXSLReader As XmlReader
' Create XMLReaderSettings Object For XMLReader Object which will read the XSLT
Dim objXSLReaderSettings As New XmlReaderSettings()
' Create XMLSecureResolver for use with the XSLCompiledTransform
Dim objXMLResolver As New XmlSecureResolver(New XmlUrlResolver(), "http://www.mysite.com/")

'Create Reader Object to read the XSL Transform
objXSLReader = XmlReader.Create(HttpContext.Current.Server.MapPath("~/XSLT/ProductDataTransform.xsl"), objXSLReaderSettings)
' Load the Transform in the XSLCompiledTransform Object, Provide the settings and resolver objects
objXSL.Load(objXSLReader, objXSLTSettings, objXMLResolver)

' Set the Source of the ProductData XML File to be transformed
Dim xmlSource As New XmlTextReader(HttpContext.Current.Server.MapPath("~/XML/ProductData.xml"))
Dim xPathDoc As New XPathDocument(xmlSource)

' Call the close method on the XMLTextReader to release all resources which is attached too.
xmlSource.Close()

' Perform the Transformation and output it to a stringwriter object
objXSL.Transform(xPathDoc, Nothing, sw)
' Call the close method on the XSLReader to release all resources which is attached too.
objXSLReader.Close()

' Set all objects to Nothing to allow the Garbage Collector to remove them
strProductDataXML = Nothing
strProductDataXSLT = Nothing
objXSL = Nothing
objXSLTSettings = Nothing
objXSLReader = Nothing
objXSLReaderSettings = Nothing
objXMLResolver = Nothing
xmlSource = Nothing
xPathDoc = Nothing

' Return the transformed string
Return sb.ToString()

Now that the XMLReader is closed and has released all of the objects holding on to it, the XSL/T file can be edited and changed without having to wait for the Garbage Collector to remove the objects and release the locks.

Leave a Reply

Your email address will not be published. Required fields are marked *