Click here to Skip to main content
15,867,316 members
Articles / Desktop Programming / ATL
Article

XML Transform Shell Extension

Rate me:
Please Sign up or sign in to vote.
4.08/5 (12 votes)
11 Oct 20033 min read 85K   1.6K   27   7
A shell extension to transform xml files against a stylesheet

Sample Image - xmlTransformer.jpg

Introduction

When working with XML and XSLT, it becomes tedious testing changes since there is no built-in support for executing the transformation. The MSXML SDK includes an XSLT command-line utility but unless the source and transforming stylesheet are in the same directory you must enter the paths for the inputs. You could write a script, as I have done many times, but this will need to be updated each time you change inputs or outputs.

This utility takes some of the pain out of writing and testing stylesheets. The output of the transformation is saved to disk and opened in its own process using notepad. This output is overwritten each time a transformation is done so you will need to 'Save As' to keep the document before closing notepad. I decided to use notepad because a transformation does not always result in valid XML.

There are a number of great articles that cover shell extensions quite well so I won't re-hash that information. I will cover simple transformations and parse errors using the DOMDocument in MSXML4.

Using the code

To use this utility, copy and register the dll. In Explorer, right click on an XML, XSL, or XSLT file to get the 'Transform with...' option. You will be prompted for an XSL/XSLT file to do the transformation. Notepad will display the results, being valid output or parser error information.

Any valid xml text can be loaded into a DOMDocument: XML, stylesheets and schemas. I have chosen to make this functionality available only to XML and stylesheets. To make this available to other file types, update the registrar script and rebuild. The following will include this option for XML schemas.

NoRemove xsdfile{
   NoRemove Shellex{
      NoRemove ContextMenuHandlers{
         RegSvrEx = s '{737E08D6-7EEA-4AD6-B15F-373B2BCDF5B7}'
}  }  }    

The Transformation

Both input files need to be loaded into a DOMDocument before we can perform a transformation. The steps to do this are simple: create a DOMDocument object, turn off asynchronous loading, load the file and check for parse errors.

// load the stylesheet into a DOM
MSXML2::IXMLDOMDocument2Ptr spStyleSheet;
spStyleSheet.CreateInstance(__uuidof(MSXML2::DOMDocument));
spStyleSheet->put_async(VARIANT_FALSE);

if( spStyleSheet->load(_variant_t(szStyleSheet)) == VARIANT_FALSE)
{
    ReportParseError(spStyleSheet->parseError, szStyleSheet);
    return S_FALSE;
}

If everything goes well, the XML is transformed using the transformNode method of the DOMDocument and the results are displayed. If there are parse errors, it is helpful to have as much information as we can.

Sample screenshot of parse error output

This is accomplished in ReportParseError. The DOMDocument exposes an interface to the parseError object. With this, we can get all error information, including the unparsed source text. I use the line and linepos properties to get a snippet of text surrounding the point where the parser stopped.

CString src = pParseError->srcText.GetBSTR();

int badChar = 0;
int maxLen = 0;

if(src.GetLength() < 120)
    maxLen = src.GetLength();
else
{
    // move to the correct line
    for(int x=0; x < pParseError->line - 1; x++)
        badChar = src.Find(_T("\n"), badChar);

    // get 120 characters starting at 60 before error
    badChar -= (60 - pParseError->linepos);
    maxLen = 120;
}
.
.
.
src.Mid(badChar, maxLen)

The parser will report an error on the first character found to be invalid. In most cases, this is a symptom of the real issue so we want to display text prior to that point. Something interesting to note is that srcTxt doesn't always contain all of the source. The SDK states that "this property returns an empty string if the error is caused by XML that is not well-formed and cannot be assigned to a specific line", but I had cases where it returns a partial string that doesn't contian enough text to see the actual error.

Points of Interest

This Shell Extension dll is an ATL project written using Visual Studio .NET and compiled for Unicode. To rebuild for ASCII, you will need to make changes using the conversion macros in order to interact with _bstr_t.

MSXML4 is a required dependency and can be downloaded, along with the SDK from MSDN.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralXML with Crystal Report Pin
Anonymous6-Apr-05 5:42
Anonymous6-Apr-05 5:42 
GeneralCan't build under VS.NET 2003 Pin
Doug Schmidt14-Oct-03 4:54
Doug Schmidt14-Oct-03 4:54 
GeneralRe: Can't build under VS.NET 2003 Pin
Doug Mitchell14-Oct-03 15:41
Doug Mitchell14-Oct-03 15:41 
GeneralSuggestions Pin
Patje13-Oct-03 3:56
Patje13-Oct-03 3:56 
GeneralRe: Suggestions Pin
Doug Mitchell13-Oct-03 5:20
Doug Mitchell13-Oct-03 5:20 
GeneralRe: Suggestions Pin
Patje13-Oct-03 5:23
Patje13-Oct-03 5:23 
GeneralRe: Suggestions Pin
memswiler7-Apr-04 0:46
memswiler7-Apr-04 0:46 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.