Document Converter Framework Sample
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 Office SharePoint Server 2007 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 Office SharePoint Server 2007 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 Office SharePoint Server 2007. |
SampleData |
Contains sample XSL and XML files that the SampleOMUsage executable file requires. Upload these files to a server running Office SharePoint Server 2007, 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 Office SharePoint Server 2007, 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"">
<XslApplicatorConverterSettings Version=""1"" ><FilePlaceHolder
Url=""https://localhost/Documents/TransformEmployeesNew.xsl""
></FilePlaceHolder></XslApplicatorConverterSettings>
</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;
}
}
}
}
//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;
}
}
}
}
See Also
Concepts
Page Publishing Using Document Converters
Custom Document to Page Converters
Document to Page Converter Configuration Settings Schema
Document to Page Conversion Object Model