This is useful if you want to give the client the ability to design their own web part, format it in any way they like while pulling merge fields from xml. Not sure if that was very clear... let me try again. The web part will create XML that contains fields that can be used by XSL, which can be edited by the client within the properties of the web part to display the results in any way they choose.
Firstly we should declare a few variables and properties
public string feedXsl = "";
[WebBrowsable(true), WebPartStorage(Storage.Shared)]
[Personalizable(PersonalizationScope.Shared)]
[FriendlyNameAttribute("Xsl Template")]
public string FeedXsl
{
get { return feedXsl; }
set { feedXsl = value; }
}
This code above is what allows the user to edit the XSL via the web part properties. Note that this will only give the user a single line to enter all their XSL code. You can click on the ... to get a text area. In future, I'll describe how you can customise the web part properties area and place items like drop down boxes, buttons, text areas and other form items within the web part properties section.
Now that we have the variables and the properties out of the way, we can start coding the main section of the web part.
Within the Render Override, you need to firstly get the xml. In this example, I'll hard code the XML, but you will probably fill the XML with variables that you want to make available to the client for your particular web part.
protected override void Render(HtmlTextWriter writer)
{
try
{
#region Create the XML contents
string xmlfile = "<?xml version="1.0"?>";
xmlfile += "<UserDetails>";
xmlfile += "<UserInfo>";
xmlfile += "<Username>jsmith</Username>";
xmlfile += "<PreferredName>John Smith</PreferredName>";
xmlfile += "<Email>john.smith@example.com</Email>";
xmlfile += "</UserInfo>";
xmlfile += "<UserInfo>";
xmlfile += "<Username>jdoe</Username>";
xmlfile += "<PreferredName>Jane Doe</PreferredName>";
xmlfile += "<Email>jane.doe@example.com</Email>";
xmlfile += "</UserInfo>";
xmlfile += "</UserDetails>";
string strHTML = string.Empty;
XslCompiledTransform xslt = new XslCompiledTransform();
if (!((FeedXsl.ToString() == null) || (FeedXsl.ToString() == string.Empty) || (FeedXsl.ToString() == "")))
{
TextReader tr = new StringReader(FeedXsl.ToString().Trim());
XmlReader xreader = new XmlTextReader(tr);
strHTML = TransformXML(xmlfile, xreader);
}
else
{
strHTML = "Please associate a valid XSL Template";
}
writer.Write(SPEncode.HtmlDecode(strHTML).ToString());
}
catch (Exception ex)
{
// handle the exception (or just display it in the web part for your information, which I did below)
writer.Write(ex);
}
}
Within the Render Override, I called a function named TransformXML(xmlfile, xreader). Here's the code for that function:
private string TransformXML(string strXML, XmlReader strXSL)
{ //Create a IO Stream
System.IO.StringWriter oSW = new System.IO.StringWriter();
try
{
StringReader stream;
stream = new StringReader(strXML);
System.Xml.XmlTextReader oXR = new System.Xml.XmlTextReader(stream);
System.Xml.Xsl.XslCompiledTransform oXSLT = new System.Xml.Xsl.XslCompiledTransform();
oXSLT.Load(strXSL);
System.Xml.XPath.XPathDocument oXPath = new System.Xml.XPath.XPathDocument(oXR);
if (oXPath != null)
{
oXSLT.Transform(oXPath, null, oSW);
}
}
catch (Exception ex)
{
// there is an error with the transformation...
oSW = new StringWriter(new StringBuilder("You have an error in your XSL Template."));
}
return oSW.ToString();
}
Building the XSLT Code
When you compile the code and view the web part, you'll get the message You have an error in your XSL Template. This is because you haven't set up the XSL yet. View the web part properties and under Miscellaneous, you'll see a text field. Click on it then click on the ... button next to it.
In the window that pops up, enter your XSL code in there. I've included a simple sample below of what can go in here to transform the xml to html:
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema"
version="1.0" exclude-result-prefixes="xsl ddwrt msxsl rssaggwrt"
xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime"
xmlns:rssaggwrt="http://schemas.microsoft.com/WebParts/v3/rssagg/runtime"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt">
<xsl:template match="/">
<table>
<xsl:attribute name="width">100%</xsl:attribute>
<xsl:for-each select="UserDetails/UserInfo">
<tr>
<td>
<xsl:attribute name="align">center</xsl:attribute>
<div>
<b>
<xsl:value-of select="PreferredName"/>
</b>
</div>
<div>
<xsl:value-of select="Email"/>
</div>
</td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>