Possible to change SQL function <root> tag and XSLT <in:inputs> tag?

Topics: Community, General, XSLT
May 22, 2012 at 5:22 PM

Hello,

My company would like to move our CMS to Composite c1. I'm new to web development, so my apologizes if these questions are over the top.

1. Is it possible to change the <root> tag name that the SQL function uses? We would like to keep the XSLT files we're importing the same.

2. We'd also like to remove the <in:inputs>,<in:result>, and <root> tags in XSLT Functions.

3. What's the easiest way to import XSLT files into Composite? I've started by:

 - creating a new xslt function

 - replace the newly created function with the old, and rename the file extension name to .xsl.

This seems like a bad way to import XSLT files to Composite. I'm sure there's a more efficient way.

 

Any help would be greatly appreciated. Please let me know if any other information is needed. And I apologize again if my questions leave you scratching your heads.

May 23, 2012 at 2:58 AM
Edited May 23, 2012 at 2:58 AM

Your question is very descriptive and relevant, no need to apologize. 

On the top of my head I'd say that if you have legacy xslt that require the input xml document to be formatted in a very specific way, the only feasible routes are one of the following

  • change the legacy xslt - locate and expand on any XPaths which start with / by prefixing with /in:inputs/in:result/root - like this

    <!-- was -->
    <xsl:template match="/mydata">
    <!-- become  -->
    <xsl:template match="/in:inpute/in:result/root/mydata">
    
    <!-- was -->
    <xsl:template match="/">
    <!-- become -->
    <xsl:template match="/in:inpute/in:result/root/*">
    
    <!-- was -->
    <xsl:template match="/mydata/elm[@class='high']">
    <!-- become  -->
    <xsl:template match="/in:inpute/in:result/root/mydata/elm[@class='high']">
    
    <!-- etc. -->
    
  • write c# code which transform the input document to your desired structure and even more code which integrate with your existing xslt. This can be done in a fairly nice way, but it is a way more complex task than the first approach.

I guess I'm suggesting you go with option 1 - if your existing xslt mostly contain relative xpaths, you may just need to update one line per xslt. Create new xslt functions, use "Function Calls" to pull in your data (with /in:inpute/in:result/root and all), paste in your legacy xslt and fix paths. search for match="/ and select="/ and {/ and insert /in:inpute/in:result/root before /.

May 24, 2012 at 1:28 AM

Hi mawtex,

thanks for the quick response and solution. We actually have a couple hundred of these xslt stylesheets, and in them quite a few <xsl:value-of select> elements, which is why I was hoping there might be an easier way to change the <root> element that composite uses. I suppose I have my work cut out for me.

Also, can you confirm these isn't a simple way to import existing xslt stylesheets into composite? Will i need to create a new xslt function and copy the existing code from the original xslt? Or is there a simpler way (like directory I can throw them in)?

best regards,

phil

May 24, 2012 at 8:04 AM
Edited May 24, 2012 at 8:15 AM

Okay, in that case you could consider one of the following approaches:

A specific XSLT render function

You can keep using XSLT Functions to build up function calls etc. but instead of pasting in your legacy XSLT here, you keep the XSLT template super simple, just calling a new function, something like this:

 

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:in="http://www.composite.net/ns/transformation/input/1.0"
	xmlns:f="http://www.composite.net/ns/function/1.0"
	xmlns="http://www.w3.org/1999/xhtml"
	exclude-result-prefixes="xsl in f">

	<xsl:template match="/">
		<html>
			<head />
			<body>
				<f:function name="What you call this">
					<f:param name="xslt" value="some_xslt.xsl"/>
					<f:param name="input">
						<xsl:copy-of select="/in:inputs/in:result" />
					</f:param>
				</f:function>
			</body>
		</html>
	</xsl:template>

</xsl:stylesheet>

Here the call is effectively passed on to a new C1 Function - this should be one you write, which simply takes the XElement passed in named as "input" and apply the xslt file identified by parameter "xslt" onto this document. And return the result as XElement or IEnumerable<XElement>.

 

The nice thing about this approach is that you have excellent control and tooling and you can use the <xsl:copy-of select="/in:inputs/in:result" /> part to control what gets copied into your function.

A function-provider

XSLT Functions are handled by a function provider (a class implementing IFunctionProvider) and perhaps it would make sense to make some 'mini function provider' for this situation. If you download the source code for Composite C1 you can see different samples of classes implementing IFunctionProvider.

If I we to do it, I'd consider having all XSLT's in some folder structure and have the new function provider automatically create a new C1 Function for each XSLT file found. Each function would have an input parameter of type XContainer (allowing for either XDocument or XElement).

When a function executes, I'd grab the input document, remove the elements that the XSLT do not expect and then apply the XSLT file associated with the C1 Function on this document - and return the result.

You hay want to return the result in the form of a XhtmlDocument.

When calling such a function you would first locate it (naming associated with xslt file folder and name) and I would have to specify what input document to use for this function - this could be a function call to sql functions for instance.

The nice thing about this approach is that you need not create individual xslt's for each legacy xslt file you have - but there will be less configuration control and all the sweet features that XSLT Functions have are not in play.