XSLT FAQ
Fetching data in XSLTs using inline C#
How can I get more fine-grained control over database queries and the XML it generates?
Answer:
You can use “the power of LINQ” to do advanced queried in C1 by adding inline C# functions to your XSLT – it’s not very complicated given a simple sample – see below or download Fetching data in XSLTs using inline CSharp.xslt.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="xsl in msxsl csharp" xmlns:in="http://www.composite.net/ns/transformation/input/1.0" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:csharp="http://c1.composite.net/sample/csharp" xmlns="http://www.w3.org/1999/xhtml"> <xsl:template match="/"> <html> <head /> <body> <textarea> <xsl:copy-of select="csharp:GetLatestPages(5)" /> </textarea> </body> </html> </xsl:template> <msxsl:script implements-prefix="csharp" language="C#"> <msxsl:assembly name="System.Core"/> <msxsl:assembly name="System.Xml.Linq"/> <msxsl:assembly name="Composite"/> <msxsl:assembly name="Composite.Generated"/> <msxsl:using namespace="System.Collections.Generic"/> <msxsl:using namespace="System.Linq"/> <msxsl:using namespace="System.Xml.Linq"/> <msxsl:using namespace="Composite.Data"/> <![CDATA[ public static XPathNodeIterator GetLatestPages(int maxItemsToReturn) { using (DataConnection connection = new DataConnection()) { IEnumerable<XElement> pageElements = from dataItem in connection.Get<Composite.Data.Types.IPage>() orderby dataItem.ChangeDate descending select new XElement("Pageinfo", new XAttribute("Title", dataItem.Title), new XAttribute("ChangeDate", dataItem.ChangeDate), new XAttribute("Description", dataItem.Description)); XElement result = new XElement("Result", pageElements.Take(maxItemsToReturn)); return result.CreateNavigator().Select("/Pageinfo"); } } ]]> </msxsl:script> </xsl:stylesheet>
The C# code should be wrapped in a <![CDATA[ ... ]]>
block - this will allow for free use of otherwise XML reserved characters. Below the C# code is shown by itself.
public static XPathNodeIterator GetLatestPages(int maxItemsToReturn) { using (DataConnection connection = new DataConnection()) { IEnumerable<XElement> pageElements = from dataItem in connection.Get<Composite.Data.Types.IPage>() orderby dataItem.ChangeDate descending select new XElement("Pageinfo", new XAttribute("Title", dataItem.Title), new XAttribute("ChangeDate", dataItem.ChangeDate), new XAttribute("Abstract", dataItem.Description)); XElement result = new XElement("Result", pageElements.Take(maxItemsToReturn)); return result.CreateNavigator().Select("/Pageinfo"); } }
The sample above will generate <PageInfo />
elements based on the 5 most recently updates pages and select some data from them. The data fetching is done using C# and C1’s super intuitive DataConnection
. Performance is good and the preview pane will contain helpful error messages if there are errors in the C# code - and when it runs OK the preview gives you instant feedback on your code change.
To run the sample, do the following:
- Have at least one page in the system
- In C1 create a new XSLT Function
- Paste the Fetching data in XSLTs using inline CSharp.xslt code into the code editor
- Preview
You should note the following about the sample:
- This sample requires that the file
/bin/Composite.Generated.dll
exists. If this isn’t the case, remove the line<msxsl:assembly name="Composite.Generated"/>
. - The namespace
http://c1.composite.net/sample/xslt/csharp
is an arbitrary URI – change it to something which identifies you, so the author (company) can be identified. - The function
csharp:GetLatestPages(5)
is calling our C# code – in this sample we just do a raw copy of the XML returned from C#, so we can see it in the preview right away. - Inside the
<msxsl:script />
block, we define assemblies to load (DLL references), namespaces we are using and the actual C# function. - If the line
<msxsl:assembly name="Composite.Generated"/>
is present, you can reference any dynamic data type in the system. connection.Get<Composite.Data.Types.IPage>()
define what type of data we want. The sample grabsIPage
data – change the full name of the type to the type you want data from.- You can easily change ordering. Note that in
dataItem.ChangeDate
theChangedDate
part is the name of a field on a data type. - descending should be self-explanatory
- The
XElement
part is what defines the “XML template” for the data we are retrieving. pageElements.Take(maxItemsToReturn)
is what actually “executes” the data fetching– we are asking it to fetch (maximum) 5IPage
data records, read only 3 of the fields and then wrap this data it in the XML template defined above.- Finally we convert our
XElements
into something the XSLT processor can work with and return it.
To modify this to another data type, do the following:
- Change the namespace declaration (
http://c1.composite.net/sample/xslt/csharp
) - Change the data type (
Composite.Data.Types.IPage
) - Change the ordering field name
- Change the field names used the create the
XAttributes
- Change the element name of the
XElement ("Pageinfo")