Document Converter Framework Sample (ECM)

Applies to: SharePoint Server 2010

This sample is composed of two related samples and supporting files that demonstrate the document converter framework, including a sample converter and Smart Client Authoring object model usage.

Note

This sample includes code intended to be saved into individual files and organized into a project. This topic describes the sample file structure and includes a procedure for saving sections of the code sample into the appropriate files and then building and running the samples.

Requirements

Before compiling and running the samples, verify that the Document Converter Load Balancer service and the Document Conversions Launcher service are turned on.

The Feature folder contains files (listed as SampleXSLTApplicatorConverterFeatureElement and feature XML files in the Code section of this topic) that are needed to run the converter on an Office SharePoint Server 2007 computer.

The SmartClientAuthoringOM sample requires that the sample converter code (found in the XsltApplicator folder in the downloadable sample) be installed on an SharePoint Server 2010 server computer.

Ensure that the sample XSL and XML files included in the SampleData folder in the sample download are uploaded to the document library in a Web site where the SharePoint Server 2010 Publishing Feature is turned on.

Demonstrates

The XsltApplicator sample demonstrates a Smart Client Authoring converter that applies an XSL transform to an XML file.

The SampleOMUsage sample demonstrates the Smart Client Authoring object model.

Folder

Description and Contents

Feature

Contains the SampleXSLTApplicatorConverterFeatureElement.xml and feature.xml files.

The contents of these files are reproduced later in this topic. These files are required to install the XsltApplicator sample on a server running SharePoint Server 2010.

SampleData

Contains sample XSL and XML files that the SampleOMUsage executable file requires. Upload these files to a server running SharePoint Server 2010, into a document library in a Web site where the Publishing Feature is turned on.

SampleOMUsage

Contains code that demonstrates the Smart Client Authoring object model. The code requires that the sample converter that is available in the XsltApplicator folder and files from the SampleData folder are installed on the server running SharePoint Server 2010, where you run this sample.

XsltApplicator

Contains code that demonstrates a Smart Client Authoring converter that applies an XSLT transformation to an XML file. This sample includes two code files (in subfolders in the SDK): XsltApplicator, which contains code for the converter, and SampleXslApplicatorSettings.ascx, which is the .ascx control that accompanies the converter and demonstrates how the IDocumentConverterControl interface is used.

Example

This example reproduces the contents of files in the Feature and SampleData folders that are included with the Microsoft Office SharePoint Server 2007 SDK.

The following Code section contains code for three sample files: two Microsoft Visual C# files and one .ascx user control. These are the program files and .ascx user control file stored in the SampleOMUsage and XsltApplicator folders of the sample code that is included with the Microsoft Office SharePoint Server 2007 SDK download.

The following XML files are provided in two files stored in the Feature folder of the downloadable sample: SampleXSLTApplicatorConverterFeatureElement.xml and feature.xml.

<!--
SampleXSLTApplicatorConverterFeatureElement.xml--!>
-  <Elements xmlns="https://schemas.microsoft.com/sharepoint/">
  <?xml version="1.0" encoding="utf-8" ?>
<DocumentConverter Id="{8E5A71E8-950E-474f-9946-EEF46B3D6600}"
  Name="Sample XSLT applicator" App="Microsoft.SDK.SharePointServices.Samples.SmartClientAuthoring.XsltApplicator.exe" 
  From="xml" To="html" ConverterUIPage="CreatePage.aspx" 
  ConverterSpecificSettingsUI="SampleXslApplicatorSettings.ascx" 
  ConverterSettingsForContentType="ConverterSettings.aspx" /> 
</Elements>

<!--feature.xml--!>
<?xml version="1.0" encoding="utf-8" ?> 
<Feature Id="{D043E33A-AF7C-4fd4-B913-7353AE8EF0FF}" Title="XSLT 
  Applicator Converter (Sample)" Description="Sample converter that 
  applies a specified XSLT to an XML file" Version="12.0.0.0" 
  Scope="WebApplication" xmlns="https://schemas.microsoft.com/sharepoint/">
<ElementManifests>
  <ElementManifest Location="SampleXSLTApplicatorConverterFeatureElement.xml" />
  </ElementManifest>

The following XML and XSL is provided in three files stored in the SampleData folder of the downloadable sample: employees.xml, TransformEmployees.xsl, and TransformEmployeesNew.xsl.

//employees.xml
<?xml version="1.0" encoding="utf-8" ?> 
- <employees>
  - <employee>
    <name>Nancy Davolio</name> 
    <photo>EMPID1</photo> 
    <hiredate>01-May-1992</hiredate> 
    <title type="Commission+">Sales Representative</title> 
    <region>WA</region> 
    </employee>
  - <employee>
    <name>Andrew Fuller</name> 
    <photo>EMPID2</photo> 
    <hiredate>14-Aug-1992</hiredate> 
    <title type="Salaried">Vice President, Sales</title> 
    <region>WA</region> 
    </employee>
  </employees>

<!--TransformEmployees.xsl--!>
<?xml version="1.0" encoding="utf-8" ?>
- <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
- <!-- 
This XSLT style sheet is used to transform the employee_data.xml 
file to a simple list like format. It is passed as an argument to the 
VBScript transformFile procedure in the default.htm file.
  -->
  <xsl:output method="html" />
  - <xsl:template match="/">
    - <html>
      - <head>
          <title>The XSLT list style sheet</title> 
        </head>
      - <body>
        - <table border="0" cellpadding="10">
          - <tr>
              <th align="left">Name</th> 
              <th align="left">Region</th> 
              <th align="left">Hire Date</th> 
              <th align="left">Compensation</th> 
              <th align="left">Title</th> 
            </tr>
           - <xsl:apply-templates select="/employees/employee">
              <xsl:sort select="name" /> 
             </xsl:apply-templates>
           </table>

  <p /> 
      </body>
    </html>
  </xsl:template>
- <!--  Outputs the child elements of the employees element.  -->
  - <xsl:template match="employee">
    - <tr>
      - <td>
          <xsl:value-of select="name" />
        </td>
      - <td>
          <xsl:value-of select="region" />
       </td>
      - <td>
          <xsl:value-of select="hiredate" />
       </td>
      - <td>
          <xsl:value-of select="title/@type" />
       </td>
      - <td>
          <xsl:value-of select="title" />
       </td>
    </tr>
    </xsl:template>
  </xsl:stylesheet>

//TransformEmployeesNew.xsl
<?xml version="1.0" encoding="utf-8" ?> 
- <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
- <!--  This XSLT style sheet is used to transform the employee_data.xml 
file to a simple list-like format. It is passed as an argument to the      
VBScript transformFile procedure in the default.htm file. --> 
<xsl:output method="html" /> 
  - <xsl:template match="/">
    - <html>
      - <head>
        <title>The XSLT list style sheet</title> 
        </head>
      - <body>
        - <table border="2" cellpadding="5">
          - <tr>
              <th align="left">Name</th> 
              <th align="left">Region</th> 
              <th align="left">Hire Date</th> 
              <th align="left">Compensation</th> 
              <th align="left">Title</th> 
            </tr>
             - <xsl:apply-templates select="/employees/employee">
                 <xsl:sort select="name" /> 
              </xsl:apply-templates>
           </table>

            <p /> 
        </body>
    </html>
  </xsl:template>
  - <!--  Outputs the child elements of the employees element. -->
    - <xsl:template match="employee">
      - <tr>
           - <td>
                <xsl:value-of select="name" /> 
             </td>
           - <td>
               <xsl:value-of select="region" /> 
             </td>
           - <td>
                <xsl:value-of select="hiredate" /> 
             </td>
            - <td>
              <xsl:value-of select="title/@type" /> 
              </td>
            - <td>
                <xsl:value-of select="title" /> 
              </td>
          </tr>
      </xsl:template>
  </xsl:stylesheet>
[C#]
//Sample object model usage code sample
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Xsl;

using Microsoft.SharePoint.Publishing;
using Microsoft.SharePoint;

namespace Microsoft.SDK.SharePointServices.Samples.SmartClientAuthoring
{

    class OmUsageSample
    {
        // Sample names.
        private const string siteName = "https://localhost";
        private const string fileToConvert = "Documents/employees.xml";
        private const string newPageNameStandard = "ConvertedPageStandard.aspx";
        private const string newPageNameNonStandard = "ConvertedPageCustomSettings.aspx";

        // Converter ID determines which converter to use for the conversion.
        // This converter ID matches the one defined by the 
        // SampleXSLTApplicatorConverterFeatureElement.xml file.
        private static Guid transformerId = new Guid("8E5A71E8-950E-474f-9946-EEF46B3D6600");

        // Demonstrates to handle DocumentToPublishingPageConversionException.
        static void HandleWarnings(DocumentToPublishingPageConversionException ex, 
        ref PublishingPage convertedPage)
        {

            if (ex.TransformedPage != null)

            {

                if (!String.IsNullOrEmpty(ex.TransformWarnings))

                {

                    Console.WriteLine("Conversion encountered issues: 
                    {0}", ex.TransformWarnings);
                }
                else
                {
                    Console.WriteLine("Conversion encountered issues: 
                   {0}", ex.ToString());

                }

                Console.WriteLine("continuing with created page");
                convertedPage = ex.TransformedPage;
            }
            else
            {
                Console.WriteLine("Conversion failed: {0}", 
                ex.ToString());
                convertedPage = null;
            }
        }
 
        // Convert a single document using the Sample XSLT Applicator 
        // Converter three times:
        // 1. With standard settings
        // 2. By running an update from the source document
        // 3. With nonstandard settings, demonstrating how to 
        // programmatically specify a different XSLT to apply
        static void Main(string[] args)
        {
            using (SPSite docSite = new SPSite(siteName))
            using (SPWeb docWeb = docSite.OpenWeb())
            {
                SPFile docFile = docWeb.GetFile(siteName + "/" + 
                fileToConvert);

                // Assumes the Publishing Feature is turned on in the 
                // site where the source document is.
                PublishingWeb pubWeb = PublishingWeb.GetPublishingWeb(docWeb);
                PublishingPageCollection pages = pubWeb.GetPublishingPages();
                PublishingPage convertedPage = null;

                Console.WriteLine("Starting initial conversion...");

                try
                {
                    convertedPage = pages.Add(newPageNameStandard, 
                    docFile, transformerId, PageConversionPriority.Immediately);
                }
                catch (DocumentToPublishingPageConversionException ex)
                {
                    HandleWarnings(ex, ref convertedPage);
                }

                // Exit if this failed.
                if (convertedPage == null)
                {
                    Console.WriteLine("initial conversion failed");
                    return;
                }

                Console.WriteLine("initial conversion done, starting update...");
                try
                {
                    convertedPage.UpdateContentFromSourceDocument(PageConversionPriority.Immediately);
                }
                catch (DocumentToPublishingPageConversionException ex)
                {
                    HandleWarnings(ex, ref convertedPage);
                }
 
                // Exit if this failed.
                if (convertedPage == null)
                {
                    Console.WriteLine("update failed");
                    return;
                }

                Console.WriteLine("Starting conversion with nonstandard settings...");
                
                // XML fragment sets items such as the layout to use (which is an ID that can be 
                // enumerated from the PublishingWeb.GetAvailablePageLayouts), and the fields specified by ID 
                // (the ID being set in the page layout). The provided defaults work only for a basic default installation
                // and may have to be adjusted to the feature set/page layouts/fields that are installed on your computer.
                string nonStandardSettings =
                    @"<rca:RCAuthoringProperties xmlns:rca=""urn:sharePointPublishingRcaProperties"">
                         <rca:Converter rca:guid=""" + transformerId.ToString() + @""">
                             <rca:property rca:type=""SelectedPageLayout"">24</rca:property>
                             <rca:property rca:type=""SelectedPageField"">f55c4d88-1f2e-4ad9-aaa8-819af4ee7ee8</rca:property>
                             <rca:property rca:type=""SelectedStylesField"">a932ec3f-94c1-48b1-b6dc-41aaa6eb7e54</rca:property>
                             <rca:property rca:type=""ConverterSpecificSettings"">
                                &lt;XslApplicatorConverterSettings Version=""1"" &gt;&lt;FilePlaceHolder 
                                        Url=""https://localhost/Documents/TransformEmployeesNew.xsl""
                                &gt;&lt;/FilePlaceHolder&gt;&lt;/XslApplicatorConverterSettings&gt;
                             </rca:property>
                         </rca:Converter>

                     </rca:RCAuthoringProperties>";

                try
                {
                    convertedPage = pages.Add(newPageNameNonStandard, docFile, transformerId, nonStandardSettings, PageConversionPriority.Immediately);
                }
                catch (DocumentToPublishingPageConversionException ex)
                {
                    HandleWarnings(ex, ref convertedPage);
                }

                // Exit if this failed.
                if (convertedPage == null)
                {
                    Console.WriteLine("nonstandard conversion failed");
                    return;
                }
                Console.WriteLine("all conversions finished successfully");
            }
        }
    }
}

//XsltApplicator code sample
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Xsl;
using System.IO;
using System.Reflection;
 
namespace Microsoft.SDK.SharePointServices.Samples.SmartClientAuthoring.XsltApplicator
{
    class XsltApplicator
    {
        #region Argument Handling Data
 
        private enum ArgumentCode
        {
            Help,
            InputFile,
            OutputFile,
            LogFile,
            ConfigFile
        }
 
        private struct ArgumentPair 
        {
            public ArgumentPair(ArgumentCode c, string s)
            {
                this.argType = c;
                this.argFlagString = s;
            }
 
            public ArgumentCode argType;
            public string       argFlagString;
        }
 
        private static ArgumentPair[] PossibleArguments = new ArgumentPair[] {
            new ArgumentPair(ArgumentCode.Help, "-?"),
            new ArgumentPair(ArgumentCode.Help, "-help"),
            new ArgumentPair(ArgumentCode.InputFile, "-in"),
            new ArgumentPair(ArgumentCode.OutputFile, "-out"),
            new ArgumentPair(ArgumentCode.LogFile, "-log"),
            new ArgumentPair(ArgumentCode.ConfigFile, "-config"),
        };
 
        private static Dictionary<ArgumentCode, string> actualArguments = new Dictionary<ArgumentCode, string>();
 
        #endregion
 
        /// <summary>
        /// Node names that appear in the web.config XML file
        /// </summary>
        private const string FilePlaceHolderElementName = "FilePlaceHolder";
 
 
        /// <summary>
        /// Prints out the usage help to the console.
        /// </summary>
        static void PrintUsage()
        {
            Console.WriteLine("Usage: {0} -in <inputfilename> -out <outputfilename> -config <configfilename> [-log <logfilename>]", 
                              Assembly.GetExecutingAssembly().ManifestModule.Name);
        }
 
        static void Log(string logString)
        {
            if (!String.IsNullOrEmpty(logString) &&
                actualArguments.ContainsKey(ArgumentCode.LogFile) && 
                !String.IsNullOrEmpty(actualArguments[ArgumentCode.LogFile]))
            {
                System.IO.FileInfo fileInfo = new System.IO.FileInfo(actualArguments[ArgumentCode.LogFile]);
 
                if (fileInfo != null)
                {
                    System.IO.TextWriter applicationLog = null;
 
                    if (fileInfo.Exists)
                    {
                        applicationLog = fileInfo.AppendText();
                    }
                    else
                    {
                        applicationLog = fileInfo.CreateText();
                    }
 
                    if (applicationLog != null)
                    {
                        applicationLog.WriteLine(logString);
 
                        applicationLog.Flush();
                        applicationLog.Close();
                    }
                }
            }
 
            if (!String.IsNullOrEmpty(logString))
            {
                Console.WriteLine(logString);
            }
        }
 
 
        static void Main(string[] args)
        {
            #region Argument Handling Code
            // read arguments
            for (int i = 0; i< args.Length; i++)
            {
                bool argumentValid = false;
                foreach (ArgumentPair ap in PossibleArguments)
                {
                    if (String.Compare(ap.argFlagString, args[i], StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        switch (ap.argType)
                        {
                            case ArgumentCode.Help:
                                PrintUsage();
                                return;
 
                            case ArgumentCode.InputFile:
                            case ArgumentCode.OutputFile:
                            case ArgumentCode.ConfigFile:
                            case ArgumentCode.LogFile:
                                if (i + 1 < args.Length)
                                {
                                    actualArguments[ap.argType] = args[i + 1];
                                    i++;
                                    argumentValid = true;
                                }
                                break;                            
                        }
                        break;
                    }
                }
 
                if (!argumentValid)
                {
                    Console.WriteLine("unknown argument {0}", args[i]);
                    PrintUsage();
                    return;
                }
            }
 
            // validate arguments
            if (!actualArguments.ContainsKey(ArgumentCode.InputFile) || 
                String.IsNullOrEmpty(actualArguments[ArgumentCode.InputFile]) ||
                !actualArguments.ContainsKey(ArgumentCode.OutputFile) ||
                String.IsNullOrEmpty(actualArguments[ArgumentCode.OutputFile]) ||
                !actualArguments.ContainsKey(ArgumentCode.ConfigFile) ||
                String.IsNullOrEmpty(actualArguments[ArgumentCode.ConfigFile]))
            {
                Console.WriteLine("required argument missing");
                PrintUsage();
                return;
            }
 
            #endregion
 
            try
            {
                // Read the config file
                XmlDocument xd = new XmlDocument();
                using (FileStream fs = new FileStream(actualArguments[ArgumentCode.ConfigFile], FileMode.Open, FileAccess.Read))
                using (StreamReader sr = new StreamReader(fs))
                {
                    String configData = sr.ReadToEnd();
                    xd.LoadXml(configData);
                }
 
                // Now find the FilePlaceHolder element that contains the XSL to apply.
                string xpathQuery = "//" + FilePlaceHolderElementName;
                XmlNodeList nodes = xd.SelectNodes(xpathQuery);
 
                if (nodes.Count < 1)
                {
                    Log("The config file does not contain the encoded XSL file to apply");
 
                    System.Environment.ExitCode = 1;
                    return;
                }
                
                // Get the xsl file as a byte array.
                byte[] xslBytes = System.Convert.FromBase64String(nodes[0].InnerXml);
 
                // Convert the byte array to a string.
                // The XSL should be UTF8 encoded.
                Decoder d = Encoding.UTF8.GetDecoder();
                int charLen = d.GetCharCount(xslBytes, 0, xslBytes.GetLength(0));

                char[] chars = new char[charLen];
                // Extract the characters to the character array.
                d.GetChars(xslBytes, 0, xslBytes.GetLength(0), chars, 0);
 
                // Convert the XSL to a string for convenience.
                string xsl = new string(chars);
 
                // Now read the XSL. 
                using (StringReader str = new StringReader(xsl))
                using (XmlTextReader xr = new XmlTextReader(str))
                {
                    // Build the XSL transformation object.
                    System.Xml.Xsl.XslCompiledTransform transform = new System.Xml.Xsl.XslCompiledTransform();
                    transform.Load(xr);
 
                    // Finally, perform the transformation.
                    transform.Transform(actualArguments[ArgumentCode.InputFile], actualArguments[ArgumentCode.OutputFile]);
                }
 
            }
            catch (System.Exception e)
            {
                Log(e.ToString());
                return;
            }
        }
    }
}
 
'Sample object model usage code sample
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Xml
Imports System.Xml.Xsl

Imports Microsoft.SharePoint.Publishing
Imports Microsoft.SharePoint

Namespace Microsoft.SDK.SharePointServices.Samples.SmartClientAuthoring

    Friend Class OmUsageSample
        ' Sample names.
        Private Const siteName As String = "https://localhost"
        Private Const fileToConvert As String = "Documents/employees.xml"
        Private Const newPageNameStandard As String = "ConvertedPageStandard.aspx"
        Private Const newPageNameNonStandard As String = "ConvertedPageCustomSettings.aspx"

        ' Converter ID determines which converter to use for the conversion.
        ' This converter ID matches the one defined by the 
        ' SampleXSLTApplicatorConverterFeatureElement.xml file.
        Private Shared transformerId As New Guid("8E5A71E8-950E-474f-9946-EEF46B3D6600")

        ' Demonstrates to handle DocumentToPublishingPageConversionException.
        Private Shared Sub HandleWarnings(ByVal ex As DocumentToPublishingPageConversionException, ByRef convertedPage As PublishingPage)

            If ex.TransformedPage IsNot Nothing Then


                If Not String.IsNullOrEmpty(ex.TransformWarnings) Then


                    Console.WriteLine("Conversion encountered issues: {0}", ex.TransformWarnings)
                Else
                    Console.WriteLine("Conversion encountered issues: {0}", ex.ToString())

                End If

                Console.WriteLine("continuing with created page")
                convertedPage = ex.TransformedPage
            Else
                Console.WriteLine("Conversion failed: {0}", ex.ToString())
                convertedPage = Nothing
            End If
        End Sub

        ' Convert a single document using the Sample XSLT Applicator 
        ' Converter three times:
        ' 1. With standard settings
        ' 2. By running an update from the source document
        ' 3. With nonstandard settings, demonstrating how to 
        ' programmatically specify a different XSLT to apply
        Shared Sub Main(ByVal args() As String)
            Using docSite As New SPSite(siteName)
                Using docWeb As SPWeb = docSite.OpenWeb()
                    Dim docFile As SPFile = docWeb.GetFile(siteName & "/" & fileToConvert)

                    ' Assumes the Publishing Feature is turned on in the 
                    ' site where the source document is.
                    Dim pubWeb As PublishingWeb = PublishingWeb.GetPublishingWeb(docWeb)
                    Dim pages As PublishingPageCollection = pubWeb.GetPublishingPages()
                    Dim convertedPage As PublishingPage = Nothing

                    Console.WriteLine("Starting initial conversion...")

                    Try
                        convertedPage = pages.Add(newPageNameStandard, docFile, transformerId, PageConversionPriority.Immediately)
                    Catch ex As DocumentToPublishingPageConversionException
                        HandleWarnings(ex, convertedPage)
                    End Try

                    ' Exit if this failed.
                    If convertedPage Is Nothing Then
                        Console.WriteLine("initial conversion failed")
                        Return
                    End If

                    Console.WriteLine("initial conversion done, starting update...")
                    Try
                        convertedPage.UpdateContentFromSourceDocument(PageConversionPriority.Immediately)
                    Catch ex As DocumentToPublishingPageConversionException
                        HandleWarnings(ex, convertedPage)
                    End Try

                    ' Exit if this failed.
                    If convertedPage Is Nothing Then
                        Console.WriteLine("update failed")
                        Return
                    End If

                    Console.WriteLine("Starting conversion with nonstandard settings...")

                    ' XML fragment sets items such as the layout to use (which is an ID that can be 
                    ' enumerated from the PublishingWeb.GetAvailablePageLayouts), and the fields specified by ID 
                    ' (the ID being set in the page layout). The provided defaults work only for a basic default installation
                    ' and may have to be adjusted to the feature set/page layouts/fields that are installed on your computer.
                    Dim nonStandardSettings As String = "<rca:RCAuthoringProperties xmlns:rca=""urn:sharePointPublishingRcaProperties"">" &
                        ControlChars.CrLf & "                         <rca:Converter rca:guid=""" & transformerId.ToString() & """>" &
                        ControlChars.CrLf & "                             <rca:property rca:type=""SelectedPageLayout"">24</rca:property>" &
                        ControlChars.CrLf & "                             <rca:property rca:type=""SelectedPageField"">f55c4d88-1f2e-4ad9-aaa8-819af4ee7ee8</rca:property>" &
                        ControlChars.CrLf & "                             <rca:property rca:type=""SelectedStylesField"">a932ec3f-94c1-48b1-b6dc-41aaa6eb7e54</rca:property>" &
                        ControlChars.CrLf & "                             <rca:property rca:type=""ConverterSpecificSettings"">" &
                        ControlChars.CrLf & "                                &lt;XslApplicatorConverterSettings Version=""1"" &gt;&lt;FilePlaceHolder " &
                        ControlChars.CrLf & "                                        Url=""https://localhost/Documents/TransformEmployeesNew.xsl""" &
                        ControlChars.CrLf & "                                &gt;&lt;/FilePlaceHolder&gt;&lt;/XslApplicatorConverterSettings&gt;" &
                        ControlChars.CrLf & "                             </rca:property>" &
                        ControlChars.CrLf & "                         </rca:Converter>" &
                        ControlChars.CrLf &
                        ControlChars.CrLf & "                     </rca:RCAuthoringProperties>"

                    Try
                        convertedPage = pages.Add(newPageNameNonStandard,
                                                  docFile,
                                                  transformerId,
                                                  nonStandardSettings,
                                                  PageConversionPriority.Immediately)
                    Catch ex As DocumentToPublishingPageConversionException
                        HandleWarnings(ex, convertedPage)
                    End Try

                    ' Exit if this failed.
                    If convertedPage Is Nothing Then
                        Console.WriteLine("nonstandard conversion failed")
                        Return
                    End If
                    Console.WriteLine("all conversions finished successfully")
                End Using
            End Using
        End Sub
    End Class
End Namespace


'XsltApplicator code sample
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Xml
Imports System.Xml.Xsl
Imports System.IO
Imports System.Reflection

Namespace Microsoft.SDK.SharePointServices.Samples.SmartClientAuthoring.XsltApplicator
    Friend Class XsltApplicator
#Region "Argument Handling Data"

        Private Enum ArgumentCode
            Help
            InputFile
            OutputFile
            LogFile
            ConfigFile
        End Enum

        Private Structure ArgumentPair
            Public Sub New(ByVal c As ArgumentCode, ByVal s As String)
                Me.argType = c
                Me.argFlagString = s
            End Sub

            Public argType As ArgumentCode
            Public argFlagString As String
        End Structure

        Private Shared PossibleArguments() As ArgumentPair =
            {New ArgumentPair(ArgumentCode.Help, "-?"),
             New ArgumentPair(ArgumentCode.Help, "-help"),
             New ArgumentPair(ArgumentCode.InputFile, "-in"),
             New ArgumentPair(ArgumentCode.OutputFile, "-out"),
             New ArgumentPair(ArgumentCode.LogFile, "-log"),
             New ArgumentPair(ArgumentCode.ConfigFile, "-config")}

        Private Shared actualArguments As New Dictionary(Of ArgumentCode, String)()

#End Region

        ''' <summary>
        ''' Node names that appear in the web.config XML file
        ''' </summary>
        Private Const FilePlaceHolderElementName As String = "FilePlaceHolder"


        ''' <summary>
        ''' Prints out the usage help to the console.
        ''' </summary>
        Private Shared Sub PrintUsage()
            Console.WriteLine("Usage: {0} -in <inputfilename> -out <outputfilename> -config <configfilename> [-log <logfilename>]",
                              System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name)
        End Sub

        Private Shared Sub Log(ByVal logString As String)
            If (Not String.IsNullOrEmpty(logString)) AndAlso
                actualArguments.ContainsKey(ArgumentCode.LogFile) AndAlso
                (Not String.IsNullOrEmpty(actualArguments(ArgumentCode.LogFile))) Then
                Dim fileInfo As New System.IO.FileInfo(actualArguments(ArgumentCode.LogFile))

                If fileInfo IsNot Nothing Then
                    Dim applicationLog As System.IO.TextWriter = Nothing

                    If fileInfo.Exists Then
                        applicationLog = fileInfo.AppendText()
                    Else
                        applicationLog = fileInfo.CreateText()
                    End If

                    If applicationLog IsNot Nothing Then
                        applicationLog.WriteLine(logString)

                        applicationLog.Flush()
                        applicationLog.Close()
                    End If
                End If
            End If

            If Not String.IsNullOrEmpty(logString) Then
                Console.WriteLine(logString)
            End If
        End Sub


        Shared Sub Main(ByVal args() As String)
            '            #Region "Argument Handling Code"
            ' read arguments
            For i As Integer = 0 To args.Length - 1
                Dim argumentValid As Boolean = False
                For Each ap As ArgumentPair In PossibleArguments
                    If String.Compare(ap.argFlagString, args(i), StringComparison.OrdinalIgnoreCase) = 0 Then
                        Select Case ap.argType
                            Case ArgumentCode.Help
                                PrintUsage()
                                Return

                            Case ArgumentCode.InputFile, ArgumentCode.OutputFile, ArgumentCode.ConfigFile, ArgumentCode.LogFile
                                If i + 1 < args.Length Then
                                    actualArguments(ap.argType) = args(i + 1)
                                    i += 1
                                    argumentValid = True
                                End If
                        End Select
                        Exit For
                    End If
                Next ap

                If Not argumentValid Then
                    Console.WriteLine("unknown argument {0}", args(i))
                    PrintUsage()
                    Return
                End If
            Next i

            ' validate arguments
            If (Not actualArguments.ContainsKey(ArgumentCode.InputFile)) OrElse
                String.IsNullOrEmpty(actualArguments(ArgumentCode.InputFile)) OrElse
                (Not actualArguments.ContainsKey(ArgumentCode.OutputFile)) OrElse
                String.IsNullOrEmpty(actualArguments(ArgumentCode.OutputFile)) OrElse
                (Not actualArguments.ContainsKey(ArgumentCode.ConfigFile)) OrElse
                String.IsNullOrEmpty(actualArguments(ArgumentCode.ConfigFile)) Then
                Console.WriteLine("required argument missing")
                PrintUsage()
                Return
            End If

            '            #End Region

            Try
                ' Read the config file
                Dim xd As New XmlDocument()
                Using fs As New FileStream(actualArguments(ArgumentCode.ConfigFile), FileMode.Open, FileAccess.Read)
                    Using sr As New StreamReader(fs)
                        Dim configData As String = sr.ReadToEnd()
                        xd.LoadXml(configData)
                    End Using
                End Using

                ' Now find the FilePlaceHolder element that contains the XSL to apply.
                Dim xpathQuery As String = "//" & FilePlaceHolderElementName
                Dim nodes As XmlNodeList = xd.SelectNodes(xpathQuery)

                If nodes.Count < 1 Then
                    Log("The config file does not contain the encoded XSL file to apply")

                    System.Environment.ExitCode = 1
                    Return
                End If

                ' Get the xsl file as a byte array.
                Dim xslBytes() As Byte = System.Convert.FromBase64String(nodes(0).InnerXml)

                ' Convert the byte array to a string.
                ' The XSL should be UTF8 encoded.
                Dim d As Decoder = Encoding.UTF8.GetDecoder()
                Dim charLen As Integer = d.GetCharCount(xslBytes, 0, xslBytes.GetLength(0))

                Dim chars(charLen - 1) As Char
                ' Extract the characters to the character array.
                d.GetChars(xslBytes, 0, xslBytes.GetLength(0), chars, 0)

                ' Convert the XSL to a string for convenience.
                Dim xsl As New String(chars)

                ' Now read the XSL. 
                Using str As New StringReader(xsl)
                    Using xr As New XmlTextReader(str)
                        ' Build the XSL transformation object.
                        Dim transform As New System.Xml.Xsl.XslCompiledTransform()
                        transform.Load(xr)

                        ' Finally, perform the transformation.
                        transform.Transform(actualArguments(ArgumentCode.InputFile), actualArguments(ArgumentCode.OutputFile))
                    End Using
                End Using

            Catch e As System.Exception
                Log(e.ToString())
                Return
            End Try
        End Sub
    End Class
End Namespace
//SampleXslApplicatorSettings.ascx user control.
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Xsl;
using System.IO;
using System.Reflection;
 
namespace Microsoft.SDK.SharePointServices.Samples.SmartClientAuthoring.XsltApplicator
{
    class XsltApplicator
    {
        #region Argument Handling Data
 
        private enum ArgumentCode
        {
            Help,
            InputFile,
            OutputFile,
            LogFile,
            ConfigFile
        }
 
        private struct ArgumentPair 
        {
            public ArgumentPair(ArgumentCode c, string s)
            {
                this.argType = c;
                this.argFlagString = s;
            }
 
            public ArgumentCode argType;
            public string       argFlagString;
        }
 
        private static ArgumentPair[] PossibleArguments = new ArgumentPair[] {
            new ArgumentPair(ArgumentCode.Help, "-?"),
            new ArgumentPair(ArgumentCode.Help, "-help"),
            new ArgumentPair(ArgumentCode.InputFile, "-in"),
            new ArgumentPair(ArgumentCode.OutputFile, "-out"),
            new ArgumentPair(ArgumentCode.LogFile, "-log"),
            new ArgumentPair(ArgumentCode.ConfigFile, "-config"),
        };
 
        private static Dictionary<ArgumentCode, string> actualArguments = new Dictionary<ArgumentCode, string>();
 
        #endregion
 
        /// <summary>
        /// Node names that appear in the configuration file
        /// </summary>
        private const string FilePlaceHolderElementName = "FilePlaceHolder";
 
 
        /// <summary>
        /// Prints out the usage help to the console.
        /// </summary>
        static void PrintUsage()
        {
            Console.WriteLine("Usage: {0} -in <inputfilename> -out <outputfilename> -config <configfilename> [-log <logfilename>]", 
                              Assembly.GetExecutingAssembly().ManifestModule.Name);
        }
 
        static void Log(string logString)
        {
            if (!String.IsNullOrEmpty(logString) &&
                actualArguments.ContainsKey(ArgumentCode.LogFile) && 
                !String.IsNullOrEmpty(actualArguments[ArgumentCode.LogFile]))
            {
                System.IO.FileInfo fileInfo = new System.IO.FileInfo(actualArguments[ArgumentCode.LogFile]);
 
                if (fileInfo != null)
                {
                    System.IO.TextWriter applicationLog = null;
 
                    if (fileInfo.Exists)
                    {
                        applicationLog = fileInfo.AppendText();
                    }
                    else
                    {
                        applicationLog = fileInfo.CreateText();
                    }
 
                    if (applicationLog != null)
                    {
                        applicationLog.WriteLine(logString);
 
                        applicationLog.Flush();
                        applicationLog.Close();
                    }
                }
            }
 
            if (!String.IsNullOrEmpty(logString))
            {
                Console.WriteLine(logString);
            }
        }
 
 
        static void Main(string[] args)
        {
            #region Argument Handling Code
            // Read arguments.
            for (int i = 0; i< args.Length; i++)
            {
                bool argumentValid = false;
                foreach (ArgumentPair ap in PossibleArguments)
                {
                    if (String.Compare(ap.argFlagString, args[i], StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        switch (ap.argType)
                        {
                            case ArgumentCode.Help:
                                PrintUsage();
                                return;
 
                            case ArgumentCode.InputFile:
                            case ArgumentCode.OutputFile:
                            case ArgumentCode.ConfigFile:
                            case ArgumentCode.LogFile:
                                if (i + 1 < args.Length)
                                {
                                    actualArguments[ap.argType] = args[i + 1];
                                    i++;
                                    argumentValid = true;
                                }
                                break;                            
                        }
                        break;
                    }
                }
 
                if (!argumentValid)
                {
                    Console.WriteLine("unknown argument {0}", args[i]);
                    PrintUsage();
                    return;
                }
            }
 
            // Validate arguments.
            if (!actualArguments.ContainsKey(ArgumentCode.InputFile) || 
                String.IsNullOrEmpty(actualArguments[ArgumentCode.InputFile]) ||
                !actualArguments.ContainsKey(ArgumentCode.OutputFile) ||
                String.IsNullOrEmpty(actualArguments[ArgumentCode.OutputFile]) ||
                !actualArguments.ContainsKey(ArgumentCode.ConfigFile) ||
                String.IsNullOrEmpty(actualArguments[ArgumentCode.ConfigFile]))
            {
                Console.WriteLine("required argument missing");
                PrintUsage();
                return;
            }
 
            #endregion
 
            try
            {
                // Read the configuration file.
                XmlDocument xd = new XmlDocument();
                using (FileStream fs = new FileStream(actualArguments[ArgumentCode.ConfigFile], FileMode.Open, FileAccess.Read))
                using (StreamReader sr = new StreamReader(fs))
                {
                    String configData = sr.ReadToEnd();
                    xd.LoadXml(configData);
                }
 
                // Find the FilePlaceHolder element that contains the XSL to apply.
                string xpathQuery = "//" + FilePlaceHolderElementName;
                XmlNodeList nodes = xd.SelectNodes(xpathQuery);
 
                if (nodes.Count < 1)
                {
                    Log("The configuration file does not contain the encoded XSL file to apply");
 
                    System.Environment.ExitCode = 1;
                    return;
                }
                
                // Get the xsl file as a byte array.
                byte[] xslBytes = System.Convert.FromBase64String(nodes[0].InnerXml);
 
                // Convert the byte array to a string.
                // The XSL should be UTF8 encoded.
                Decoder d = Encoding.UTF8.GetDecoder();
                int charLen = d.GetCharCount(xslBytes, 0, xslBytes.GetLength(0));
                char[] chars = new char[charLen];
                // Extract the characters to the character array.
                d.GetChars(xslBytes, 0, xslBytes.GetLength(0), chars, 0);
 
                // Convert the XSL to a string for convenience.
                string xsl = new string(chars);
 
                // Now read the XSL. 
                using (StringReader str = new StringReader(xsl))
                using (XmlTextReader xr = new XmlTextReader(str))
                {
                    // Build the XSLT object.
                    System.Xml.Xsl.XslCompiledTransform transform = new System.Xml.Xsl.XslCompiledTransform();
                    transform.Load(xr);
 
                    // Finally, perform the transformation.
                    transform.Transform(actualArguments[ArgumentCode.InputFile], actualArguments[ArgumentCode.OutputFile]);
                }
 
            }
            catch (System.Exception e)
            {
                Log(e.ToString());
                return;
            }
        }
    }
}
'SampleXslApplicatorSettings.ascx user control.
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Xml
Imports System.Xml.Xsl
Imports System.IO
Imports System.Reflection

Namespace Microsoft.SDK.SharePointServices.Samples.SmartClientAuthoring.XsltApplicator
    Friend Class XsltApplicator
#Region "Argument Handling Data"

        Private Enum ArgumentCode
            Help
            InputFile
            OutputFile
            LogFile
            ConfigFile
        End Enum

        Private Structure ArgumentPair
            Public Sub New(ByVal c As ArgumentCode, ByVal s As String)
                Me.argType = c
                Me.argFlagString = s
            End Sub

            Public argType As ArgumentCode
            Public argFlagString As String
        End Structure

        Private Shared PossibleArguments() As ArgumentPair =
            {New ArgumentPair(ArgumentCode.Help, "-?"),
                New ArgumentPair(ArgumentCode.Help, "-help"),
             New ArgumentPair(ArgumentCode.InputFile, "-in"),
             New ArgumentPair(ArgumentCode.OutputFile, "-out"),
             New ArgumentPair(ArgumentCode.LogFile, "-log"),
             New ArgumentPair(ArgumentCode.ConfigFile, "-config")}

        Private Shared actualArguments As New Dictionary(Of ArgumentCode, String)()

#End Region

        ''' <summary>
        ''' Node names that appear in the configuration file
        ''' </summary>
        Private Const FilePlaceHolderElementName As String = "FilePlaceHolder"


        ''' <summary>
        ''' Prints out the usage help to the console.
        ''' </summary>
        Private Shared Sub PrintUsage()
            Console.WriteLine("Usage: {0} -in <inputfilename> -out <outputfilename> -config <configfilename> [-log <logfilename>]",
                              System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name)
        End Sub

        Private Shared Sub Log(ByVal logString As String)
            If (Not String.IsNullOrEmpty(logString)) AndAlso
                actualArguments.ContainsKey(ArgumentCode.LogFile) AndAlso
                (Not String.IsNullOrEmpty(actualArguments(ArgumentCode.LogFile))) Then
                Dim fileInfo As New System.IO.FileInfo(actualArguments(ArgumentCode.LogFile))

                If fileInfo IsNot Nothing Then
                    Dim applicationLog As System.IO.TextWriter = Nothing

                    If fileInfo.Exists Then
                        applicationLog = fileInfo.AppendText()
                    Else
                        applicationLog = fileInfo.CreateText()
                    End If

                    If applicationLog IsNot Nothing Then
                        applicationLog.WriteLine(logString)

                        applicationLog.Flush()
                        applicationLog.Close()
                    End If
                End If
            End If

            If Not String.IsNullOrEmpty(logString) Then
                Console.WriteLine(logString)
            End If
        End Sub


        Shared Sub Main(ByVal args() As String)
            '            #Region "Argument Handling Code"
            ' Read arguments.
            For i As Integer = 0 To args.Length - 1
                Dim argumentValid As Boolean = False
                For Each ap As ArgumentPair In PossibleArguments
                    If String.Compare(ap.argFlagString, args(i), StringComparison.OrdinalIgnoreCase) = 0 Then
                        Select Case ap.argType
                            Case ArgumentCode.Help
                                PrintUsage()
                                Return

                            Case ArgumentCode.InputFile, ArgumentCode.OutputFile, ArgumentCode.ConfigFile, ArgumentCode.LogFile
                                If i + 1 < args.Length Then
                                    actualArguments(ap.argType) = args(i + 1)
                                    i += 1
                                    argumentValid = True
                                End If
                        End Select
                        Exit For
                    End If
                Next ap

                If Not argumentValid Then
                    Console.WriteLine("unknown argument {0}", args(i))
                    PrintUsage()
                    Return
                End If
            Next i

            ' Validate arguments.
            If (Not actualArguments.ContainsKey(ArgumentCode.InputFile)) OrElse
                String.IsNullOrEmpty(actualArguments(ArgumentCode.InputFile)) OrElse
                (Not actualArguments.ContainsKey(ArgumentCode.OutputFile)) OrElse
                String.IsNullOrEmpty(actualArguments(ArgumentCode.OutputFile)) OrElse
                (Not actualArguments.ContainsKey(ArgumentCode.ConfigFile)) OrElse
                String.IsNullOrEmpty(actualArguments(ArgumentCode.ConfigFile)) Then
                Console.WriteLine("required argument missing")
                PrintUsage()
                Return
            End If

            '            #End Region

            Try
                ' Read the configuration file.
                Dim xd As New XmlDocument()
                Using fs As New FileStream(actualArguments(ArgumentCode.ConfigFile), FileMode.Open, FileAccess.Read)
                    Using sr As New StreamReader(fs)
                        Dim configData As String = sr.ReadToEnd()
                        xd.LoadXml(configData)
                    End Using
                End Using

                ' Find the FilePlaceHolder element that contains the XSL to apply.
                Dim xpathQuery As String = "//" & FilePlaceHolderElementName
                Dim nodes As XmlNodeList = xd.SelectNodes(xpathQuery)

                If nodes.Count < 1 Then
                    Log("The configuration file does not contain the encoded XSL file to apply")

                    System.Environment.ExitCode = 1
                    Return
                End If

                ' Get the xsl file as a byte array.
                Dim xslBytes() As Byte = System.Convert.FromBase64String(nodes(0).InnerXml)

                ' Convert the byte array to a string.
                ' The XSL should be UTF8 encoded.
                Dim d As Decoder = Encoding.UTF8.GetDecoder()
                Dim charLen As Integer = d.GetCharCount(xslBytes, 0, xslBytes.GetLength(0))
                Dim chars(charLen - 1) As Char
                ' Extract the characters to the character array.
                d.GetChars(xslBytes, 0, xslBytes.GetLength(0), chars, 0)

                ' Convert the XSL to a string for convenience.
                Dim xsl As New String(chars)

                ' Now read the XSL. 
                Using str As New StringReader(xsl)
                    Using xr As New XmlTextReader(str)
                        ' Build the XSLT object.
                        Dim transform As New System.Xml.Xsl.XslCompiledTransform()
                        transform.Load(xr)

                        ' Finally, perform the transformation.
                        transform.Transform(actualArguments(ArgumentCode.InputFile), actualArguments(ArgumentCode.OutputFile))
                    End Using
                End Using

            Catch e As System.Exception
                Log(e.ToString())
                Return
            End Try
        End Sub
    End Class
End Namespace

See Also

Concepts

Page Publishing Using SharePoint Document Converters (ECM)

Custom Document to Page Converters in SharePoint Server 2010 (ECM)

Document to Page Converter Configuration Settings Schema in SharePoint Server 2010 (ECM)

Document to Page Conversion Object Model (ECM)